Merge "audio: add API for querying the Ultrasound support"
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 1ac8482..9c98778 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;
@@ -72,22 +73,16 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
ATRACE_CALL();
- if (session == nullptr || requests == nullptr || numRequests < 1) {
- ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
- __FUNCTION__, session, numRequests, requests);
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
+ return captureTemplate(session, cbs, numRequests, requests, captureSequenceId);
+}
- if (session->isClosed()) {
- ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- if (captureSequenceId != nullptr) {
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
- }
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
-
- return session->capture(
- cbs, numRequests, requests, captureSequenceId);
+EXPORT
+camera_status_t ACameraCaptureSession_captureV2(
+ ACameraCaptureSession* session, /*optional*/ACameraCaptureSession_captureCallbacksV2* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ return captureTemplate(session, cbs, numRequests, requests, captureSequenceId);
}
EXPORT
@@ -97,22 +92,26 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
ATRACE_CALL();
- if (session == nullptr || requests == nullptr || numRequests < 1) {
- ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
- __FUNCTION__, session, numRequests, requests);
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
+ return captureTemplate(session, lcbs, numRequests, requests, captureSequenceId);
+}
- if (session->isClosed()) {
- ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- if (captureSequenceId) {
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
- }
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_captureV2(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ return captureTemplate(session, lcbs, numRequests, requests, captureSequenceId);
+}
- return session->capture(
- lcbs, numRequests, requests, captureSequenceId);
+EXPORT
+camera_status_t ACameraCaptureSession_setRepeatingRequestV2(
+ ACameraCaptureSession* session, /*optional*/ACameraCaptureSession_captureCallbacksV2* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ return setRepeatingRequestTemplate(session, cbs, numRequests, requests, captureSequenceId);
}
EXPORT
@@ -121,23 +120,10 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
ATRACE_CALL();
- if (session == nullptr || requests == nullptr || numRequests < 1) {
- ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
- __FUNCTION__, session, numRequests, requests);
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
-
- if (session->isClosed()) {
- ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- if (captureSequenceId) {
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
- }
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
-
- return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
+ return setRepeatingRequestTemplate(session, cbs, numRequests, requests, captureSequenceId);
}
+
EXPORT
camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
ACameraCaptureSession* session,
@@ -145,21 +131,18 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
ATRACE_CALL();
- if (session == nullptr || requests == nullptr || numRequests < 1) {
- ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
- __FUNCTION__, session, numRequests, requests);
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
+ return setRepeatingRequestTemplate(session, lcbs, numRequests, requests, captureSequenceId);
+}
- if (session->isClosed()) {
- ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- if (captureSequenceId) {
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
- }
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
- return session->setRepeatingRequest(lcbs, numRequests, requests, captureSequenceId);
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequestV2(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ return setRepeatingRequestTemplate(session, lcbs, numRequests, requests, captureSequenceId);
}
EXPORT
diff --git a/camera/ndk/NdkCameraCaptureSession.inc b/camera/ndk/NdkCameraCaptureSession.inc
new file mode 100644
index 0000000..258e20d
--- /dev/null
+++ b/camera/ndk/NdkCameraCaptureSession.inc
@@ -0,0 +1,70 @@
+/*
+ * 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 "impl/ACameraCaptureSession.h"
+
+#include <camera/NdkCameraCaptureSession.h>
+
+using namespace android;
+
+template <class CallbackType>
+camera_status_t captureTemplate(
+ ACameraCaptureSession* session,
+ /*optional*/CallbackType* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ if (captureSequenceId) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->capture(
+ cbs, numRequests, requests, captureSequenceId);
+}
+
+template <class CallbackType>
+camera_status_t setRepeatingRequestTemplate(
+ ACameraCaptureSession* session,
+ /*optional*/CallbackType* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ if (captureSequenceId) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->setRepeatingRequest(cbs, numRequests, requests, captureSequenceId);
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index dd652c7..7997768 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -26,8 +26,6 @@
#include "ACaptureRequest.h"
#include "ACameraCaptureSession.h"
-#include "ACameraCaptureSession.inc"
-
ACameraDevice::~ACameraDevice() {
mDevice->stopLooperAndDisconnect();
}
@@ -913,6 +911,7 @@
case kWhatOnError:
case kWhatSessionStateCb:
case kWhatCaptureStart:
+ case kWhatCaptureStart2:
case kWhatCaptureResult:
case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
@@ -985,6 +984,7 @@
}
case kWhatSessionStateCb:
case kWhatCaptureStart:
+ case kWhatCaptureStart2:
case kWhatCaptureResult:
case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
@@ -1004,6 +1004,7 @@
sp<CaptureRequest> requestSp = nullptr;
switch (msg->what()) {
case kWhatCaptureStart:
+ case kWhatCaptureStart2:
case kWhatCaptureResult:
case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
@@ -1055,6 +1056,35 @@
freeACaptureRequest(request);
break;
}
+ case kWhatCaptureStart2:
+ {
+ ACameraCaptureSession_captureCallback_startV2 onStart2;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onStart2);
+ if (!found) {
+ ALOGE("%s: Cannot find capture startV2 callback!", __FUNCTION__);
+ return;
+ }
+ if (onStart2 == nullptr) {
+ return;
+ }
+ int64_t timestamp;
+ found = msg->findInt64(kTimeStampKey, ×tamp);
+ if (!found) {
+ ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
+ return;
+ }
+ int64_t frameNumber;
+ found = msg->findInt64(kFrameNumberKey, &frameNumber);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, mId);
+ (*onStart2)(context, session.get(), request, timestamp, frameNumber);
+ freeACaptureRequest(request);
+ break;
+ }
case kWhatCaptureResult:
{
ACameraCaptureSession_captureCallback_result onResult;
@@ -1285,7 +1315,8 @@
ACameraCaptureSession_captureCallbacks* cbs) :
mSession(session), mRequests(requests),
mIsRepeating(isRepeating),
- mIsLogicalCameraCallback(false) {
+ mIsLogicalCameraCallback(false),
+ mIs2Callback(false) {
initCaptureCallbacks(cbs);
if (cbs != nullptr) {
@@ -1301,7 +1332,8 @@
ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
mSession(session), mRequests(requests),
mIsRepeating(isRepeating),
- mIsLogicalCameraCallback(true) {
+ mIsLogicalCameraCallback(true),
+ mIs2Callback(false) {
initCaptureCallbacks(lcbs);
if (lcbs != nullptr) {
@@ -1310,6 +1342,40 @@
}
}
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacksV2* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false),
+ mIs2Callback(true) {
+ initCaptureCallbacksV2(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true),
+ mIs2Callback(true) {
+ initCaptureCallbacksV2(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ mOnLogicalCameraCaptureFailed = lcbs->onLogicalCameraCaptureFailed;
+ }
+}
+
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
const int sequenceId, const int64_t lastFrameNumber) {
@@ -1536,7 +1602,6 @@
const CaptureResultExtras& resultExtras,
int64_t timestamp) {
binder::Status ret = binder::Status::ok();
-
sp<CameraDevice> dev = mDevice.promote();
if (dev == nullptr) {
return ret; // device has been closed
@@ -1551,11 +1616,14 @@
int sequenceId = resultExtras.requestId;
int32_t burstId = resultExtras.burstId;
+ int64_t frameNumber = resultExtras.frameNumber;
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
+ bool v2Callback = cbh.mIs2Callback;
ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_startV2 onStart2 = cbh.mOnCaptureStarted2;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1563,12 +1631,19 @@
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
- sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+ sp<AMessage> msg = nullptr;
+ if (v2Callback) {
+ msg = new AMessage(kWhatCaptureStart2, dev->mHandler);
+ msg->setPointer(kCallbackFpKey, (void*) onStart2);
+ } else {
+ msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+ msg->setPointer(kCallbackFpKey, (void *)onStart);
+ }
msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
msg->setInt64(kTimeStampKey, timestamp);
+ msg->setInt64(kFrameNumberKey, frameNumber);
dev->postSessionMsgAndCleanup(msg);
}
return ret;
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 344d964..17988fe 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -215,6 +215,7 @@
kWhatSessionStateCb, // onReady, onActive
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
+ kWhatCaptureStart2, // onCaptureStarted
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
@@ -294,11 +295,18 @@
const Vector<sp<CaptureRequest> >& requests,
bool isRepeating,
ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
-
- template <class T>
- void initCaptureCallbacks(T* cbs) {
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacksV2* cbs);
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs);
+ void clearCallbacks() {
mContext = nullptr;
mOnCaptureStarted = nullptr;
+ mOnCaptureStarted2 = nullptr;
mOnCaptureProgressed = nullptr;
mOnCaptureCompleted = nullptr;
mOnLogicalCameraCaptureCompleted = nullptr;
@@ -307,6 +315,24 @@
mOnCaptureSequenceCompleted = nullptr;
mOnCaptureSequenceAborted = nullptr;
mOnCaptureBufferLost = nullptr;
+ }
+
+ template <class T>
+ void initCaptureCallbacksV2(T* cbs) {
+ clearCallbacks();
+ if (cbs != nullptr) {
+ mContext = cbs->context;
+ mOnCaptureStarted2 = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
+ }
+ }
+
+ template <class T>
+ void initCaptureCallbacks(T* cbs) {
+ clearCallbacks();
if (cbs != nullptr) {
mContext = cbs->context;
mOnCaptureStarted = cbs->onCaptureStarted;
@@ -320,9 +346,11 @@
Vector<sp<CaptureRequest> > mRequests;
const bool mIsRepeating;
const bool mIsLogicalCameraCallback;
+ const bool mIs2Callback;
void* mContext;
ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_startV2 mOnCaptureStarted2;
ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 2b7f040..b0fd00c 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -811,6 +811,184 @@
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+/**
+ * The definition of camera capture start callback. The same as
+ * {@link ACameraCaptureSession_captureCallbacks#onCaptureStarted}, except that
+ * it has the frame number of the capture as well.
+ *
+ * @param context The optional application context provided by user in
+ * {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request that is starting. Note that this pointer points to a copy of
+ * capture request sent by application, so the address is different to what
+ * application sent but the content will match. This request will be freed by
+ * framework immediately after this callback returns.
+ * @param timestamp The timestamp when the capture is started. This timestamp will match
+ * {@link ACAMERA_SENSOR_TIMESTAMP} of the {@link ACameraMetadata} in
+ * {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted} callback.
+ * @param frameNumber the frame number of the capture started
+ */
+typedef void (*ACameraCaptureSession_captureCallback_startV2)(
+ void* context, ACameraCaptureSession* session,
+ const ACaptureRequest* request, int64_t timestamp, int64_t frameNumber);
+/**
+ * This has the same functionality as ACameraCaptureSession_captureCallbacks,
+ * with the exception that captureCallback_startV2 callback is
+ * used, instead of captureCallback_start, to support retrieving the frame number.
+ */
+typedef struct ACameraCaptureSession_captureCallbacksV2 {
+ /**
+ * Same as ACameraCaptureSession_captureCallbacks
+ */
+ void* context;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureStarted},
+ * except that it has the frame number of the capture added in the parameter
+ * list.
+ */
+ ACameraCaptureSession_captureCallback_startV2 onCaptureStarted;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureProgressed}.
+ */
+ ACameraCaptureSession_captureCallback_result onCaptureProgressed;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted}.
+ */
+ ACameraCaptureSession_captureCallback_result onCaptureCompleted;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureFailed}.
+ */
+ ACameraCaptureSession_captureCallback_failed onCaptureFailed;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureSequenceCompleted}.
+ */
+ ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureSequenceAborted}.
+ */
+ ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureBufferLost}.
+ */
+ ACameraCaptureSession_captureCallback_bufferLost onCaptureBufferLost;
+
+
+} ACameraCaptureSession_captureCallbacksV2;
+
+/**
+ * This has the same functionality as ACameraCaptureSession_logicalCamera_captureCallbacks,
+ * with the exception that an captureCallback_startV2 callback is
+ * used, instead of captureCallback_start, to support retrieving frame number.
+ */
+typedef struct ACameraCaptureSession_logicalCamera_captureCallbacksV2 {
+ /**
+ * Same as ACameraCaptureSession_captureCallbacks
+ */
+ void* context;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureStarted},
+ * except that it has the frame number of the capture added in the parameter
+ * list.
+ */
+ ACameraCaptureSession_captureCallback_startV2 onCaptureStarted;
+
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureProgressed}.
+ */
+ ACameraCaptureSession_captureCallback_result onCaptureProgressed;
+
+ /**
+ * Same as
+ * {@link ACameraCaptureSession_logicalCamera_captureCallbacks#onLogicalCaptureCompleted}.
+ */
+ ACameraCaptureSession_logicalCamera_captureCallback_result onLogicalCameraCaptureCompleted;
+
+ /**
+ * This callback is called instead of {@link onLogicalCameraCaptureCompleted} when the
+ * camera device failed to produce a capture result for the
+ * request.
+ *
+ * <p>Other requests are unaffected, and some or all image buffers from
+ * the capture may have been pushed to their respective output
+ * streams.</p>
+ *
+ * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+ * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+ *
+ * @see ALogicalCameraCaptureFailure
+ */
+ ACameraCaptureSession_logicalCamera_captureCallback_failed onLogicalCameraCaptureFailed;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureSequenceCompleted}.
+ */
+ ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureSequenceAborted}.
+ */
+ ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+
+ /**
+ * Same as {@link ACameraCaptureSession_captureCallbacks#onCaptureBufferLost}.
+ */
+ ACameraCaptureSession_captureCallback_bufferLost onCaptureBufferLost;
+
+} ACameraCaptureSession_logicalCamera_captureCallbacksV2;
+
+/**
+ * This has the same functionality as ACameraCaptureSession_capture, with added
+ * support for v2 of camera callbacks, where the onCaptureStarted callback
+ * adds frame number in its parameter list.
+ */
+camera_status_t ACameraCaptureSession_captureV2(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_captureCallbacksV2* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(33);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_logical_setRepeatingRequest, with added
+ * support for v2 of logical multi-camera callbacks where the onCaptureStarted
+ * callback adds frame number in its parameter list.
+ */
+camera_status_t ACameraCaptureSession_setRepeatingRequestV2(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_captureCallbacksV2* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(33);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_logical_capture, with added
+ * support for v2 of logical multi-camera callbacks where the onCaptureStarted callback
+ * adds frame number in its parameter list.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_captureV2(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(33);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_logical_setRepeatingRequest, with added
+ * support for v2 of logical multi-camera callbacks where the onCaptureStarted
+ * callback adds frame number in its parameter list.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequestV2(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacksV2* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(33);
+
__END_DECLS
#endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 2b630db..b3977ff 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -2,11 +2,15 @@
global:
ACameraCaptureSession_abortCaptures;
ACameraCaptureSession_capture;
+ ACameraCaptureSession_captureV2; # introduced=33
ACameraCaptureSession_logicalCamera_capture; # introduced=29
+ ACameraCaptureSession_logicalCamera_captureV2; # introduced=33
ACameraCaptureSession_close;
ACameraCaptureSession_getDevice;
ACameraCaptureSession_setRepeatingRequest;
+ ACameraCaptureSession_setRepeatingRequestV2; # introduced=33
ACameraCaptureSession_logicalCamera_setRepeatingRequest; # introduced=29
+ ACameraCaptureSession_logicalCamera_setRepeatingRequestV2; # introduced=33
ACameraCaptureSession_stopRepeating;
ACameraCaptureSession_updateSharedOutput; # introduced=28
ACameraDevice_close;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 9f63099..4cc1292 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -29,8 +29,6 @@
#include "ACaptureRequest.h"
#include "utils.h"
-#include "ACameraCaptureSession.inc"
-
#define CHECK_TRANSACTION_AND_RET(remoteRet, status, callName) \
if (!remoteRet.isOk()) { \
ALOGE("%s: Transaction error during %s call %s", __FUNCTION__, callName, \
@@ -910,6 +908,7 @@
case kWhatOnError:
case kWhatSessionStateCb:
case kWhatCaptureStart:
+ case kWhatCaptureStart2:
case kWhatCaptureResult:
case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
@@ -982,6 +981,7 @@
}
case kWhatSessionStateCb:
case kWhatCaptureStart:
+ case kWhatCaptureStart2:
case kWhatCaptureResult:
case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
@@ -1002,6 +1002,7 @@
const char *id_cstr = mId.c_str();
switch (msg->what()) {
case kWhatCaptureStart:
+ case kWhatCaptureStart2:
case kWhatCaptureResult:
case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
@@ -1053,6 +1054,35 @@
freeACaptureRequest(request);
break;
}
+ case kWhatCaptureStart2:
+ {
+ ACameraCaptureSession_captureCallback_startV2 onStart2;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onStart2);
+ if (!found) {
+ ALOGE("%s: Cannot find capture startV2 callback!", __FUNCTION__);
+ return;
+ }
+ if (onStart2 == nullptr) {
+ return;
+ }
+ int64_t timestamp;
+ found = msg->findInt64(kTimeStampKey, ×tamp);
+ if (!found) {
+ ALOGE("%s: Cannot find timestamp!", __FUNCTION__);
+ return;
+ }
+ int64_t frameNumber;
+ found = msg->findInt64(kFrameNumberKey, &frameNumber);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
+ (*onStart2)(context, session.get(), request, timestamp, frameNumber);
+ freeACaptureRequest(request);
+ break;
+ }
case kWhatCaptureResult:
{
ACameraCaptureSession_captureCallback_result onResult;
@@ -1281,6 +1311,7 @@
ACameraCaptureSession_captureCallbacks* cbs) :
mSession(session), mRequests(requests),
mIsRepeating(isRepeating),
+ mIs2Callback(false),
mIsLogicalCameraCallback(false) {
initCaptureCallbacks(cbs);
@@ -1297,6 +1328,7 @@
ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
mSession(session), mRequests(requests),
mIsRepeating(isRepeating),
+ mIs2Callback(false),
mIsLogicalCameraCallback(true) {
initCaptureCallbacks(lcbs);
@@ -1306,6 +1338,40 @@
}
}
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacksV2* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIs2Callback(true),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacksV2(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIs2Callback(true),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacksV2(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ mOnLogicalCameraCaptureFailed = lcbs->onLogicalCameraCaptureFailed;
+ }
+}
+
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
const int sequenceId, const int64_t lastFrameNumber) {
@@ -1542,11 +1608,14 @@
int32_t sequenceId = resultExtras.requestId;
int32_t burstId = resultExtras.burstId;
+ int64_t frameNumber = resultExtras.frameNumber;
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_startV2 onStart2 = cbh.mOnCaptureStarted2;
+ bool v2Callback = cbh.mIs2Callback;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1554,12 +1623,19 @@
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
- sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+ sp<AMessage> msg = nullptr;
+ if (v2Callback) {
+ msg = new AMessage(kWhatCaptureStart2, dev->mHandler);
+ msg->setPointer(kCallbackFpKey, (void*) onStart2);
+ } else {
+ msg = new AMessage(kWhatCaptureStart, dev->mHandler);
+ msg->setPointer(kCallbackFpKey, (void*) onStart);
+ }
msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
msg->setInt64(kTimeStampKey, timestamp);
+ msg->setInt64(kFrameNumberKey, frameNumber);
dev->postSessionMsgAndCleanup(msg);
}
return ret;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 0b6c7c8..c306206 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -245,6 +245,7 @@
kWhatSessionStateCb, // onReady, onActive
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
+ kWhatCaptureStart2, // onCaptureStarted2
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
@@ -309,11 +310,18 @@
const Vector<sp<CaptureRequest>>& requests,
bool isRepeating,
ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
-
- template <class T>
- void initCaptureCallbacks(T* cbs) {
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacksV2* cbs);
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs);
+ void clearCallbacks() {
mContext = nullptr;
mOnCaptureStarted = nullptr;
+ mOnCaptureStarted2 = nullptr;
mOnCaptureProgressed = nullptr;
mOnCaptureCompleted = nullptr;
mOnLogicalCameraCaptureCompleted = nullptr;
@@ -322,6 +330,24 @@
mOnCaptureSequenceCompleted = nullptr;
mOnCaptureSequenceAborted = nullptr;
mOnCaptureBufferLost = nullptr;
+ }
+
+ template <class T>
+ void initCaptureCallbacksV2(T* cbs) {
+ clearCallbacks();
+ if (cbs != nullptr) {
+ mContext = cbs->context;
+ mOnCaptureStarted2 = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
+ }
+ }
+
+ template <class T>
+ void initCaptureCallbacks(T* cbs) {
+ clearCallbacks();
if (cbs != nullptr) {
mContext = cbs->context;
mOnCaptureStarted = cbs->onCaptureStarted;
@@ -335,10 +361,12 @@
sp<ACameraCaptureSession> mSession;
Vector<sp<CaptureRequest>> mRequests;
const bool mIsRepeating;
+ const bool mIs2Callback;
const bool mIsLogicalCameraCallback;
void* mContext;
ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_startV2 mOnCaptureStarted2;
ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index ba14c5c..63cdb76 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -236,6 +236,11 @@
return ACameraCaptureSession_capture(mSession, &mCaptureCallbacks, 1, &mStillRequest,
&seqId);
}
+ int takePicture2() {
+ int seqId;
+ return ACameraCaptureSession_captureV2(mSession, &mCaptureCallbacksV2, 1,
+ &mStillRequest, &seqId);
+ }
int takeLogicalCameraPicture() {
int seqId;
@@ -243,15 +248,31 @@
1, &mStillRequest, &seqId);
}
+ int takeLogicalCameraPicture2() {
+ int seqId;
+ return ACameraCaptureSession_logicalCamera_captureV2(mSession,
+ &mLogicalCaptureCallbacksV2, 1, &mStillRequest, &seqId);
+ }
+
bool checkCallbacks(int pictureCount) {
std::lock_guard<std::mutex> lock(mMutex);
if (mCompletedCaptureCallbackCount != pictureCount) {
- ALOGE("Completed capture callaback count not as expected. expected %d actual %d",
+ ALOGE("Completed capture callback count not as expected. expected %d actual %d",
pictureCount, mCompletedCaptureCallbackCount);
return false;
}
return true;
}
+ bool checkCallbacksV2(int pictureCount) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mCaptureStartedCallbackCount != pictureCount) {
+ ALOGE("Capture started callback count not as expected. expected %d actual %d",
+ pictureCount, mCaptureStartedCallbackCount);
+ return false;
+ }
+ return true;
+ }
+
private:
ACameraDevice_StateCallbacks mDeviceCb{this, nullptr, nullptr};
@@ -276,6 +297,7 @@
const char* mCameraId;
ACameraManager* mCameraManager;
int mCompletedCaptureCallbackCount = 0;
+ int mCaptureStartedCallbackCount = 0;
std::mutex mMutex;
ACameraCaptureSession_captureCallbacks mCaptureCallbacks = {
// TODO: Add tests for other callbacks
@@ -293,8 +315,25 @@
nullptr, // onCaptureSequenceAborted
nullptr, // onCaptureBufferLost
};
+ ACameraCaptureSession_captureCallbacksV2 mCaptureCallbacksV2 = {
+ this, // context
+ [](void* ctx , ACameraCaptureSession *,const ACaptureRequest *, int64_t,
+ int64_t frameNumber ) {
+ CameraHelper *ch = static_cast<CameraHelper *>(ctx);
+ ASSERT_TRUE(frameNumber >= 0);
+ std::lock_guard<std::mutex> lock(ch->mMutex);
+ ch->mCaptureStartedCallbackCount++;
+ },
+ nullptr, // onCaptureProgressed
+ nullptr, // onCaptureCompleted
+ nullptr, // onCaptureFailed
+ nullptr, // onCaptureSequenceCompleted
+ nullptr, // onCaptureSequenceAborted
+ nullptr, // onCaptureBufferLost
+ };
std::vector<std::string> mPhysicalCameraIds;
+
ACameraCaptureSession_logicalCamera_captureCallbacks mLogicalCaptureCallbacks = {
// TODO: Add tests for other callbacks
this, // context
@@ -336,6 +375,23 @@
nullptr, // onCaptureSequenceAborted
nullptr, // onCaptureBufferLost
};
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2 mLogicalCaptureCallbacksV2 = {
+ this, // context
+ [](void* ctx , ACameraCaptureSession *,const ACaptureRequest *, int64_t,
+ int64_t frameNumber) {
+ CameraHelper *ch = static_cast<CameraHelper *>(ctx);
+ ASSERT_TRUE(frameNumber >= 0);
+ std::lock_guard<std::mutex> lock(ch->mMutex);
+ ch->mCaptureStartedCallbackCount++;
+ },
+ nullptr, // onCaptureProgressed
+ nullptr, //onLogicalCaptureCompleted
+ nullptr, //onLogicalCpatureFailed
+ nullptr, // onCaptureSequenceCompleted
+ nullptr, // onCaptureSequenceAborted
+ nullptr, // onCaptureBufferLost
+ };
+
};
class ImageReaderTestCase {
@@ -570,7 +626,7 @@
}
bool takePictures(const char* id, uint64_t readerUsage, int readerMaxImages,
- bool readerAsync, int pictureCount) {
+ bool readerAsync, int pictureCount, bool v2 = false) {
int ret = 0;
ImageReaderTestCase testCase(
@@ -600,7 +656,11 @@
}
for (int i = 0; i < pictureCount; i++) {
- ret = cameraHelper.takePicture();
+ if (v2) {
+ ret = cameraHelper.takePicture2();
+ } else {
+ ret = cameraHelper.takePicture();
+ }
if (ret < 0) {
ALOGE("Unable to take picture");
return false;
@@ -617,7 +677,8 @@
}
}
return testCase.getAcquiredImageCount() == pictureCount &&
- cameraHelper.checkCallbacks(pictureCount);
+ v2 ? cameraHelper.checkCallbacksV2(pictureCount) :
+ cameraHelper.checkCallbacks(pictureCount);
}
bool testTakePicturesNative(const char* id) {
@@ -626,12 +687,14 @@
for (auto& readerMaxImages : {1, 4, 8}) {
for (auto& readerAsync : {true, false}) {
for (auto& pictureCount : {1, 4, 8}) {
- if (!takePictures(id, readerUsage, readerMaxImages,
- readerAsync, pictureCount)) {
- ALOGE("Test takePictures failed for test case usage=%" PRIu64
- ", maxImages=%d, async=%d, pictureCount=%d",
- readerUsage, readerMaxImages, readerAsync, pictureCount);
- return false;
+ for ( auto & v2 : {true, false}) {
+ if (!takePictures(id, readerUsage, readerMaxImages,
+ readerAsync, pictureCount, v2)) {
+ ALOGE("Test takePictures failed for test case usage=%" PRIu64
+ ", maxImages=%d, async=%d, pictureCount=%d",
+ readerUsage, readerMaxImages, readerAsync, pictureCount);
+ return false;
+ }
}
}
}
@@ -725,7 +788,7 @@
return;
}
- void testLogicalCameraPhysicalStream(bool usePhysicalSettings) {
+ void testLogicalCameraPhysicalStream(bool usePhysicalSettings, bool v2) {
const char* cameraId = nullptr;
ACameraMetadata* staticMetadata = nullptr;
std::vector<const char*> physicalCameraIds;
@@ -772,7 +835,12 @@
}
for (int i = 0; i < pictureCount; i++) {
- ret = cameraHelper.takeLogicalCameraPicture();
+ if (v2) {
+ ret = cameraHelper.takeLogicalCameraPicture2();
+ }
+ else {
+ ret = cameraHelper.takeLogicalCameraPicture();
+ }
ASSERT_EQ(ret, 0);
}
@@ -793,8 +861,11 @@
ALOGI("Testing window %p", testCase->getNativeWindow());
ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
}
-
- ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
+ if (v2) {
+ ASSERT_TRUE(cameraHelper.checkCallbacksV2(pictureCount));
+ } else {
+ ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
+ }
ACameraMetadata_free(staticMetadata);
}
@@ -834,8 +905,10 @@
}
TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
- testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/);
- testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/);
+ for (auto & v2 : {true, false}) {
+ testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/, v2);
+ testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/, v2);
+ }
}
} // namespace
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
new file mode 100644
index 0000000..2997b67
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -0,0 +1,72 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_defaults {
+ name: "aidl_clearkey_service_defaults",
+ vendor: true,
+
+ srcs: [
+ "CreatePluginFactories.cpp",
+ "CryptoFactory.cpp",
+ "CryptoPlugin.cpp",
+ "DrmFactory.cpp",
+ "DrmPlugin.cpp",
+ ],
+
+ relative_install_path: "hw",
+
+ cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+
+ include_dirs: ["frameworks/av/include"],
+
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcrypto",
+ "liblog",
+ "libprotobuf-cpp-lite",
+ "libutils",
+ "android.hardware.drm-V1-ndk",
+ ],
+
+ static_libs: [
+ "android.hardware.common-V2-ndk",
+ "libclearkeybase",
+ ],
+
+ local_include_dirs: ["include"],
+
+ sanitize: {
+ integer_overflow: true,
+ },
+}
+
+cc_binary {
+ name: "android.hardware.drm-service.clearkey",
+ defaults: ["aidl_clearkey_service_defaults"],
+ srcs: ["Service.cpp"],
+ init_rc: ["android.hardware.drm-service.clearkey.rc"],
+ vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
+}
+
+cc_binary {
+ name: "android.hardware.drm-service-lazy.clearkey",
+ defaults: ["aidl_clearkey_service_defaults"],
+ overrides: ["android.hardware.drm-service.clearkey"],
+ srcs: ["ServiceLazy.cpp"],
+ init_rc: ["android.hardware.drm-service-lazy.clearkey.rc"],
+ vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
+}
+
+phony {
+ name: "android.hardware.drm@latest-service.clearkey",
+ required: [
+ "android.hardware.drm-service.clearkey",
+ ],
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp
new file mode 100644
index 0000000..5f6bfe8
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/CreatePluginFactories.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "CreatePluginFactories.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+std::shared_ptr<DrmFactory> createDrmFactory() {
+ return ::ndk::SharedRefBase::make<DrmFactory>();
+}
+
+std::shared_ptr<CryptoFactory> createCryptoFactory() {
+ return ::ndk::SharedRefBase::make<CryptoFactory>();
+}
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/aidl/CryptoFactory.cpp
new file mode 100644
index 0000000..43b325d
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/CryptoFactory.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-CryptoFactory"
+#include <utils/Log.h>
+
+#include "CryptoFactory.h"
+
+#include "ClearKeyUUID.h"
+#include "CryptoPlugin.h"
+#include "AidlUtils.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+using ::aidl::android::hardware::drm::Status;
+using ::aidl::android::hardware::drm::Uuid;
+
+using std::vector;
+
+::ndk::ScopedAStatus CryptoFactory::createPlugin(
+ const ::aidl::android::hardware::drm::Uuid& in_uuid,
+ const std::vector<uint8_t>& in_initData,
+ std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) {
+ if (!isClearKeyUUID(in_uuid.uuid.data())) {
+ ALOGE("Clearkey Drm HAL: failed to create crypto plugin, "
+ "invalid crypto scheme");
+ *_aidl_return = nullptr;
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::shared_ptr<CryptoPlugin> plugin = ::ndk::SharedRefBase::make<CryptoPlugin>(in_initData);
+ Status status = plugin->getInitStatus();
+ if (status != Status::OK) {
+ plugin.reset();
+ plugin = nullptr;
+ }
+ *_aidl_return = plugin;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus CryptoFactory::isCryptoSchemeSupported(const Uuid& in_uuid,
+ bool* _aidl_return) {
+ *_aidl_return = isClearKeyUUID(in_uuid.uuid.data());
+ return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
new file mode 100644
index 0000000..b65d40f
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-CryptoPlugin"
+
+#include <utils/Log.h>
+#include <cerrno>
+#include <cstring>
+
+#include "CryptoPlugin.h"
+#include "SessionLibrary.h"
+#include "AidlUtils.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+using ::aidl::android::hardware::drm::Status;
+
+::ndk::ScopedAStatus CryptoPlugin::decrypt(
+ bool in_secure, const std::vector<uint8_t>& in_keyId, const std::vector<uint8_t>& in_iv,
+ ::aidl::android::hardware::drm::Mode in_mode,
+ const ::aidl::android::hardware::drm::Pattern& in_pattern,
+ const std::vector<::aidl::android::hardware::drm::SubSample>& in_subSamples,
+ const ::aidl::android::hardware::drm::SharedBuffer& in_source, int64_t in_offset,
+ const ::aidl::android::hardware::drm::DestinationBuffer& in_destination,
+ ::aidl::android::hardware::drm::DecryptResult* _aidl_return) {
+ UNUSED(in_pattern);
+
+ std::string detailedError;
+
+ _aidl_return->bytesWritten = 0;
+ if (in_secure) {
+ _aidl_return->detailedError = "secure decryption is not supported with ClearKey";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
+ if (mSharedBufferMap.find(in_source.bufferId) == mSharedBufferMap.end()) {
+ _aidl_return->detailedError = "source decrypt buffer base not set";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ if (in_destination.type == BufferType::SHARED_MEMORY) {
+ const SharedBuffer& dest = in_destination.nonsecureMemory;
+ if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
+ _aidl_return->detailedError = "destination decrypt buffer base not set";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+ } else {
+ _aidl_return->detailedError = "destination type not supported";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ auto src = mSharedBufferMap[in_source.bufferId];
+ if (src->mBase == nullptr) {
+ _aidl_return->detailedError = "source is a nullptr";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ size_t totalSize = 0;
+ if (__builtin_add_overflow(in_source.offset, in_offset, &totalSize) ||
+ __builtin_add_overflow(totalSize, in_source.size, &totalSize) || totalSize > src->mSize) {
+ android_errorWriteLog(0x534e4554, "176496160");
+ _aidl_return->detailedError = "invalid buffer size";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ // destination.type == BufferType::SHARED_MEMORY
+ const SharedBuffer& destBuffer = in_destination.nonsecureMemory;
+ auto dest = mSharedBufferMap[destBuffer.bufferId];
+ if (dest->mBase == nullptr) {
+ _aidl_return->detailedError = "destination is a nullptr";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ totalSize = 0;
+ if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
+ totalSize > dest->mSize) {
+ android_errorWriteLog(0x534e4554, "176444622");
+ _aidl_return->detailedError = "invalid buffer size";
+ return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+ }
+
+ // Calculate the output buffer size and determine if any subsamples are
+ // encrypted.
+ uint8_t* srcPtr = src->mBase + in_source.offset + in_offset;
+ uint8_t* destPtr = dest->mBase + in_destination.nonsecureMemory.offset;
+ size_t destSize = 0;
+ size_t srcSize = 0;
+ bool haveEncryptedSubsamples = false;
+ for (size_t i = 0; i < in_subSamples.size(); i++) {
+ const SubSample& subSample = in_subSamples[i];
+ if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize) ||
+ __builtin_add_overflow(srcSize, subSample.numBytesOfClearData, &srcSize)) {
+ _aidl_return->detailedError = "subsample clear size overflow";
+ return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+ }
+ if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize) ||
+ __builtin_add_overflow(srcSize, subSample.numBytesOfEncryptedData, &srcSize)) {
+ _aidl_return->detailedError = "subsample encrypted size overflow";
+ return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+ }
+ if (subSample.numBytesOfEncryptedData > 0) {
+ haveEncryptedSubsamples = true;
+ }
+ }
+
+ if (destSize > destBuffer.size || srcSize > in_source.size) {
+ _aidl_return->detailedError = "subsample sum too large";
+ return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE);
+ }
+
+ if (in_mode == Mode::UNENCRYPTED) {
+ if (haveEncryptedSubsamples) {
+ _aidl_return->detailedError =
+ "Encrypted subsamples found in allegedly unencrypted data.";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+
+ size_t offset = 0;
+ for (size_t i = 0; i < in_subSamples.size(); ++i) {
+ const SubSample& subSample = in_subSamples[i];
+ if (subSample.numBytesOfClearData != 0) {
+ memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
+ reinterpret_cast<const uint8_t*>(srcPtr) + offset,
+ subSample.numBytesOfClearData);
+ offset += subSample.numBytesOfClearData;
+ }
+ }
+
+ _aidl_return->bytesWritten = static_cast<ssize_t>(offset);
+ _aidl_return->detailedError = "";
+ return toNdkScopedAStatus(Status::OK);
+ } else if (in_mode == Mode::AES_CTR) {
+ size_t bytesDecrypted{};
+ std::vector<int32_t> clearDataLengths;
+ std::vector<int32_t> encryptedDataLengths;
+ for (auto ss : in_subSamples) {
+ clearDataLengths.push_back(ss.numBytesOfClearData);
+ encryptedDataLengths.push_back(ss.numBytesOfEncryptedData);
+ }
+ auto res =
+ mSession->decrypt(in_keyId.data(), in_iv.data(),
+ srcPtr, static_cast<uint8_t*>(destPtr),
+ clearDataLengths, encryptedDataLengths,
+ &bytesDecrypted);
+ if (res == clearkeydrm::OK) {
+ _aidl_return->bytesWritten = static_cast<ssize_t>(bytesDecrypted);
+ _aidl_return->detailedError = "";
+ return toNdkScopedAStatus(Status::OK);
+ } else {
+ _aidl_return->bytesWritten = 0;
+ _aidl_return->detailedError = "Decryption Error";
+ return toNdkScopedAStatus(static_cast<Status>(res));
+ }
+ } else {
+ _aidl_return->bytesWritten = 0;
+ _aidl_return->detailedError =
+ "selected encryption mode is not supported by the ClearKey DRM \
+Plugin";
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+}
+
+::ndk::ScopedAStatus CryptoPlugin::getLogMessages(
+ std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) {
+ using std::chrono::duration_cast;
+ using std::chrono::milliseconds;
+ using std::chrono::system_clock;
+
+ auto timeMillis = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+
+ std::vector<::aidl::android::hardware::drm::LogMessage> logs = {
+ {timeMillis, ::aidl::android::hardware::drm::LogPriority::ERROR,
+ std::string("Not implemented")}};
+ *_aidl_return = logs;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus CryptoPlugin::notifyResolution(int32_t in_width, int32_t in_height) {
+ UNUSED(in_width);
+ UNUSED(in_height);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus CryptoPlugin::requiresSecureDecoderComponent(const std::string& in_mime,
+ bool* _aidl_return) {
+ UNUSED(in_mime);
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus CryptoPlugin::setMediaDrmSession(const std::vector<uint8_t>& in_sessionId) {
+ Status status = Status::OK;
+ if (!in_sessionId.size()) {
+ mSession = nullptr;
+ } else {
+ mSession = SessionLibrary::get()->findSession(in_sessionId);
+ if (!mSession.get()) {
+ status = Status::ERROR_DRM_SESSION_NOT_OPENED;
+ }
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus CryptoPlugin::setSharedBufferBase(
+ const ::aidl::android::hardware::common::Ashmem& in_base, int32_t in_bufferId) {
+ std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
+ mSharedBufferMap[in_bufferId] = std::make_shared<SharedBufferBase>(in_base);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+SharedBufferBase::SharedBufferBase(const ::aidl::android::hardware::common::Ashmem& mem)
+ : mBase(nullptr),
+ mSize(mem.size) {
+ if (mem.fd.get() < 0) {
+ return;
+ }
+ auto addr = mmap(nullptr, mem.size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ mem.fd.get(), 0);
+ if (addr == MAP_FAILED) {
+ ALOGE("mmap err: fd %d; errno %s",
+ mem.fd.get(), strerror(errno));
+ } else {
+ mBase = static_cast<uint8_t*>(addr);
+ }
+}
+
+SharedBufferBase::~SharedBufferBase() {
+ if (munmap(mBase, mSize)) {
+ ALOGE("munmap err: base %p; errno %s",
+ mBase, strerror(errno));
+ }
+}
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp
new file mode 100644
index 0000000..168a661
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmFactory.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-DrmFactory"
+
+#include <utils/Log.h>
+
+#include "DrmFactory.h"
+
+#include "ClearKeyUUID.h"
+#include "DrmPlugin.h"
+#include "MimeTypeStdStr.h"
+#include "SessionLibrary.h"
+#include "AidlUtils.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+using std::string;
+using std::vector;
+
+using ::aidl::android::hardware::drm::SecurityLevel;
+using ::aidl::android::hardware::drm::Status;
+using ::aidl::android::hardware::drm::Uuid;
+
+::ndk::ScopedAStatus DrmFactory::createPlugin(
+ const Uuid& in_uuid, const string& in_appPackageName,
+ std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) {
+ UNUSED(in_appPackageName);
+
+ if (!isClearKeyUUID(in_uuid.uuid.data())) {
+ ALOGE("Clearkey Drm HAL: failed to create drm plugin, "
+ "invalid crypto scheme");
+ *_aidl_return = nullptr;
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::shared_ptr<DrmPlugin> plugin =
+ ::ndk::SharedRefBase::make<DrmPlugin>(SessionLibrary::get());
+ *_aidl_return = plugin;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmFactory::getSupportedCryptoSchemes(vector<Uuid>* _aidl_return) {
+ vector<Uuid> schemes;
+ Uuid scheme;
+ for (const auto& uuid : ::aidl::android::hardware::drm::clearkey::getSupportedCryptoSchemes()) {
+ scheme.uuid.assign(uuid.begin(), uuid.end());
+ schemes.push_back(scheme);
+ }
+ *_aidl_return = schemes;
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmFactory::isContentTypeSupported(const string& in_mimeType,
+ bool* _aidl_return) {
+ // This should match the in_mimeTypes handed by InitDataParser.
+ *_aidl_return = in_mimeType == kIsoBmffVideoMimeType || in_mimeType == kIsoBmffAudioMimeType ||
+ in_mimeType == kCencInitDataFormat || in_mimeType == kWebmVideoMimeType ||
+ in_mimeType == kWebmAudioMimeType || in_mimeType == kWebmInitDataFormat;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmFactory::isCryptoSchemeSupported(const Uuid& in_uuid,
+ const string& in_mimeType,
+ SecurityLevel in_securityLevel,
+ bool* _aidl_return) {
+ bool isSupportedMimeType = false;
+ if (!isContentTypeSupported(in_mimeType, &isSupportedMimeType).isOk()) {
+ ALOGD("%s mime type is not supported by crypto scheme", in_mimeType.c_str());
+ }
+ *_aidl_return = isClearKeyUUID(in_uuid.uuid.data()) && isSupportedMimeType &&
+ in_securityLevel == SecurityLevel::SW_SECURE_CRYPTO;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+binder_status_t DrmFactory::dump(int fd, const char** args, uint32_t numArgs) {
+ UNUSED(args);
+ UNUSED(numArgs);
+
+ if (fd < 0) {
+ ALOGE("%s: negative fd", __FUNCTION__);
+ return STATUS_BAD_VALUE;
+ }
+
+ uint32_t currentSessions = SessionLibrary::get()->numOpenSessions();
+ dprintf(fd, "current open sessions: %u\n", currentSessions);
+
+ return STATUS_OK;
+}
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
new file mode 100644
index 0000000..92bea66
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-DrmPlugin"
+
+#include <aidl/android/hardware/drm/DrmMetric.h>
+#include <utils/Log.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <chrono>
+
+#include "AidlUtils.h"
+#include "ClearKeyDrmProperties.h"
+#include "DrmPlugin.h"
+#include "Session.h"
+#include "Utils.h"
+
+namespace {
+const std::string kKeySetIdPrefix("ckid");
+const int kKeySetIdLength = 16;
+const int kSecureStopIdStart = 100;
+const std::string kOfflineLicense("\"type\":\"persistent-license\"");
+const std::string kStreaming("Streaming");
+const std::string kTemporaryLicense("\"type\":\"temporary\"");
+const std::string kTrue("True");
+
+const std::string kQueryKeyLicenseType("LicenseType");
+// Value: "Streaming" or "Offline"
+const std::string kQueryKeyPlayAllowed("PlayAllowed");
+// Value: "True" or "False"
+const std::string kQueryKeyRenewAllowed("RenewAllowed");
+// Value: "True" or "False"
+
+const int kSecureStopIdSize = 10;
+
+std::vector<uint8_t> uint32ToVector(uint32_t value) {
+ // 10 bytes to display max value 4294967295 + one byte null terminator
+ char buffer[kSecureStopIdSize];
+ memset(buffer, 0, kSecureStopIdSize);
+ snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
+ return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
+}
+
+}; // unnamed namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+using ::android::Mutex;
+
+DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
+ : mSessionLibrary(sessionLibrary),
+ mOpenSessionOkCount(0),
+ mCloseSessionOkCount(0),
+ mCloseSessionNotOpenedCount(0),
+ mNextSecureStopId(kSecureStopIdStart),
+ mMockError(Status::OK) {
+ mPlayPolicy.clear();
+ initProperties();
+ mSecureStops.clear();
+ mReleaseKeysMap.clear();
+ std::srand(std::time(nullptr));
+}
+
+void DrmPlugin::initProperties() {
+ mStringProperties.clear();
+ mStringProperties[kVendorKey] = kVendorValue;
+ mStringProperties[kVersionKey] = kVersionValue;
+ mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
+ mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
+ mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
+ mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
+
+ std::vector<uint8_t> valueVector;
+ valueVector.clear();
+ valueVector.insert(valueVector.end(), kTestDeviceIdData,
+ kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
+ mByteArrayProperties[kDeviceIdKey] = valueVector;
+
+ valueVector.clear();
+ valueVector.insert(valueVector.end(), kMetricsData,
+ kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
+ mByteArrayProperties[kMetricsKey] = valueVector;
+}
+
+// The secure stop in ClearKey implementation is not installed securely.
+// This function merely creates a test environment for testing secure stops APIs.
+// The content in this secure stop is implementation dependent, the clearkey
+// secureStop does not serve as a reference implementation.
+void DrmPlugin::installSecureStop(const std::vector<uint8_t>& sessionId) {
+ ::android::Mutex::Autolock lock(mSecureStopLock);
+
+ ClearkeySecureStop clearkeySecureStop;
+ clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
+ clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
+
+ mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(clearkeySecureStop.id,
+ clearkeySecureStop));
+}
+
+::ndk::ScopedAStatus DrmPlugin::closeSession(const std::vector<uint8_t>& in_sessionId) {
+ if (in_sessionId.size() == 0) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ ::android::sp<Session> session = mSessionLibrary->findSession(in_sessionId);
+ if (session.get()) {
+ mSessionLibrary->destroySession(session);
+ if (session->getMockError() != clearkeydrm::OK) {
+ sendSessionLostState(in_sessionId);
+ return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE);
+ }
+ mCloseSessionOkCount++;
+ return toNdkScopedAStatus(Status::OK);
+ }
+ mCloseSessionNotOpenedCount++;
+ return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
+}
+
+::ndk::ScopedAStatus DrmPlugin::decrypt(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_keyId,
+ const std::vector<uint8_t>& in_input,
+ const std::vector<uint8_t>& in_iv,
+ std::vector<uint8_t>* _aidl_return) {
+ *_aidl_return = {};
+ if (in_sessionId.size() == 0 || in_keyId.size() == 0 || in_input.size() == 0 ||
+ in_iv.size() == 0) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::encrypt(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_keyId,
+ const std::vector<uint8_t>& in_input,
+ const std::vector<uint8_t>& in_iv,
+ std::vector<uint8_t>* _aidl_return) {
+ *_aidl_return = {};
+ if (in_sessionId.size() == 0 || in_keyId.size() == 0 || in_input.size() == 0 ||
+ in_iv.size() == 0) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getHdcpLevels(
+ ::aidl::android::hardware::drm::HdcpLevels* _aidl_return) {
+ _aidl_return->connectedLevel = HdcpLevel::HDCP_NONE;
+ _aidl_return->maxLevel = HdcpLevel::HDCP_NO_OUTPUT;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getKeyRequest(
+ const std::vector<uint8_t>& in_scope, const std::vector<uint8_t>& in_initData,
+ const std::string& in_mimeType, ::aidl::android::hardware::drm::KeyType in_keyType,
+ const std::vector<::aidl::android::hardware::drm::KeyValue>& in_optionalParameters,
+ ::aidl::android::hardware::drm::KeyRequest* _aidl_return) {
+ UNUSED(in_optionalParameters);
+
+ KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
+ std::string defaultUrl("");
+
+ _aidl_return->request = {};
+ _aidl_return->requestType = keyRequestType;
+ _aidl_return->defaultUrl = defaultUrl;
+
+ if (in_scope.size() == 0 ||
+ (in_keyType != KeyType::STREAMING && in_keyType != KeyType::OFFLINE &&
+ in_keyType != KeyType::RELEASE)) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ const std::vector<uint8_t> scopeId = in_scope;
+ ::android::sp<Session> session;
+ if (in_keyType == KeyType::STREAMING || in_keyType == KeyType::OFFLINE) {
+ std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
+ session = mSessionLibrary->findSession(sessionId);
+ if (!session.get()) {
+ return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
+ } else if (session->getMockError() != clearkeydrm::OK) {
+ return toNdkScopedAStatus(session->getMockError());
+ }
+ keyRequestType = KeyRequestType::INITIAL;
+ }
+
+ std::vector<uint8_t> request = {};
+ auto keyType = static_cast<CdmKeyType>(in_keyType);
+ auto status = session->getKeyRequest(in_initData, in_mimeType, keyType, &request);
+
+ if (in_keyType == KeyType::RELEASE) {
+ std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end());
+ std::string requestString(request.begin(), request.end());
+ if (requestString.find(kOfflineLicense) != std::string::npos) {
+ std::string emptyResponse;
+ std::string keySetIdString(keySetId.begin(), keySetId.end());
+ if (!mFileHandle.StoreLicense(keySetIdString, DeviceFiles::kLicenseStateReleasing,
+ emptyResponse)) {
+ ALOGE("Problem releasing offline license");
+ return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN);
+ }
+ if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
+ ::android::sp<Session> session = mSessionLibrary->createSession();
+ mReleaseKeysMap[keySetIdString] = session->sessionId();
+ } else {
+ ALOGI("key is in use, ignore release request");
+ }
+ } else {
+ ALOGE("Offline license not found, nothing to release");
+ }
+ keyRequestType = KeyRequestType::RELEASE;
+ }
+ _aidl_return->request = request;
+ _aidl_return->requestType = keyRequestType;
+ _aidl_return->defaultUrl = defaultUrl;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getLogMessages(
+ std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) {
+ using std::chrono::duration_cast;
+ using std::chrono::milliseconds;
+ using std::chrono::system_clock;
+
+ auto timeMillis = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+
+ std::vector<::aidl::android::hardware::drm::LogMessage> logs = {
+ {timeMillis, ::aidl::android::hardware::drm::LogPriority::ERROR,
+ std::string("Not implemented")}};
+ *_aidl_return = logs;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getMetrics(
+ std::vector<::aidl::android::hardware::drm::DrmMetricGroup>* _aidl_return) {
+ // Set the open session count metric.
+ DrmMetricNamedValue openSessionOkAttribute = {"status", static_cast<int64_t>(Status::OK)};
+ DrmMetricNamedValue openSessionMetricValue = {"count", mOpenSessionOkCount};
+ DrmMetric openSessionMetric = {
+ "open_session", {openSessionOkAttribute}, {openSessionMetricValue}};
+
+ // Set the close session count metric.
+ DrmMetricNamedValue closeSessionOkAttribute = {"status", static_cast<int64_t>(Status::OK)};
+ DrmMetricNamedValue closeSessionMetricValue = {"count", mCloseSessionOkCount};
+ DrmMetric closeSessionMetric = {
+ "close_session", {closeSessionOkAttribute}, {closeSessionMetricValue}};
+
+ // Set the close session, not opened metric.
+ DrmMetricNamedValue closeSessionNotOpenedAttribute = {"status",
+ static_cast<int64_t>(Status::ERROR_DRM_SESSION_NOT_OPENED)};
+ DrmMetricNamedValue closeSessionNotOpenedMetricValue = {"count", mCloseSessionNotOpenedCount};
+ DrmMetric closeSessionNotOpenedMetric = {
+ "close_session", {closeSessionNotOpenedAttribute}, {closeSessionNotOpenedMetricValue}};
+
+ // Set the setPlaybackId metric.
+ std::vector<DrmMetricNamedValue> sids = {};
+ std::vector<DrmMetricNamedValue> playbackIds = {};
+ for (const auto& [key, value] : mPlaybackId) {
+ std::string sid(key.begin(), key.end());
+ DrmMetricNamedValue sessionIdAttribute = {"sid", sid};
+ sids.push_back(sessionIdAttribute);
+
+ DrmMetricNamedValue playbackIdMetricValue = {"playbackId", value};
+ playbackIds.push_back(playbackIdMetricValue);
+ }
+ DrmMetric setPlaybackIdMetric = {"set_playback_id", sids, playbackIds};
+
+ DrmMetricGroup metrics = {{openSessionMetric, closeSessionMetric, closeSessionNotOpenedMetric,
+ setPlaybackIdMetric}};
+
+ *_aidl_return = {metrics};
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getNumberOfSessions(
+ ::aidl::android::hardware::drm::NumberOfSessions* _aidl_return) {
+ _aidl_return->currentSessions = mSessionLibrary->numOpenSessions();
+ _aidl_return->maxSessions = 10;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getOfflineLicenseKeySetIds(
+ std::vector<::aidl::android::hardware::drm::KeySetId>* _aidl_return) {
+ std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
+ std::vector<KeySetId> keySetIds = {};
+ if (mMockError != Status::OK) {
+ *_aidl_return = keySetIds;
+ return toNdkScopedAStatus(toMockStatus(mMockError));
+ }
+ for (const auto& name : licenseNames) {
+ std::vector<uint8_t> keySetId(name.begin(), name.end());
+ KeySetId id = {};
+ id.keySetId = keySetId;
+ keySetIds.push_back(id);
+ }
+ *_aidl_return = keySetIds;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getOfflineLicenseState(
+ const ::aidl::android::hardware::drm::KeySetId& in_keySetId,
+ ::aidl::android::hardware::drm::OfflineLicenseState* _aidl_return) {
+ std::string licenseName(in_keySetId.keySetId.begin(), in_keySetId.keySetId.end());
+ DeviceFiles::LicenseState state;
+ std::string license;
+ OfflineLicenseState licenseState = OfflineLicenseState::UNKNOWN;
+ Status status = Status::OK;
+ if (mMockError != Status::OK) {
+ *_aidl_return = licenseState;
+ return toNdkScopedAStatus(toMockStatus(mMockError));
+ } else if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) {
+ switch (state) {
+ case DeviceFiles::kLicenseStateActive:
+ licenseState = OfflineLicenseState::USABLE;
+ break;
+ case DeviceFiles::kLicenseStateReleasing:
+ licenseState = OfflineLicenseState::INACTIVE;
+ break;
+ case DeviceFiles::kLicenseStateUnknown:
+ licenseState = OfflineLicenseState::UNKNOWN;
+ break;
+ }
+ } else {
+ status = Status::BAD_VALUE;
+ }
+ *_aidl_return = licenseState;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getPropertyByteArray(const std::string& in_propertyName,
+ std::vector<uint8_t>* _aidl_return) {
+ std::map<std::string, std::vector<uint8_t>>::iterator itr =
+ mByteArrayProperties.find(std::string(in_propertyName.c_str()));
+ Status status = Status::OK;
+ if (itr != mByteArrayProperties.end()) {
+ *_aidl_return = itr->second;
+ } else {
+ ALOGE("App requested unknown property: %s", in_propertyName.c_str());
+ status = Status::BAD_VALUE;
+ *_aidl_return = {};
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getPropertyString(const std::string& in_propertyName,
+ std::string* _aidl_return) {
+ std::string name(in_propertyName.c_str());
+ std::string value;
+ Status status = Status::OK;
+
+ if (name == kVendorKey) {
+ value = mStringProperties[kVendorKey];
+ } else if (name == kVersionKey) {
+ value = mStringProperties[kVersionKey];
+ } else if (name == kPluginDescriptionKey) {
+ value = mStringProperties[kPluginDescriptionKey];
+ } else if (name == kAlgorithmsKey) {
+ value = mStringProperties[kAlgorithmsKey];
+ } else if (name == kListenerTestSupportKey) {
+ value = mStringProperties[kListenerTestSupportKey];
+ } else if (name == kDrmErrorTestKey) {
+ value = mStringProperties[kDrmErrorTestKey];
+ } else {
+ ALOGE("App requested unknown string property %s", name.c_str());
+ status = Status::ERROR_DRM_CANNOT_HANDLE;
+ }
+ *_aidl_return = value;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getProvisionRequest(
+ const std::string& in_certificateType, const std::string& in_certificateAuthority,
+ ::aidl::android::hardware::drm::ProvisionRequest* _aidl_return) {
+ UNUSED(in_certificateType);
+ UNUSED(in_certificateAuthority);
+ _aidl_return->request = {};
+ _aidl_return->defaultUrl = {};
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getSecureStop(
+ const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId,
+ ::aidl::android::hardware::drm::SecureStop* _aidl_return) {
+ std::vector<uint8_t> stop = {};
+
+ mSecureStopLock.lock();
+ auto itr = mSecureStops.find(in_secureStopId.secureStopId);
+ if (itr != mSecureStops.end()) {
+ ClearkeySecureStop clearkeyStop = itr->second;
+ stop.assign(clearkeyStop.id.begin(), clearkeyStop.id.end());
+ stop.assign(clearkeyStop.data.begin(), clearkeyStop.data.end());
+ }
+ mSecureStopLock.unlock();
+
+ SecureStop secureStop = {};
+ Status status = Status::OK;
+ if (!stop.empty()) {
+ secureStop.opaqueData = stop;
+ } else {
+ status = Status::BAD_VALUE;
+ }
+ *_aidl_return = secureStop;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getSecureStopIds(
+ std::vector<::aidl::android::hardware::drm::SecureStopId>* _aidl_return) {
+ mSecureStopLock.lock();
+ std::vector<::aidl::android::hardware::drm::SecureStopId> ids;
+ for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
+ SecureStopId id;
+ id.secureStopId = itr->first;
+ ids.push_back(id);
+ }
+ mSecureStopLock.unlock();
+
+ *_aidl_return = ids;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getSecureStops(
+ std::vector<::aidl::android::hardware::drm::SecureStop>* _aidl_return) {
+ mSecureStopLock.lock();
+ std::vector<::aidl::android::hardware::drm::SecureStop> stops;
+ for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
+ ClearkeySecureStop clearkeyStop = itr->second;
+ std::vector<uint8_t> stop = {};
+ stop.assign(clearkeyStop.id.begin(), clearkeyStop.id.end());
+ stop.assign(clearkeyStop.data.begin(), clearkeyStop.data.end());
+
+ SecureStop secureStop;
+ secureStop.opaqueData = stop;
+ stops.push_back(secureStop);
+ }
+ mSecureStopLock.unlock();
+
+ *_aidl_return = stops;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::getSecurityLevel(
+ const std::vector<uint8_t>& in_sessionId,
+ ::aidl::android::hardware::drm::SecurityLevel* _aidl_return) {
+ if (in_sessionId.size() == 0) {
+ *_aidl_return = ::aidl::android::hardware::drm::SecurityLevel::UNKNOWN;
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::vector<uint8_t> sid = in_sessionId;
+ ::android::sp<Session> session = mSessionLibrary->findSession(sid);
+ if (!session.get()) {
+ *_aidl_return = SecurityLevel::UNKNOWN;
+ return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
+ }
+
+ std::map<std::vector<uint8_t>, ::aidl::android::hardware::drm::SecurityLevel>::iterator itr =
+ mSecurityLevel.find(sid);
+ if (itr == mSecurityLevel.end()) {
+ ALOGE("Session id not found");
+ *_aidl_return = SecurityLevel::UNKNOWN;
+ return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE);
+ }
+
+ *_aidl_return = itr->second;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::openSession(
+ ::aidl::android::hardware::drm::SecurityLevel in_securityLevel,
+ std::vector<uint8_t>* _aidl_return) {
+ ::android::sp<Session> session = mSessionLibrary->createSession();
+ processMockError(session);
+ std::vector<uint8_t> sessionId = session->sessionId();
+
+ Status status = setSecurityLevel(sessionId, in_securityLevel);
+ if (status == Status::OK) {
+ mOpenSessionOkCount++;
+ } else {
+ mSessionLibrary->destroySession(session);
+ sessionId.clear();
+ }
+ *_aidl_return = sessionId;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::provideKeyResponse(
+ const std::vector<uint8_t>& in_scope, const std::vector<uint8_t>& in_response,
+ ::aidl::android::hardware::drm::KeySetId* _aidl_return) {
+ if (in_scope.size() == 0 || in_response.size() == 0) {
+ // Returns empty keySetId
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::string responseString(reinterpret_cast<const char*>(in_response.data()),
+ in_response.size());
+ const std::vector<uint8_t> scopeId = in_scope;
+ std::vector<uint8_t> sessionId = {};
+ std::string keySetId;
+
+ bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos;
+ if (scopeId.size() < kKeySetIdPrefix.size()) {
+ android_errorWriteLog(0x534e4554, "144507096");
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+ }
+ bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0);
+ if (isRelease) {
+ keySetId.assign(scopeId.begin(), scopeId.end());
+
+ auto iter = mReleaseKeysMap.find(std::string(keySetId.begin(), keySetId.end()));
+ if (iter != mReleaseKeysMap.end()) {
+ sessionId.assign(iter->second.begin(), iter->second.end());
+ }
+ } else {
+ sessionId.assign(scopeId.begin(), scopeId.end());
+ // non offline license returns empty keySetId
+ keySetId.clear();
+ }
+
+ ::android::sp<Session> session = mSessionLibrary->findSession(sessionId);
+ if (!session.get()) {
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
+ }
+ setPlayPolicy();
+
+ auto res = session->provideKeyResponse(in_response);
+ if (res == clearkeydrm::OK) {
+ if (isOfflineLicense) {
+ if (isRelease) {
+ mFileHandle.DeleteLicense(keySetId);
+ mSessionLibrary->destroySession(session);
+ } else {
+ if (!makeKeySetId(&keySetId)) {
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN);
+ }
+
+ bool ok = mFileHandle.StoreLicense(
+ keySetId, DeviceFiles::kLicenseStateActive,
+ std::string(in_response.begin(), in_response.end()));
+ if (!ok) {
+ ALOGE("Failed to store offline license");
+ }
+ }
+ }
+
+ // Test calling AMediaDrm listeners.
+ sendEvent(EventType::VENDOR_DEFINED, sessionId, sessionId);
+
+ sendExpirationUpdate(sessionId, 100);
+
+ std::vector<KeyStatus> keysStatus = {};
+ KeyStatus keyStatus;
+
+ std::vector<uint8_t> keyId1 = {0xA, 0xB, 0xC};
+ keyStatus.keyId = keyId1;
+ keyStatus.type = KeyStatusType::USABLE;
+ keysStatus.push_back(keyStatus);
+
+ std::vector<uint8_t> keyId2 = {0xD, 0xE, 0xF};
+ keyStatus.keyId = keyId2;
+ keyStatus.type = KeyStatusType::EXPIRED;
+ keysStatus.push_back(keyStatus);
+
+ std::vector<uint8_t> keyId3 = {0x0, 0x1, 0x2};
+ keyStatus.keyId = keyId3;
+ keyStatus.type = KeyStatusType::USABLEINFUTURE;
+ keysStatus.push_back(keyStatus);
+
+ sendKeysChange(sessionId, keysStatus, true);
+
+ installSecureStop(sessionId);
+ } else {
+ ALOGE("provideKeyResponse returns error=%d", res);
+ }
+
+ std::vector<uint8_t> keySetIdVec(keySetId.begin(), keySetId.end());
+ _aidl_return->keySetId = keySetIdVec;
+ return toNdkScopedAStatus(res);
+}
+
+::ndk::ScopedAStatus DrmPlugin::provideProvisionResponse(
+ const std::vector<uint8_t>& in_response,
+ ::aidl::android::hardware::drm::ProvideProvisionResponseResult* _aidl_return) {
+ Status status = Status::ERROR_DRM_CANNOT_HANDLE;
+ _aidl_return->certificate = {};
+ _aidl_return->wrappedKey = {};
+ if (in_response.size() == 0) {
+ status = Status::BAD_VALUE;
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::queryKeyStatus(
+ const std::vector<uint8_t>& in_sessionId,
+ std::vector<::aidl::android::hardware::drm::KeyValue>* _aidl_return) {
+ if (in_sessionId.size() == 0) {
+ // Returns empty key status KeyValue pair
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::vector<KeyValue> infoMap = {};
+ mPlayPolicyLock.lock();
+ KeyValue keyValuePair;
+ for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
+ keyValuePair.key = mPlayPolicy[i].key;
+ keyValuePair.value = mPlayPolicy[i].value;
+ infoMap.push_back(keyValuePair);
+ }
+ mPlayPolicyLock.unlock();
+ *_aidl_return = infoMap;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::releaseAllSecureStops() {
+ Status status = Status::OK;
+ const auto res = removeAllSecureStops();
+ if (!res.isOk() && res.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = static_cast<Status>(res.getServiceSpecificError());
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::releaseSecureStop(
+ const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) {
+ Status status = Status::OK;
+ const auto res = removeSecureStop(in_secureStopId);
+ if (!res.isOk() && res.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = static_cast<Status>(res.getServiceSpecificError());
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::releaseSecureStops(
+ const ::aidl::android::hardware::drm::OpaqueData& in_ssRelease) {
+ // OpaqueData starts with 4 byte decimal integer string
+ const size_t kFourBytesOffset = 4;
+ if (in_ssRelease.opaqueData.size() < kFourBytesOffset) {
+ ALOGE("Invalid secureStopRelease length");
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ Status status = Status::OK;
+ std::vector<uint8_t> input = in_ssRelease.opaqueData;
+
+ if (input.size() < kSecureStopIdSize + kFourBytesOffset) {
+ // The minimum size of secure stop has to contain
+ // a 4 bytes count and one secureStop id
+ ALOGE("Total size of secureStops is too short");
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ // The format of opaqueData is shared between the server
+ // and the drm service. The clearkey implementation consists of:
+ // count - number of secure stops
+ // list of fixed length secure stops
+ size_t countBufferSize = sizeof(uint32_t);
+ if (input.size() < countBufferSize) {
+ // SafetyNet logging
+ android_errorWriteLog(0x534e4554, "144766455");
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+ uint32_t count = 0;
+ sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
+
+ // Avoid divide by 0 below.
+ if (count == 0) {
+ ALOGE("Invalid 0 secureStop count");
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ // Computes the fixed length secureStop size
+ size_t secureStopSize = (input.size() - kFourBytesOffset) / count;
+ if (secureStopSize < kSecureStopIdSize) {
+ // A valid secureStop contains the id plus data
+ ALOGE("Invalid secureStop size");
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+ uint8_t* buffer = new uint8_t[secureStopSize];
+ size_t offset = kFourBytesOffset; // skip the count
+ for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
+ memcpy(buffer, input.data() + offset, secureStopSize);
+
+ // A secureStop contains id+data, we only use the id for removal
+ std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
+ ::aidl::android::hardware::drm::SecureStopId secureStopId{id};
+ const auto res = removeSecureStop(secureStopId);
+ if (!res.isOk() && res.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ status = static_cast<Status>(res.getServiceSpecificError());
+ }
+ if (Status::OK != status) break;
+ }
+
+ delete[] buffer;
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::removeAllSecureStops() {
+ Mutex::Autolock lock(mSecureStopLock);
+
+ mSecureStops.clear();
+ mNextSecureStopId = kSecureStopIdStart;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::removeKeys(const std::vector<uint8_t>& in_sessionId) {
+ Status status = Status::ERROR_DRM_CANNOT_HANDLE;
+ if (in_sessionId.size() == 0) {
+ status = Status::BAD_VALUE;
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::removeOfflineLicense(
+ const ::aidl::android::hardware::drm::KeySetId& in_keySetId) {
+ if (mMockError != Status::OK) {
+ return toNdkScopedAStatus(toMockStatus(mMockError));
+ }
+ Status status = Status::BAD_VALUE;
+ std::string licenseName(in_keySetId.keySetId.begin(), in_keySetId.keySetId.end());
+ if (mFileHandle.DeleteLicense(licenseName)) {
+ status = Status::OK;
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::removeSecureStop(
+ const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) {
+ Mutex::Autolock lock(mSecureStopLock);
+
+ Status status = Status::OK;
+ if (1 != mSecureStops.erase(in_secureStopId.secureStopId)) {
+ status = Status::BAD_VALUE;
+ }
+ return toNdkScopedAStatus(status);
+}
+
+::ndk::ScopedAStatus DrmPlugin::requiresSecureDecoder(
+ const std::string& in_mime, ::aidl::android::hardware::drm::SecurityLevel in_level,
+ bool* _aidl_return) {
+ UNUSED(in_mime);
+ UNUSED(in_level);
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmPlugin::requiresSecureDecoderDefault(const std::string& in_mime,
+ bool* _aidl_return) {
+ UNUSED(in_mime);
+ // Clearkey only supports SW_SECURE_CRYPTO, so we always returns false
+ // regardless of mime type.
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmPlugin::restoreKeys(
+ const std::vector<uint8_t>& in_sessionId,
+ const ::aidl::android::hardware::drm::KeySetId& in_keySetId) {
+ if (in_sessionId.size() == 0 || in_keySetId.keySetId.size() == 0) {
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ DeviceFiles::LicenseState licenseState;
+ std::string offlineLicense;
+ if (!mFileHandle.RetrieveLicense(
+ std::string(in_keySetId.keySetId.begin(), in_keySetId.keySetId.end()),
+ &licenseState, &offlineLicense)) {
+ ALOGE("Failed to restore offline license");
+ return toNdkScopedAStatus(Status::ERROR_DRM_NO_LICENSE);
+ }
+
+ if (DeviceFiles::kLicenseStateUnknown == licenseState ||
+ DeviceFiles::kLicenseStateReleasing == licenseState) {
+ ALOGE("Invalid license state=%d", licenseState);
+ return toNdkScopedAStatus(Status::ERROR_DRM_NO_LICENSE);
+ }
+
+ ::android::sp<Session> session = mSessionLibrary->findSession(in_sessionId);
+ if (!session.get()) {
+ return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
+ }
+ auto res = session->provideKeyResponse(
+ std::vector<uint8_t>(offlineLicense.begin(), offlineLicense.end()));
+ if (res != clearkeydrm::OK) {
+ ALOGE("Failed to restore keys");
+ }
+ return toNdkScopedAStatus(res);
+}
+
+void DrmPlugin::sendEvent(::aidl::android::hardware::drm::EventType in_eventType,
+ const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_data) {
+ if (mListener != nullptr) {
+ mListener->onEvent(in_eventType, in_sessionId, in_data);
+ } else {
+ ALOGE("Null event listener, event not sent");
+ }
+ return;
+}
+
+void DrmPlugin::sendExpirationUpdate(const std::vector<uint8_t>& in_sessionId,
+ int64_t in_expiryTimeInMS) {
+ if (mListener != nullptr) {
+ mListener->onExpirationUpdate(in_sessionId, in_expiryTimeInMS);
+ } else {
+ ALOGE("Null event listener, event not sent");
+ }
+ return;
+}
+
+void DrmPlugin::sendKeysChange(
+ const std::vector<uint8_t>& in_sessionId,
+ const std::vector<::aidl::android::hardware::drm::KeyStatus>& in_keyStatusList,
+ bool in_hasNewUsableKey) {
+ if (mListener != nullptr) {
+ mListener->onKeysChange(in_sessionId, in_keyStatusList, in_hasNewUsableKey);
+ } else {
+ ALOGE("Null event listener, event not sent");
+ }
+ return;
+}
+
+void DrmPlugin::sendSessionLostState(const std::vector<uint8_t>& in_sessionId) {
+ if (mListener != nullptr) {
+ mListener->onSessionLostState(in_sessionId);
+ }
+ return;
+}
+
+::ndk::ScopedAStatus DrmPlugin::setCipherAlgorithm(const std::vector<uint8_t>& /*in_sessionId*/,
+ const std::string& /*in_algorithm*/) {
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::setListener(
+ const std::shared_ptr<
+ ::aidl::android::hardware::drm::IDrmPluginListener>& in_listener) {
+ mListener = in_listener;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::setMacAlgorithm(const std::vector<uint8_t>& /*in_sessionId*/,
+ const std::string& /*in_algorithm*/) {
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::setPlaybackId(const std::vector<uint8_t>& in_sessionId,
+ const std::string& in_playbackId) {
+ if (in_sessionId.size() == 0) {
+ ALOGE("Invalid empty session id");
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::vector<uint8_t> sid = in_sessionId;
+ mPlaybackId[sid] = in_playbackId;
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::setPropertyByteArray(const std::string& in_propertyName,
+ const std::vector<uint8_t>& in_value) {
+ if (in_propertyName == kDeviceIdKey) {
+ ALOGD("Cannot set immutable property: %s", in_propertyName.c_str());
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ } else if (in_propertyName == kClientIdKey) {
+ mByteArrayProperties[kClientIdKey] = in_value;
+ return toNdkScopedAStatus(Status::OK);
+ }
+
+ // Setting of undefined properties is not supported
+ ALOGE("Failed to set property byte array, key=%s", in_propertyName.c_str());
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::setPropertyString(const std::string& in_propertyName,
+ const std::string& in_value) {
+ std::string immutableKeys;
+ immutableKeys.append(kAlgorithmsKey + ",");
+ immutableKeys.append(kPluginDescriptionKey + ",");
+ immutableKeys.append(kVendorKey + ",");
+ immutableKeys.append(kVersionKey + ",");
+
+ std::string key = std::string(in_propertyName.c_str());
+ if (immutableKeys.find(key) != std::string::npos) {
+ ALOGD("Cannot set immutable property: %s", key.c_str());
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ std::map<std::string, std::string>::iterator itr = mStringProperties.find(key);
+ if (itr == mStringProperties.end()) {
+ ALOGE("Cannot set undefined property string, key=%s", key.c_str());
+ return toNdkScopedAStatus(Status::BAD_VALUE);
+ }
+
+ if (in_propertyName == kDrmErrorTestKey) {
+ if (in_value == kResourceContentionValue) {
+ mMockError = Status::ERROR_DRM_RESOURCE_CONTENTION;
+ } else if (in_value == kLostStateValue) {
+ mMockError = Status::ERROR_DRM_SESSION_LOST_STATE;
+ } else if (in_value == kFrameTooLargeValue) {
+ mMockError = Status::ERROR_DRM_FRAME_TOO_LARGE;
+ } else if (in_value == kInvalidStateValue) {
+ mMockError = Status::ERROR_DRM_INVALID_STATE;
+ } else {
+ mMockError = Status::ERROR_DRM_UNKNOWN;
+ }
+ }
+
+ mStringProperties[key] = std::string(in_value.c_str());
+ return toNdkScopedAStatus(Status::OK);
+}
+
+::ndk::ScopedAStatus DrmPlugin::sign(const std::vector<uint8_t>& /*in_sessionId*/,
+ const std::vector<uint8_t>& /*in_keyId*/,
+ const std::vector<uint8_t>& /*in_message*/,
+ std::vector<uint8_t>* _aidl_return) {
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::signRSA(const std::vector<uint8_t>& /*in_sessionId*/,
+ const std::string& /*in_algorithm*/,
+ const std::vector<uint8_t>& /*in_message*/,
+ const std::vector<uint8_t>& /*in_wrappedkey*/,
+ std::vector<uint8_t>* _aidl_return) {
+ *_aidl_return = {};
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+::ndk::ScopedAStatus DrmPlugin::verify(const std::vector<uint8_t>& /*in_sessionId*/,
+ const std::vector<uint8_t>& /*in_keyId*/,
+ const std::vector<uint8_t>& /*in_message*/,
+ const std::vector<uint8_t>& /*in_signature*/,
+ bool* _aidl_return) {
+ *_aidl_return = false;
+ return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
+}
+
+// Private methods below.
+void DrmPlugin::setPlayPolicy() {
+ ::android::Mutex::Autolock lock(mPlayPolicyLock);
+ mPlayPolicy.clear();
+
+ KeyValue policy;
+ policy.key = kQueryKeyLicenseType;
+ policy.value = kStreaming;
+ mPlayPolicy.push_back(policy);
+
+ policy.key = kQueryKeyPlayAllowed;
+ policy.value = kTrue;
+ mPlayPolicy.push_back(policy);
+
+ policy.key = kQueryKeyRenewAllowed;
+ mPlayPolicy.push_back(policy);
+}
+
+bool DrmPlugin::makeKeySetId(std::string* keySetId) {
+ if (!keySetId) {
+ ALOGE("keySetId destination not provided");
+ return false;
+ }
+ std::vector<uint8_t> ksid(kKeySetIdPrefix.begin(), kKeySetIdPrefix.end());
+ ksid.resize(kKeySetIdLength);
+ std::vector<uint8_t> randomData((kKeySetIdLength - kKeySetIdPrefix.size()) / 2, 0);
+
+ while (keySetId->empty()) {
+ for (auto itr = randomData.begin(); itr != randomData.end(); ++itr) {
+ *itr = std::rand() % 0xff;
+ }
+ auto id = reinterpret_cast<const uint8_t*>(randomData.data());
+ *keySetId = kKeySetIdPrefix + ::android::ByteArrayToHexString(id, randomData.size());
+ if (mFileHandle.LicenseExists(*keySetId)) {
+ // collision, regenerate
+ ALOGV("Retry generating KeySetId");
+ keySetId->clear();
+ }
+ }
+ return true;
+}
+
+Status DrmPlugin::setSecurityLevel(const std::vector<uint8_t>& sessionId, SecurityLevel level) {
+ if (sessionId.size() == 0) {
+ ALOGE("Invalid empty session id");
+ return Status::BAD_VALUE;
+ }
+
+ if (level != SecurityLevel::DEFAULT && level != SecurityLevel::SW_SECURE_CRYPTO) {
+ ALOGE("Cannot set security level > max");
+ return Status::ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ std::vector<uint8_t> sid = sessionId;
+ ::android::sp<Session> session = mSessionLibrary->findSession(sid);
+ if (!session.get()) {
+ return Status::ERROR_DRM_SESSION_NOT_OPENED;
+ }
+
+ std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr = mSecurityLevel.find(sid);
+ if (itr != mSecurityLevel.end()) {
+ mSecurityLevel[sid] = level;
+ } else {
+ if (!mSecurityLevel.insert(std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level))
+ .second) {
+ ALOGE("Failed to set security level");
+ return Status::ERROR_DRM_INVALID_STATE;
+ }
+ }
+ return Status::OK;
+}
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Service.cpp b/drm/mediadrm/plugins/clearkey/aidl/Service.cpp
new file mode 100644
index 0000000..7d342f3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/Service.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+#define LOG_NDEBUG 1
+#define LOG_TAG "clearkey-main"
+
+#include "CreatePluginFactories.h"
+
+#include <android-base/logging.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::android::base::InitLogging;
+using ::android::base::LogdLogger;
+
+using ::aidl::android::hardware::drm::clearkey::createCryptoFactory;
+using ::aidl::android::hardware::drm::clearkey::createDrmFactory;
+using ::aidl::android::hardware::drm::clearkey::CryptoFactory;
+using ::aidl::android::hardware::drm::clearkey::DrmFactory;
+
+int main(int /*argc*/, char* argv[]) {
+ InitLogging(argv, LogdLogger());
+ ::android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
+ ABinderProcess_setThreadPoolMaxThreadCount(8);
+
+ std::shared_ptr<DrmFactory> drmFactory = createDrmFactory();
+ const std::string drmInstance = std::string() + DrmFactory::descriptor + "/clearkey";
+ binder_status_t status =
+ AServiceManager_addService(drmFactory->asBinder().get(), drmInstance.c_str());
+ CHECK(status == STATUS_OK);
+
+ std::shared_ptr<CryptoFactory> cryptoFactory = createCryptoFactory();
+ const std::string cryptoInstance = std::string() + CryptoFactory::descriptor + "/clearkey";
+ status = AServiceManager_addService(cryptoFactory->asBinder().get(), cryptoInstance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reached
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp b/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp
new file mode 100644
index 0000000..55aa6e0
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/ServiceLazy.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+#define LOG_NDEBUG 1
+#define LOG_TAG "clearkey-main"
+
+#include "CreatePluginFactories.h"
+
+#include <android-base/logging.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::android::base::InitLogging;
+using ::android::base::StderrLogger;
+
+using ::aidl::android::hardware::drm::clearkey::createCryptoFactory;
+using ::aidl::android::hardware::drm::clearkey::createDrmFactory;
+using ::aidl::android::hardware::drm::clearkey::CryptoFactory;
+using ::aidl::android::hardware::drm::clearkey::DrmFactory;
+
+int main(int /*argc*/, char* argv[]) {
+ InitLogging(argv, StderrLogger);
+ ::android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
+ ABinderProcess_setThreadPoolMaxThreadCount(8);
+
+ binder_status_t status{};
+ std::shared_ptr<DrmFactory> drmFactory = createDrmFactory();
+ const std::string drmInstance = std::string() + DrmFactory::descriptor + "/clearkey";
+ status = AServiceManager_registerLazyService(drmFactory->asBinder().get(),
+ drmInstance.c_str());
+ CHECK(status == STATUS_OK);
+
+ std::shared_ptr<CryptoFactory> cryptoFactory = createCryptoFactory();
+ const std::string cryptoInstance = std::string() + CryptoFactory::descriptor + "/clearkey";
+ status = AServiceManager_registerLazyService(cryptoFactory->asBinder().get(),
+ cryptoInstance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reached
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service-lazy.clearkey.rc
new file mode 100644
index 0000000..019c726
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service-lazy.clearkey.rc
@@ -0,0 +1,9 @@
+service vendor.drm-clearkey-service /vendor/bin/hw/android.hardware.drm-service.clearkey
+ disabled
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+ interface aidl android.hardware.drm.IDrmFactory/clearkey
+ interface aidl android.hardware.drm.ICryptoFactory/clearkey
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc
new file mode 100644
index 0000000..2b2637f
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.rc
@@ -0,0 +1,8 @@
+service vendor.drm-clearkey-service /vendor/bin/hw/android.hardware.drm-service.clearkey
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+ interface aidl android.hardware.drm.IDrmFactory/clearkey
+ interface aidl android.hardware.drm.ICryptoFactory/clearkey
diff --git a/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml
new file mode 100644
index 0000000..73c15f3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/android.hardware.drm-service.clearkey.xml
@@ -0,0 +1,8 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.drm</name>
+ <version>1</version>
+ <fqname>ICryptoFactory/clearkey</fqname>
+ <fqname>IDrmFactory/clearkey</fqname>
+ </hal>
+</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
new file mode 100644
index 0000000..0370ebe
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <android/binder_auto_utils.h>
+#include "aidl/android/hardware/drm/Status.h"
+#include "ClearKeyTypes.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+inline ::aidl::android::hardware::drm::Status toMockStatus(
+ ::aidl::android::hardware::drm::Status status) {
+ switch (status) {
+ case ::aidl::android::hardware::drm::Status::ERROR_DRM_INSUFFICIENT_SECURITY:
+ case ::aidl::android::hardware::drm::Status::ERROR_DRM_FRAME_TOO_LARGE:
+ case ::aidl::android::hardware::drm::Status::ERROR_DRM_SESSION_LOST_STATE:
+ return ::aidl::android::hardware::drm::Status::ERROR_DRM_UNKNOWN;
+ default:
+ return status;
+ }
+}
+
+inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status) {
+ if (Status::OK == status) {
+ return ::ndk::ScopedAStatus::ok();
+ } else {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(status));
+ }
+}
+
+inline ::ndk::ScopedAStatus toNdkScopedAStatus(clearkeydrm::CdmResponseType res) {
+ return toNdkScopedAStatus(static_cast<::aidl::android::hardware::drm::Status>(res));
+}
+
+#define UNUSED(x) (void)(x);
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h
new file mode 100644
index 0000000..5a90fb8
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/CreatePluginFactories.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include "CryptoFactory.h"
+#include "DrmFactory.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+//extern "C" {
+std::shared_ptr<DrmFactory> createDrmFactory();
+std::shared_ptr<CryptoFactory> createCryptoFactory();
+//}
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoFactory.h
new file mode 100644
index 0000000..0d6c4ce
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoFactory.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/drm/BnCryptoFactory.h>
+#include <aidl/android/hardware/drm/ICryptoFactory.h>
+#include <aidl/android/hardware/drm/ICryptoPlugin.h>
+
+#include "ClearKeyTypes.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+struct CryptoFactory : public BnCryptoFactory {
+ CryptoFactory() {}
+ virtual ~CryptoFactory() {}
+
+ ::ndk::ScopedAStatus createPlugin(
+ const ::aidl::android::hardware::drm::Uuid& in_uuid,
+ const std::vector<uint8_t>& in_initData,
+ std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return) override;
+
+ ::ndk::ScopedAStatus isCryptoSchemeSupported(
+ const ::aidl::android::hardware::drm::Uuid& in_uuid, bool* _aidl_return) override;
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoFactory);
+};
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h
new file mode 100644
index 0000000..f98829d
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/CryptoPlugin.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/drm/BnCryptoPlugin.h>
+#include <aidl/android/hardware/drm/Status.h>
+
+#include <aidl/android/hardware/common/Ashmem.h>
+
+#include <android/binder_auto_utils.h>
+
+#include <memory>
+#include <mutex>
+
+#include "ClearKeyTypes.h"
+#include "Session.h"
+
+namespace {
+static const size_t KEY_ID_SIZE = 16;
+static const size_t KEY_IV_SIZE = 16;
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+using namespace clearkeydrm;
+using ::aidl::android::hardware::drm::Status;
+
+struct SharedBufferBase {
+ uint8_t* mBase;
+ int64_t mSize;
+ SharedBufferBase(const ::aidl::android::hardware::common::Ashmem& mem);
+ ~SharedBufferBase();
+};
+
+struct CryptoPlugin : public BnCryptoPlugin {
+ explicit CryptoPlugin(const std::vector<uint8_t>& sessionId) {
+ const auto res = setMediaDrmSession(sessionId);
+ mInitStatus = Status::OK;
+ if (!res.isOk() && res.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ mInitStatus = static_cast<Status>(res.getServiceSpecificError());
+ }
+ }
+ virtual ~CryptoPlugin() {}
+
+ ::ndk::ScopedAStatus decrypt(
+ bool in_secure, const std::vector<uint8_t>& in_keyId, const std::vector<uint8_t>& in_iv,
+ ::aidl::android::hardware::drm::Mode in_mode,
+ const ::aidl::android::hardware::drm::Pattern& in_pattern,
+ const std::vector<::aidl::android::hardware::drm::SubSample>& in_subSamples,
+ const ::aidl::android::hardware::drm::SharedBuffer& in_source, int64_t in_offset,
+ const ::aidl::android::hardware::drm::DestinationBuffer& in_destination,
+ ::aidl::android::hardware::drm::DecryptResult* _aidl_return) override;
+
+ ::ndk::ScopedAStatus getLogMessages(
+ std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) override;
+
+ ::ndk::ScopedAStatus notifyResolution(int32_t in_width, int32_t in_height) override;
+
+ ::ndk::ScopedAStatus requiresSecureDecoderComponent(const std::string& in_mime,
+ bool* _aidl_return) override;
+
+ ::ndk::ScopedAStatus setMediaDrmSession(const std::vector<uint8_t>& in_sessionId) override;
+
+ ::ndk::ScopedAStatus setSharedBufferBase(
+ const ::aidl::android::hardware::common::Ashmem& in_base, int32_t in_bufferId) override;
+
+ ::aidl::android::hardware::drm::Status getInitStatus() const { return mInitStatus; }
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoPlugin);
+
+ std::mutex mSharedBufferLock;
+ std::map<uint32_t, std::shared_ptr<SharedBufferBase>> mSharedBufferMap
+ GUARDED_BY(mSharedBufferLock);
+ ::android::sp<Session> mSession;
+ ::aidl::android::hardware::drm::Status mInitStatus;
+};
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h
new file mode 100644
index 0000000..0143dc7
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmFactory.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/drm/BnDrmFactory.h>
+#include <aidl/android/hardware/drm/IDrmFactory.h>
+#include <aidl/android/hardware/drm/IDrmPlugin.h>
+
+#include <string>
+#include <vector>
+
+#include "ClearKeyTypes.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+struct DrmFactory : public BnDrmFactory {
+ DrmFactory() {}
+ virtual ~DrmFactory() {}
+
+ ::ndk::ScopedAStatus createPlugin(
+ const ::aidl::android::hardware::drm::Uuid& in_uuid,
+ const std::string& in_appPackageName,
+ std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return) override;
+
+ ::ndk::ScopedAStatus getSupportedCryptoSchemes(
+ std::vector<::aidl::android::hardware::drm::Uuid>* _aidl_return) override;
+
+ ::ndk::ScopedAStatus isContentTypeSupported(const std::string& in_mimeType,
+ bool* _aidl_return) override;
+
+ ::ndk::ScopedAStatus isCryptoSchemeSupported(
+ const ::aidl::android::hardware::drm::Uuid& in_uuid, const std::string& in_mimeType,
+ ::aidl::android::hardware::drm::SecurityLevel in_securityLevel,
+ bool* _aidl_return) override;
+
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory);
+};
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
new file mode 100644
index 0000000..44db1d5
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/drm/BnDrmPlugin.h>
+#include <aidl/android/hardware/drm/IDrmPluginListener.h>
+#include <aidl/android/hardware/drm/Status.h>
+
+#include <stdio.h>
+#include <map>
+
+#include <utils/List.h>
+
+#include "DeviceFiles.h"
+#include "SessionLibrary.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace drm {
+namespace clearkey {
+
+using namespace clearkeydrm;
+using ::aidl::android::hardware::drm::KeyType;
+using ::aidl::android::hardware::drm::Status;
+
+struct DrmPlugin : public BnDrmPlugin {
+ public:
+ explicit DrmPlugin(SessionLibrary* sessionLibrary);
+ virtual ~DrmPlugin() { mFileHandle.DeleteAllLicenses(); }
+
+ ::ndk::ScopedAStatus closeSession(const std::vector<uint8_t>& in_sessionId) override;
+ ::ndk::ScopedAStatus decrypt(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_keyId,
+ const std::vector<uint8_t>& in_input,
+ const std::vector<uint8_t>& in_iv,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus encrypt(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_keyId,
+ const std::vector<uint8_t>& in_input,
+ const std::vector<uint8_t>& in_iv,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getHdcpLevels(
+ ::aidl::android::hardware::drm::HdcpLevels* _aidl_return) override;
+ ::ndk::ScopedAStatus getKeyRequest(
+ const std::vector<uint8_t>& in_scope, const std::vector<uint8_t>& in_initData,
+ const std::string& in_mimeType, ::aidl::android::hardware::drm::KeyType in_keyType,
+ const std::vector<::aidl::android::hardware::drm::KeyValue>& in_optionalParameters,
+ ::aidl::android::hardware::drm::KeyRequest* _aidl_return) override;
+ ::ndk::ScopedAStatus getLogMessages(
+ std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) override;
+
+ ::ndk::ScopedAStatus getMetrics(
+ std::vector<::aidl::android::hardware::drm::DrmMetricGroup>* _aidl_return) override;
+ ::ndk::ScopedAStatus getNumberOfSessions(
+ ::aidl::android::hardware::drm::NumberOfSessions* _aidl_return) override;
+ ::ndk::ScopedAStatus getOfflineLicenseKeySetIds(
+ std::vector<::aidl::android::hardware::drm::KeySetId>* _aidl_return) override;
+ ::ndk::ScopedAStatus getOfflineLicenseState(
+ const ::aidl::android::hardware::drm::KeySetId& in_keySetId,
+ ::aidl::android::hardware::drm::OfflineLicenseState* _aidl_return) override;
+ ::ndk::ScopedAStatus getPropertyByteArray(const std::string& in_propertyName,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getPropertyString(const std::string& in_propertyName,
+ std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getProvisionRequest(
+ const std::string& in_certificateType, const std::string& in_certificateAuthority,
+ ::aidl::android::hardware::drm::ProvisionRequest* _aidl_return) override;
+ ::ndk::ScopedAStatus getSecureStop(
+ const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId,
+ ::aidl::android::hardware::drm::SecureStop* _aidl_return) override;
+ ::ndk::ScopedAStatus getSecureStopIds(
+ std::vector<::aidl::android::hardware::drm::SecureStopId>* _aidl_return) override;
+ ::ndk::ScopedAStatus getSecureStops(
+ std::vector<::aidl::android::hardware::drm::SecureStop>* _aidl_return) override;
+ ::ndk::ScopedAStatus getSecurityLevel(
+ const std::vector<uint8_t>& in_sessionId,
+ ::aidl::android::hardware::drm::SecurityLevel* _aidl_return) override;
+ ::ndk::ScopedAStatus openSession(::aidl::android::hardware::drm::SecurityLevel in_securityLevel,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus provideKeyResponse(
+ const std::vector<uint8_t>& in_scope, const std::vector<uint8_t>& in_response,
+ ::aidl::android::hardware::drm::KeySetId* _aidl_return) override;
+ ::ndk::ScopedAStatus provideProvisionResponse(
+ const std::vector<uint8_t>& in_response,
+ ::aidl::android::hardware::drm::ProvideProvisionResponseResult* _aidl_return) override;
+ ::ndk::ScopedAStatus queryKeyStatus(
+ const std::vector<uint8_t>& in_sessionId,
+ std::vector<::aidl::android::hardware::drm::KeyValue>* _aidl_return) override;
+ ::ndk::ScopedAStatus releaseAllSecureStops() override;
+ ::ndk::ScopedAStatus releaseSecureStop(
+ const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) override;
+ ::ndk::ScopedAStatus releaseSecureStops(
+ const ::aidl::android::hardware::drm::OpaqueData& in_ssRelease) override;
+ ::ndk::ScopedAStatus removeAllSecureStops() override;
+ ::ndk::ScopedAStatus removeKeys(const std::vector<uint8_t>& in_sessionId) override;
+ ::ndk::ScopedAStatus removeOfflineLicense(
+ const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override;
+ ::ndk::ScopedAStatus removeSecureStop(
+ const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId) override;
+ ::ndk::ScopedAStatus requiresSecureDecoder(
+ const std::string& in_mime, ::aidl::android::hardware::drm::SecurityLevel in_level,
+ bool* _aidl_return) override;
+ ::ndk::ScopedAStatus requiresSecureDecoderDefault(const std::string& in_mime,
+ bool* _aidl_return) override;
+ ::ndk::ScopedAStatus restoreKeys(
+ const std::vector<uint8_t>& in_sessionId,
+ const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override;
+ ::ndk::ScopedAStatus setCipherAlgorithm(const std::vector<uint8_t>& in_sessionId,
+ const std::string& in_algorithm) override;
+ ::ndk::ScopedAStatus setListener(
+ // const ::android::sp<::aidl::android::hardware::drm::IDrmPluginListener>&
+ // in_listener)
+ const std::shared_ptr<IDrmPluginListener>& in_listener) override;
+ ::ndk::ScopedAStatus setMacAlgorithm(const std::vector<uint8_t>& in_sessionId,
+ const std::string& in_algorithm) override;
+ ::ndk::ScopedAStatus setPlaybackId(const std::vector<uint8_t>& in_sessionId,
+ const std::string& in_playbackId) override;
+ ::ndk::ScopedAStatus setPropertyByteArray(const std::string& in_propertyName,
+ const std::vector<uint8_t>& in_value) override;
+ ::ndk::ScopedAStatus setPropertyString(const std::string& in_propertyName,
+ const std::string& in_value) override;
+ ::ndk::ScopedAStatus sign(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_keyId,
+ const std::vector<uint8_t>& in_message,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus signRSA(const std::vector<uint8_t>& in_sessionId,
+ const std::string& in_algorithm,
+ const std::vector<uint8_t>& in_message,
+ const std::vector<uint8_t>& in_wrappedkey,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus verify(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_keyId,
+ const std::vector<uint8_t>& in_message,
+ const std::vector<uint8_t>& in_signature,
+ bool* _aidl_return) override;
+
+ private:
+ void initProperties();
+ void installSecureStop(const std::vector<uint8_t>& sessionId);
+ bool makeKeySetId(std::string* keySetId);
+ void setPlayPolicy();
+
+ void sendEvent(::aidl::android::hardware::drm::EventType in_eventType,
+ const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_data);
+ void sendExpirationUpdate(const std::vector<uint8_t>& in_sessionId,
+ int64_t in_expiryTimeInMS);
+ void sendKeysChange(
+ const std::vector<uint8_t>& in_sessionId,
+ const std::vector<::aidl::android::hardware::drm::KeyStatus>& in_keyStatusList,
+ bool in_hasNewUsableKey);
+ void sendSessionLostState(const std::vector<uint8_t>& in_sessionId);
+
+ Status setSecurityLevel(const std::vector<uint8_t>& sessionId, SecurityLevel level);
+
+ Status getKeyRequestCommon(const std::vector<uint8_t>& scope,
+ const std::vector<uint8_t>& initData, const std::string& mimeType,
+ KeyType keyType, const std::vector<KeyValue>& optionalParameters,
+ std::vector<uint8_t>* request, KeyRequestType* getKeyRequestType,
+ std::string* defaultUrl);
+
+ struct ClearkeySecureStop {
+ std::vector<uint8_t> id;
+ std::vector<uint8_t> data;
+ };
+
+ std::map<std::vector<uint8_t>, ClearkeySecureStop> mSecureStops;
+ std::vector<KeyValue> mPlayPolicy;
+ std::map<std::string, std::string> mStringProperties;
+ std::map<std::string, std::vector<uint8_t>> mByteArrayProperties;
+ std::map<std::string, std::vector<uint8_t>> mReleaseKeysMap;
+ std::map<std::vector<uint8_t>, std::string> mPlaybackId;
+ std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
+ ::std::shared_ptr<IDrmPluginListener> mListener;
+ SessionLibrary* mSessionLibrary;
+ int64_t mOpenSessionOkCount;
+ int64_t mCloseSessionOkCount;
+ int64_t mCloseSessionNotOpenedCount;
+ uint32_t mNextSecureStopId;
+ ::android::Mutex mPlayPolicyLock;
+
+ // set by property to mock error scenarios
+ Status mMockError;
+
+ void processMockError(const ::android::sp<Session>& session) {
+ session->setMockError(static_cast<CdmResponseType>(mMockError));
+ mMockError = Status::OK;
+ }
+
+ DeviceFiles mFileHandle;
+ ::android::Mutex mSecureStopLock;
+
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
+};
+
+} // namespace clearkey
+} // namespace drm
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/drm/mediadrm/plugins/clearkey/common/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/common/AesCtrDecryptor.cpp
new file mode 100644
index 0000000..0b97820
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/AesCtrDecryptor.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-AesDecryptor"
+
+#include <utils/Log.h>
+
+#include <openssl/aes.h>
+
+#include "AesCtrDecryptor.h"
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+
+static const size_t kBlockBitCount = kBlockSize * 8;
+
+CdmResponseType AesCtrDecryptor::decrypt(const std::vector<uint8_t>& key, const Iv iv,
+ const uint8_t* source, uint8_t* destination,
+ const std::vector<int32_t>& clearDataLengths,
+ const std::vector<int32_t>& encryptedDataLengths,
+ size_t* bytesDecryptedOut) {
+
+ if (key.size() != kBlockSize || clearDataLengths.size() != encryptedDataLengths.size()) {
+ android_errorWriteLog(0x534e4554, "63982768");
+ return clearkeydrm::ERROR_DECRYPT;
+ }
+
+ uint32_t blockOffset = 0;
+ uint8_t previousEncryptedCounter[kBlockSize];
+ memset(previousEncryptedCounter, 0, kBlockSize);
+
+ size_t offset = 0;
+ AES_KEY opensslKey;
+ AES_set_encrypt_key(key.data(), kBlockBitCount, &opensslKey);
+ Iv opensslIv;
+ memcpy(opensslIv, iv, sizeof(opensslIv));
+
+ for (size_t i = 0; i < clearDataLengths.size(); ++i) {
+ int32_t numBytesOfClearData = clearDataLengths[i];
+ if (numBytesOfClearData > 0) {
+ memcpy(destination + offset, source + offset, numBytesOfClearData);
+ offset += numBytesOfClearData;
+ }
+
+ int32_t numBytesOfEncryptedData = encryptedDataLengths[i];
+ if (numBytesOfEncryptedData > 0) {
+ AES_ctr128_encrypt(source + offset, destination + offset,
+ numBytesOfEncryptedData, &opensslKey, opensslIv,
+ previousEncryptedCounter, &blockOffset);
+ offset += numBytesOfEncryptedData;
+ }
+ }
+
+ *bytesDecryptedOut = offset;
+ return clearkeydrm::OK;
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/Android.bp b/drm/mediadrm/plugins/clearkey/common/Android.bp
index 7ed8b88..a6a5b28 100644
--- a/drm/mediadrm/plugins/clearkey/common/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/common/Android.bp
@@ -44,3 +44,56 @@
integer_overflow: true,
},
}
+
+cc_library_static {
+ name: "libclearkeydevicefiles-protos.common",
+ vendor: true,
+
+ proto: {
+ export_proto_headers: true,
+ type: "lite",
+ },
+ srcs: ["protos/DeviceFiles.proto"],
+}
+
+cc_library_static {
+ name: "libclearkeybase",
+ vendor: true,
+
+ srcs: [
+ "AesCtrDecryptor.cpp",
+ "Base64.cpp",
+ "Buffer.cpp",
+ "ClearKeyUUID.cpp",
+ "DeviceFiles.cpp",
+ "InitDataParser.cpp",
+ "JsonWebKey.cpp",
+ "MemoryFileSystem.cpp",
+ "Session.cpp",
+ "SessionLibrary.cpp",
+ "Utils.cpp",
+ ],
+
+ cflags: ["-Wall", "-Werror"],
+
+ include_dirs: ["frameworks/av/include"],
+
+ shared_libs: [
+ "libutils",
+ "libcrypto",
+ ],
+
+ whole_static_libs: [
+ "libjsmn",
+ "libclearkeydevicefiles-protos.common",
+ ],
+
+ export_include_dirs: [
+ "include",
+ "include/clearkeydrm",
+ ],
+
+ sanitize: {
+ integer_overflow: true,
+ },
+}
diff --git a/drm/mediadrm/plugins/clearkey/common/Base64.cpp b/drm/mediadrm/plugins/clearkey/common/Base64.cpp
new file mode 100644
index 0000000..6499793
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/Base64.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-Base64"
+
+#include "Base64.h"
+
+#include <string>
+
+namespace clearkeydrm {
+
+::android::sp<Buffer> decodeBase64(const std::string& s) {
+ size_t n = s.size();
+
+ if ((n % 4) != 0) {
+ return nullptr;
+ }
+
+ size_t padding = 0;
+ if (n >= 1 && s.c_str()[n - 1] == '=') {
+ padding = 1;
+
+ if (n >= 2 && s.c_str()[n - 2] == '=') {
+ padding = 2;
+
+ if (n >= 3 && s.c_str()[n - 3] == '=') {
+ padding = 3;
+ }
+ }
+ }
+
+ // We divide first to avoid overflow. It's OK to do this because we
+ // already made sure that n % 4 == 0.
+ size_t outLen = (n / 4) * 3 - padding;
+
+ ::android::sp<Buffer> buffer = new Buffer(outLen);
+ uint8_t* out = buffer->data();
+ if (out == nullptr || buffer->size() < outLen) {
+ return nullptr;
+ }
+
+ size_t j = 0;
+ uint32_t accum = 0;
+ for (size_t i = 0; i < n; ++i) {
+ char c = s.c_str()[i];
+ unsigned value;
+ if (c >= 'A' && c <= 'Z') {
+ value = c - 'A';
+ } else if (c >= 'a' && c <= 'z') {
+ value = 26 + c - 'a';
+ } else if (c >= '0' && c <= '9') {
+ value = 52 + c - '0';
+ } else if (c == '+' || c == '-') {
+ value = 62;
+ } else if (c == '/' || c == '_') {
+ value = 63;
+ } else if (c != '=') {
+ return nullptr;
+ } else {
+ if (i < n - padding) {
+ return nullptr;
+ }
+
+ value = 0;
+ }
+
+ accum = (accum << 6) | value;
+
+ if (((i + 1) % 4) == 0) {
+ if (j < outLen) {
+ out[j++] = (accum >> 16);
+ }
+ if (j < outLen) {
+ out[j++] = (accum >> 8) & 0xff;
+ }
+ if (j < outLen) {
+ out[j++] = accum & 0xff;
+ }
+
+ accum = 0;
+ }
+ }
+
+ return buffer;
+}
+
+static char encode6Bit(unsigned x) {
+ if (x <= 25) {
+ return 'A' + x;
+ } else if (x <= 51) {
+ return 'a' + x - 26;
+ } else if (x <= 61) {
+ return '0' + x - 52;
+ } else if (x == 62) {
+ return '+';
+ } else {
+ return '/';
+ }
+}
+
+void encodeBase64(const void* _data, size_t size, std::string* out) {
+ out->clear();
+
+ const uint8_t* data = (const uint8_t*)_data;
+
+ size_t i;
+ for (i = 0; i < (size / 3) * 3; i += 3) {
+ uint8_t x1 = data[i];
+ uint8_t x2 = data[i + 1];
+ uint8_t x3 = data[i + 2];
+
+ out->push_back(encode6Bit(x1 >> 2));
+ out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+ out->push_back(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
+ out->push_back(encode6Bit(x3 & 0x3f));
+ }
+ switch (size % 3) {
+ case 0:
+ break;
+ case 2: {
+ uint8_t x1 = data[i];
+ uint8_t x2 = data[i + 1];
+ out->push_back(encode6Bit(x1 >> 2));
+ out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+ out->push_back(encode6Bit((x2 << 2) & 0x3f));
+ out->push_back('=');
+ break;
+ }
+ default: {
+ uint8_t x1 = data[i];
+ out->push_back(encode6Bit(x1 >> 2));
+ out->push_back(encode6Bit((x1 << 4) & 0x3f));
+ out->append("==");
+ break;
+ }
+ }
+}
+
+void encodeBase64Url(const void* _data, size_t size, std::string* out) {
+ encodeBase64(_data, size, out);
+
+ if ((std::string::npos != out->find("+")) || (std::string::npos != out->find("/"))) {
+ size_t outLen = out->size();
+ char* base64url = new char[outLen];
+ for (size_t i = 0; i < outLen; ++i) {
+ if (out->c_str()[i] == '+')
+ base64url[i] = '-';
+ else if (out->c_str()[i] == '/')
+ base64url[i] = '_';
+ else
+ base64url[i] = out->c_str()[i];
+ }
+
+ out->assign(base64url, outLen);
+ delete[] base64url;
+ }
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/Buffer.cpp b/drm/mediadrm/plugins/clearkey/common/Buffer.cpp
new file mode 100644
index 0000000..1671598
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/Buffer.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 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.
+ */
+#include "Buffer.h"
+
+namespace clearkeydrm {
+
+Buffer::Buffer(size_t capacity) : mRangeOffset(0), mOwnsData(true) {
+ mData = malloc(capacity);
+ if (mData == nullptr) {
+ mCapacity = 0;
+ mRangeLength = 0;
+ } else {
+ mCapacity = capacity;
+ mRangeLength = capacity;
+ }
+}
+
+Buffer::~Buffer() {
+ if (mOwnsData) {
+ if (mData != nullptr) {
+ free(mData);
+ mData = nullptr;
+ }
+ }
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/DeviceFiles.cpp b/drm/mediadrm/plugins/clearkey/common/DeviceFiles.cpp
new file mode 100644
index 0000000..2299249
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/DeviceFiles.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 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.
+ */
+#include <utils/Log.h>
+
+#include <sys/stat.h>
+#include <string>
+
+#include "DeviceFiles.h"
+#include "protos/DeviceFiles.pb.h"
+
+#include <openssl/sha.h>
+
+// Protobuf generated classes.
+using clearkeydrm::HashedFile;
+using clearkeydrm::License;
+using clearkeydrm::License_LicenseState_ACTIVE;
+using clearkeydrm::License_LicenseState_RELEASING;
+using clearkeydrm::OfflineFile;
+
+namespace {
+const char kLicenseFileNameExt[] = ".lic";
+
+bool Hash(const std::string& data, std::string* hash) {
+ if (!hash) return false;
+
+ hash->resize(SHA256_DIGEST_LENGTH);
+
+ const unsigned char* input = reinterpret_cast<const unsigned char*>(data.data());
+ unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]);
+ SHA256(input, data.size(), output);
+ return true;
+}
+
+} // namespace
+
+namespace clearkeydrm {
+
+bool DeviceFiles::StoreLicense(const std::string& keySetId, LicenseState state,
+ const std::string& licenseResponse) {
+ OfflineFile file;
+ file.set_type(OfflineFile::LICENSE);
+ file.set_version(OfflineFile::VERSION_1);
+
+ License* license = file.mutable_license();
+ switch (state) {
+ case kLicenseStateActive:
+ license->set_state(License_LicenseState_ACTIVE);
+ license->set_license(licenseResponse);
+ break;
+ case kLicenseStateReleasing:
+ license->set_state(License_LicenseState_RELEASING);
+ license->set_license(licenseResponse);
+ break;
+ default:
+ ALOGW("StoreLicense: Unknown license state: %u", state);
+ return false;
+ }
+
+ std::string serializedFile;
+ file.SerializeToString(&serializedFile);
+
+ return StoreFileWithHash(keySetId + kLicenseFileNameExt, serializedFile);
+}
+
+bool DeviceFiles::StoreFileWithHash(const std::string& fileName,
+ const std::string& serializedFile) {
+ std::string hash;
+ if (!Hash(serializedFile, &hash)) {
+ ALOGE("StoreFileWithHash: Failed to compute hash");
+ return false;
+ }
+
+ HashedFile hashFile;
+ hashFile.set_file(serializedFile);
+ hashFile.set_hash(hash);
+
+ std::string serializedHashFile;
+ hashFile.SerializeToString(&serializedHashFile);
+
+ return StoreFileRaw(fileName, serializedHashFile);
+}
+
+bool DeviceFiles::StoreFileRaw(const std::string& fileName, const std::string& serializedHashFile) {
+ MemoryFileSystem::MemoryFile memFile;
+ memFile.setFileName(fileName);
+ memFile.setContent(serializedHashFile);
+ memFile.setFileSize(serializedHashFile.size());
+ size_t len = mFileHandle.Write(fileName, memFile);
+
+ if (len != static_cast<size_t>(serializedHashFile.size())) {
+ ALOGE("StoreFileRaw: Failed to write %s", fileName.c_str());
+ ALOGD("StoreFileRaw: expected=%zd, actual=%zu", serializedHashFile.size(), len);
+ return false;
+ }
+
+ ALOGD("StoreFileRaw: wrote %zu bytes to %s", serializedHashFile.size(), fileName.c_str());
+ return true;
+}
+
+bool DeviceFiles::RetrieveLicense(const std::string& keySetId, LicenseState* state,
+ std::string* offlineLicense) {
+ OfflineFile file;
+ if (!RetrieveHashedFile(keySetId + kLicenseFileNameExt, &file)) {
+ return false;
+ }
+
+ if (file.type() != OfflineFile::LICENSE) {
+ ALOGE("RetrieveLicense: Invalid file type");
+ return false;
+ }
+
+ if (file.version() != OfflineFile::VERSION_1) {
+ ALOGE("RetrieveLicense: Invalid file version");
+ return false;
+ }
+
+ if (!file.has_license()) {
+ ALOGE("RetrieveLicense: License not present");
+ return false;
+ }
+
+ License license = file.license();
+ switch (license.state()) {
+ case License_LicenseState_ACTIVE:
+ *state = kLicenseStateActive;
+ break;
+ case License_LicenseState_RELEASING:
+ *state = kLicenseStateReleasing;
+ break;
+ default:
+ ALOGW("RetrieveLicense: Unrecognized license state: %u", kLicenseStateUnknown);
+ *state = kLicenseStateUnknown;
+ break;
+ }
+ *offlineLicense = license.license();
+ return true;
+}
+
+bool DeviceFiles::DeleteLicense(const std::string& keySetId) {
+ return mFileHandle.RemoveFile(keySetId + kLicenseFileNameExt);
+}
+
+bool DeviceFiles::DeleteAllLicenses() {
+ return mFileHandle.RemoveAllFiles();
+}
+
+bool DeviceFiles::LicenseExists(const std::string& keySetId) {
+ return mFileHandle.FileExists(keySetId + kLicenseFileNameExt);
+}
+
+std::vector<std::string> DeviceFiles::ListLicenses() const {
+ std::vector<std::string> licenses = mFileHandle.ListFiles();
+ for (size_t i = 0; i < licenses.size(); i++) {
+ std::string& license = licenses[i];
+ license = license.substr(0, license.size() - strlen(kLicenseFileNameExt));
+ }
+ return licenses;
+}
+
+bool DeviceFiles::RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile) {
+ if (!deSerializedFile) {
+ ALOGE("RetrieveHashedFile: invalid file parameter");
+ return false;
+ }
+
+ if (!FileExists(fileName)) {
+ ALOGE("RetrieveHashedFile: %s does not exist", fileName.c_str());
+ return false;
+ }
+
+ ssize_t bytes = GetFileSize(fileName);
+ if (bytes <= 0) {
+ ALOGE("RetrieveHashedFile: invalid file size: %s", fileName.c_str());
+ // Remove the corrupted file so the caller will not get the same error
+ // when trying to access the file repeatedly, causing the system to stall.
+ RemoveFile(fileName);
+ return false;
+ }
+
+ std::string serializedHashFile;
+ serializedHashFile.resize(bytes);
+ bytes = mFileHandle.Read(fileName, &serializedHashFile);
+
+ if (bytes != static_cast<ssize_t>(serializedHashFile.size())) {
+ ALOGE("RetrieveHashedFile: Failed to read from %s", fileName.c_str());
+ ALOGV("RetrieveHashedFile: expected: %zd, actual: %zd", serializedHashFile.size(), bytes);
+ // Remove the corrupted file so the caller will not get the same error
+ // when trying to access the file repeatedly, causing the system to stall.
+ RemoveFile(fileName);
+ return false;
+ }
+
+ ALOGV("RetrieveHashedFile: read %zd from %s", bytes, fileName.c_str());
+
+ HashedFile hashFile;
+ if (!hashFile.ParseFromString(serializedHashFile)) {
+ ALOGE("RetrieveHashedFile: Unable to parse hash file");
+ // Remove corrupt file.
+ RemoveFile(fileName);
+ return false;
+ }
+
+ std::string hash;
+ if (!Hash(hashFile.file(), &hash)) {
+ ALOGE("RetrieveHashedFile: Hash computation failed");
+ return false;
+ }
+
+ if (hash != hashFile.hash()) {
+ ALOGE("RetrieveHashedFile: Hash mismatch");
+ // Remove corrupt file.
+ RemoveFile(fileName);
+ return false;
+ }
+
+ if (!deSerializedFile->ParseFromString(hashFile.file())) {
+ ALOGE("RetrieveHashedFile: Unable to parse file");
+ // Remove corrupt file.
+ RemoveFile(fileName);
+ return false;
+ }
+
+ return true;
+}
+
+bool DeviceFiles::FileExists(const std::string& fileName) const {
+ return mFileHandle.FileExists(fileName);
+}
+
+bool DeviceFiles::RemoveFile(const std::string& fileName) {
+ return mFileHandle.RemoveFile(fileName);
+}
+
+ssize_t DeviceFiles::GetFileSize(const std::string& fileName) const {
+ return mFileHandle.GetFileSize(fileName);
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/common/InitDataParser.cpp
new file mode 100644
index 0000000..fc839e9
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/InitDataParser.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 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.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "clearkey-InitDataParser"
+
+#include <algorithm>
+#include <arpa/inet.h>
+#include <utils/Log.h>
+
+#include "InitDataParser.h"
+
+#include "Base64.h"
+
+#include "ClearKeyUUID.h"
+#include "MimeType.h"
+
+namespace {
+const size_t kKeyIdSize = 16;
+const size_t kSystemIdSize = 16;
+} // namespace
+
+namespace clearkeydrm {
+
+std::vector<uint8_t> StrToVector(const std::string& str) {
+ std::vector<uint8_t> vec(str.begin(), str.end());
+ return vec;
+}
+
+CdmResponseType InitDataParser::parse(const std::vector<uint8_t>& initData,
+ const std::string& mimeType,
+ CdmKeyType keyType,
+ std::vector<uint8_t>* licenseRequest) {
+ // Build a list of the key IDs
+ std::vector<const uint8_t*> keyIds;
+
+ if (mimeType == kIsoBmffVideoMimeType.c_str() || mimeType == kIsoBmffAudioMimeType.c_str() ||
+ mimeType == kCencInitDataFormat.c_str()) {
+ auto res = parsePssh(initData, &keyIds);
+ if (res != clearkeydrm::OK) {
+ return res;
+ }
+ } else if (mimeType == kWebmVideoMimeType.c_str() || mimeType == kWebmAudioMimeType.c_str() ||
+ mimeType == kWebmInitDataFormat.c_str()) {
+ // WebM "init data" is just a single key ID
+ if (initData.size() != kKeyIdSize) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+ keyIds.push_back(initData.data());
+ } else {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+
+ if (keyType == clearkeydrm::KEY_TYPE_RELEASE) {
+ // restore key
+ }
+
+ // Build the request
+ std::string requestJson = generateRequest(keyType, keyIds);
+ std::vector<uint8_t> requestJsonVec = StrToVector(requestJson);
+
+ licenseRequest->clear();
+ licenseRequest->insert(licenseRequest->end(), requestJsonVec.begin(), requestJsonVec.end());
+ return clearkeydrm::OK;
+}
+
+CdmResponseType InitDataParser::parsePssh(const std::vector<uint8_t>& initData,
+ std::vector<const uint8_t*>* keyIds) {
+ // Description of PSSH format:
+ // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html
+ size_t readPosition = 0;
+
+ uint32_t expectedSize = initData.size();
+ const char psshIdentifier[4] = {'p', 's', 's', 'h'};
+ const uint8_t psshVersion1[4] = {1, 0, 0, 0};
+ uint32_t keyIdCount = 0;
+ size_t headerSize = sizeof(expectedSize) + sizeof(psshIdentifier) + sizeof(psshVersion1) +
+ kSystemIdSize + sizeof(keyIdCount);
+ if (initData.size() < headerSize) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+
+ // Validate size field
+ expectedSize = htonl(expectedSize);
+ if (memcmp(&initData[readPosition], &expectedSize, sizeof(expectedSize)) != 0) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+ readPosition += sizeof(expectedSize);
+
+ // Validate PSSH box identifier
+ if (memcmp(&initData[readPosition], psshIdentifier, sizeof(psshIdentifier)) != 0) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+ readPosition += sizeof(psshIdentifier);
+
+ // Validate EME version number
+ if (memcmp(&initData[readPosition], psshVersion1, sizeof(psshVersion1)) != 0) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+ readPosition += sizeof(psshVersion1);
+
+ // Validate system ID
+ if (!isClearKeyUUID(&initData[readPosition])) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+ readPosition += kSystemIdSize;
+
+ // Read key ID count
+ memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount));
+ keyIdCount = ntohl(keyIdCount);
+ readPosition += sizeof(keyIdCount);
+
+ uint64_t psshSize = 0;
+ if (__builtin_mul_overflow(keyIdCount, kKeyIdSize, &psshSize) ||
+ __builtin_add_overflow(readPosition, psshSize, &psshSize) ||
+ psshSize != initData.size() - sizeof(uint32_t) /* DataSize(0) */) {
+ return clearkeydrm::ERROR_CANNOT_HANDLE;
+ }
+
+ // Calculate the key ID offsets
+ for (uint32_t i = 0; i < keyIdCount; ++i) {
+ size_t keyIdPosition = readPosition + (i * kKeyIdSize);
+ keyIds->push_back(&initData[keyIdPosition]);
+ }
+ return clearkeydrm::OK;
+}
+
+std::string InitDataParser::generateRequest(CdmKeyType keyType,
+ const std::vector<const uint8_t*>& keyIds) {
+ const std::string kRequestPrefix("{\"kids\":[");
+ const std::string kTemporarySession("],\"type\":\"temporary\"}");
+ const std::string kPersistentSession("],\"type\":\"persistent-license\"}");
+
+ std::string request(kRequestPrefix);
+ std::string encodedId;
+ for (size_t i = 0; i < keyIds.size(); ++i) {
+ encodedId.clear();
+ encodeBase64Url(keyIds[i], kKeyIdSize, &encodedId);
+ if (i != 0) {
+ request.append(",");
+ }
+ request.push_back('\"');
+ request.append(encodedId);
+ request.push_back('\"');
+ }
+ if (keyType == clearkeydrm::KEY_TYPE_STREAMING) {
+ request.append(kTemporarySession);
+ } else if (keyType == clearkeydrm::KEY_TYPE_OFFLINE ||
+ keyType == clearkeydrm::KEY_TYPE_RELEASE) {
+ request.append(kPersistentSession);
+ }
+
+ // Android's Base64 encoder produces padding. EME forbids padding.
+ const char kBase64Padding = '=';
+ request.erase(std::remove(request.begin(), request.end(), kBase64Padding), request.end());
+
+ return request;
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp
new file mode 100644
index 0000000..ddbc594
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-JsonWebKey"
+
+#include <utils/Log.h>
+
+#include "JsonWebKey.h"
+
+#include "Base64.h"
+
+namespace {
+const std::string kBase64Padding("=");
+const std::string kKeysTag("keys");
+const std::string kKeyTypeTag("kty");
+const std::string kKeyTag("k");
+const std::string kKeyIdTag("kid");
+const std::string kMediaSessionType("type");
+const std::string kPersistentLicenseSession("persistent-license");
+const std::string kSymmetricKeyValue("oct");
+const std::string kTemporaryLicenseSession("temporary");
+} // namespace
+
+namespace clearkeydrm {
+
+JsonWebKey::JsonWebKey() {}
+
+JsonWebKey::~JsonWebKey() {}
+
+/*
+ * Parses a JSON Web Key Set string, initializes a KeyMap with key id:key
+ * pairs from the JSON Web Key Set. Both key ids and keys are base64url
+ * encoded. The KeyMap contains base64url decoded key id:key pairs.
+ *
+ * @return Returns false for errors, true for success.
+ */
+bool JsonWebKey::extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet, KeyMap* keys) {
+ keys->clear();
+
+ if (!parseJsonWebKeySet(jsonWebKeySet, &mJsonObjects)) {
+ return false;
+ }
+
+ // mJsonObjects[0] contains the entire JSON Web Key Set, including
+ // all the base64 encoded keys. Each key is also stored separately as
+ // a JSON object in mJsonObjects[1..n] where n is the total
+ // number of keys in the set.
+ if (mJsonObjects.size() == 0 || !isJsonWebKeySet(mJsonObjects[0])) {
+ return false;
+ }
+
+ std::string encodedKey, encodedKeyId;
+ std::vector<uint8_t> decodedKey, decodedKeyId;
+
+ // mJsonObjects[1] contains the first JSON Web Key in the set
+ for (size_t i = 1; i < mJsonObjects.size(); ++i) {
+ encodedKeyId.clear();
+ encodedKey.clear();
+
+ if (!parseJsonObject(mJsonObjects[i], &mTokens)) return false;
+
+ if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
+ if (encodedKeyId.empty() || encodedKey.empty()) {
+ ALOGE("Must have both key id and key in the JsonWebKey set.");
+ continue;
+ }
+
+ if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
+ ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
+ continue;
+ }
+
+ if (!decodeBase64String(encodedKey, &decodedKey)) {
+ ALOGE("Failed to decode key(%s)", encodedKey.c_str());
+ continue;
+ }
+
+ keys->insert(std::pair<std::vector<uint8_t>, std::vector<uint8_t>>(decodedKeyId,
+ decodedKey));
+ }
+ }
+ return true;
+}
+
+bool JsonWebKey::decodeBase64String(const std::string& encodedText,
+ std::vector<uint8_t>* decodedText) {
+ decodedText->clear();
+
+ // encodedText should not contain padding characters as per EME spec.
+ if (encodedText.find(kBase64Padding) != std::string::npos) {
+ return false;
+ }
+
+ // Since decodeBase64() requires padding characters,
+ // add them so length of encodedText is exactly a multiple of 4.
+ int remainder = encodedText.length() % 4;
+ std::string paddedText(encodedText);
+ if (remainder > 0) {
+ for (int i = 0; i < 4 - remainder; ++i) {
+ paddedText.append(kBase64Padding);
+ }
+ }
+
+ ::android::sp<Buffer> buffer = decodeBase64(paddedText);
+ if (buffer == nullptr) {
+ ALOGE("Malformed base64 encoded content found.");
+ return false;
+ }
+
+ decodedText->insert(decodedText->end(), buffer->base(), buffer->base() + buffer->size());
+ return true;
+}
+
+bool JsonWebKey::findKey(const std::string& jsonObject, std::string* keyId,
+ std::string* encodedKey) {
+ std::string key, value;
+
+ // Only allow symmetric key, i.e. "kty":"oct" pair.
+ if (jsonObject.find(kKeyTypeTag) != std::string::npos) {
+ findValue(kKeyTypeTag, &value);
+ if (0 != value.compare(kSymmetricKeyValue)) return false;
+ }
+
+ if (jsonObject.find(kKeyIdTag) != std::string::npos) {
+ findValue(kKeyIdTag, keyId);
+ }
+
+ if (jsonObject.find(kKeyTag) != std::string::npos) {
+ findValue(kKeyTag, encodedKey);
+ }
+ return true;
+}
+
+void JsonWebKey::findValue(const std::string& key, std::string* value) {
+ value->clear();
+ const char* valueToken;
+ for (std::vector<std::string>::const_iterator nextToken = mTokens.begin();
+ nextToken != mTokens.end(); ++nextToken) {
+ if (0 == (*nextToken).compare(key)) {
+ if (nextToken + 1 == mTokens.end()) break;
+ valueToken = (*(nextToken + 1)).c_str();
+ value->assign(valueToken);
+ nextToken++;
+ break;
+ }
+ }
+}
+
+bool JsonWebKey::isJsonWebKeySet(const std::string& jsonObject) const {
+ if (jsonObject.find(kKeysTag) == std::string::npos) {
+ ALOGE("JSON Web Key does not contain keys.");
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Parses a JSON objects string and initializes a vector of tokens.
+ *
+ * @return Returns false for errors, true for success.
+ */
+bool JsonWebKey::parseJsonObject(const std::string& jsonObject, std::vector<std::string>* tokens) {
+ jsmn_parser parser;
+
+ jsmn_init(&parser);
+ int numTokens = jsmn_parse(&parser, jsonObject.c_str(), jsonObject.size(), nullptr, 0);
+ if (numTokens < 0) {
+ ALOGE("Parser returns error code=%d", numTokens);
+ return false;
+ }
+
+ unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
+ mJsmnTokens.clear();
+ mJsmnTokens.resize(jsmnTokensSize);
+
+ jsmn_init(&parser);
+ int status = jsmn_parse(&parser, jsonObject.c_str(), jsonObject.size(), mJsmnTokens.data(),
+ numTokens);
+ if (status < 0) {
+ ALOGE("Parser returns error code=%d", status);
+ return false;
+ }
+
+ tokens->clear();
+ std::string token;
+ const char* pjs;
+ for (int j = 0; j < numTokens; ++j) {
+ pjs = jsonObject.c_str() + mJsmnTokens[j].start;
+ if (mJsmnTokens[j].type == JSMN_STRING || mJsmnTokens[j].type == JSMN_PRIMITIVE) {
+ token.assign(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
+ tokens->push_back(token);
+ }
+ }
+ return true;
+}
+
+/*
+ * Parses JSON Web Key Set string and initializes a vector of JSON objects.
+ *
+ * @return Returns false for errors, true for success.
+ */
+bool JsonWebKey::parseJsonWebKeySet(const std::string& jsonWebKeySet,
+ std::vector<std::string>* jsonObjects) {
+ if (jsonWebKeySet.empty()) {
+ ALOGE("Empty JSON Web Key");
+ return false;
+ }
+
+ // The jsmn parser only supports unicode encoding.
+ jsmn_parser parser;
+
+ // Computes number of tokens. A token marks the type, offset in
+ // the original string.
+ jsmn_init(&parser);
+ int numTokens = jsmn_parse(&parser, jsonWebKeySet.c_str(), jsonWebKeySet.size(), nullptr, 0);
+ if (numTokens < 0) {
+ ALOGE("Parser returns error code=%d", numTokens);
+ return false;
+ }
+
+ unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
+ mJsmnTokens.resize(jsmnTokensSize);
+
+ jsmn_init(&parser);
+ int status = jsmn_parse(&parser, jsonWebKeySet.c_str(), jsonWebKeySet.size(),
+ mJsmnTokens.data(), numTokens);
+ if (status < 0) {
+ ALOGE("Parser returns error code=%d", status);
+ return false;
+ }
+
+ std::string token;
+ const char* pjs;
+ for (int i = 0; i < numTokens; ++i) {
+ pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
+ if (mJsmnTokens[i].type == JSMN_OBJECT) {
+ token.assign(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
+ jsonObjects->push_back(token);
+ }
+ }
+ return true;
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/common/MemoryFileSystem.cpp
new file mode 100644
index 0000000..1045458
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/MemoryFileSystem.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 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.
+ */
+#include <utils/Log.h>
+#include <string>
+#include <vector>
+
+#include "MemoryFileSystem.h"
+
+namespace clearkeydrm {
+
+std::string MemoryFileSystem::GetFileName(const std::string& path) {
+ size_t index = path.find_last_of('/');
+ if (index != std::string::npos) {
+ return path.substr(index + 1);
+ } else {
+ return path;
+ }
+}
+
+bool MemoryFileSystem::FileExists(const std::string& fileName) const {
+ auto result = mMemoryFileSystem.find(fileName);
+ return result != mMemoryFileSystem.end();
+}
+
+ssize_t MemoryFileSystem::GetFileSize(const std::string& fileName) const {
+ auto result = mMemoryFileSystem.find(fileName);
+ if (result != mMemoryFileSystem.end()) {
+ return static_cast<ssize_t>(result->second.getFileSize());
+ } else {
+ ALOGE("Failed to get size for %s", fileName.c_str());
+ return -1;
+ }
+}
+
+std::vector<std::string> MemoryFileSystem::ListFiles() const {
+ std::vector<std::string> list;
+ for (const auto& filename : mMemoryFileSystem) {
+ list.push_back(filename.first);
+ }
+ return list;
+}
+
+size_t MemoryFileSystem::Read(const std::string& path, std::string* buffer) {
+ std::string key = GetFileName(path);
+ auto result = mMemoryFileSystem.find(key);
+ if (result != mMemoryFileSystem.end()) {
+ std::string serializedHashFile = result->second.getContent();
+ buffer->assign(serializedHashFile);
+ return buffer->size();
+ } else {
+ ALOGE("Failed to read from %s", path.c_str());
+ return -1;
+ }
+}
+
+size_t MemoryFileSystem::Write(const std::string& path, const MemoryFile& memoryFile) {
+ std::string key = GetFileName(path);
+ auto result = mMemoryFileSystem.find(key);
+ if (result != mMemoryFileSystem.end()) {
+ mMemoryFileSystem.erase(key);
+ }
+ mMemoryFileSystem.insert(std::pair<std::string, MemoryFile>(key, memoryFile));
+ return memoryFile.getFileSize();
+}
+
+bool MemoryFileSystem::RemoveFile(const std::string& fileName) {
+ auto result = mMemoryFileSystem.find(fileName);
+ if (result != mMemoryFileSystem.end()) {
+ mMemoryFileSystem.erase(result);
+ return true;
+ } else {
+ ALOGE("Cannot find license to remove: %s", fileName.c_str());
+ return false;
+ }
+}
+
+bool MemoryFileSystem::RemoveAllFiles() {
+ mMemoryFileSystem.clear();
+ return mMemoryFileSystem.empty();
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/Session.cpp b/drm/mediadrm/plugins/clearkey/common/Session.cpp
new file mode 100644
index 0000000..d7fd13a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/Session.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-Session"
+
+#include <utils/Log.h>
+
+#include "Session.h"
+
+#include "AesCtrDecryptor.h"
+#include "InitDataParser.h"
+#include "JsonWebKey.h"
+
+namespace clearkeydrm {
+
+using ::android::Mutex;
+using ::android::sp;
+
+CdmResponseType Session::getKeyRequest(const std::vector<uint8_t>& initData,
+ const std::string& mimeType,
+ CdmKeyType keyType,
+ std::vector<uint8_t>* keyRequest) const {
+ InitDataParser parser;
+ return parser.parse(initData, mimeType, keyType, keyRequest);
+}
+
+CdmResponseType Session::provideKeyResponse(const std::vector<uint8_t>& response) {
+ std::string responseString(reinterpret_cast<const char*>(response.data()), response.size());
+ KeyMap keys;
+
+ Mutex::Autolock lock(mMapLock);
+ JsonWebKey parser;
+ if (parser.extractKeysFromJsonWebKeySet(responseString, &keys)) {
+ for (auto& key : keys) {
+ std::string first(key.first.begin(), key.first.end());
+ std::string second(key.second.begin(), key.second.end());
+ mKeyMap.insert(
+ std::pair<std::vector<uint8_t>, std::vector<uint8_t>>(key.first, key.second));
+ }
+ return clearkeydrm::OK;
+ } else {
+ return clearkeydrm::ERROR_UNKNOWN;
+ }
+}
+
+CdmResponseType Session::decrypt(const KeyId keyId, const Iv iv,
+ const uint8_t* srcPtr, uint8_t* destPtr,
+ const std::vector<int32_t>& clearDataLengths,
+ const std::vector<int32_t>& encryptedDataLengths,
+ size_t* bytesDecryptedOut) {
+ Mutex::Autolock lock(mMapLock);
+
+ if (getMockError() != clearkeydrm::OK) {
+ return getMockError();
+ }
+
+ std::vector<uint8_t> keyIdVector;
+ keyIdVector.clear();
+ keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize);
+ std::map<std::vector<uint8_t>, std::vector<uint8_t>>::iterator itr;
+ itr = mKeyMap.find(keyIdVector);
+ if (itr == mKeyMap.end()) {
+ return clearkeydrm::ERROR_NO_LICENSE;
+ }
+
+ clearkeydrm::AesCtrDecryptor decryptor;
+ auto status = decryptor.decrypt(itr->second /*key*/, iv, srcPtr, destPtr,
+ clearDataLengths,
+ encryptedDataLengths,
+ bytesDecryptedOut);
+ return status;
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/common/SessionLibrary.cpp
new file mode 100644
index 0000000..6b2ff38
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/SessionLibrary.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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.
+ */
+#define LOG_TAG "clearkey-SessionLibrary"
+
+#include <utils/Log.h>
+
+#include "SessionLibrary.h"
+
+namespace clearkeydrm {
+
+using ::android::Mutex;
+using ::android::sp;
+
+Mutex SessionLibrary::sSingletonLock;
+SessionLibrary* SessionLibrary::sSingleton = NULL;
+
+SessionLibrary* SessionLibrary::get() {
+ Mutex::Autolock lock(sSingletonLock);
+
+ if (sSingleton == NULL) {
+ ALOGD("Instantiating Session Library Singleton.");
+ sSingleton = new SessionLibrary();
+ }
+
+ return sSingleton;
+}
+
+sp<Session> SessionLibrary::createSession() {
+ Mutex::Autolock lock(mSessionsLock);
+
+ char sessionIdRaw[16];
+ snprintf(sessionIdRaw, sizeof(sessionIdRaw), "%u", mNextSessionId);
+
+ mNextSessionId += 1;
+
+ std::vector<uint8_t> sessionId;
+ sessionId.insert(sessionId.end(), sessionIdRaw,
+ sessionIdRaw + sizeof(sessionIdRaw) / sizeof(uint8_t));
+
+ mSessions.insert(
+ std::pair<std::vector<uint8_t>, sp<Session>>(sessionId, new Session(sessionId)));
+ std::map<std::vector<uint8_t>, sp<Session>>::iterator itr = mSessions.find(sessionId);
+ if (itr != mSessions.end()) {
+ return itr->second;
+ } else {
+ return nullptr;
+ }
+}
+
+sp<Session> SessionLibrary::findSession(const std::vector<uint8_t>& sessionId) {
+ Mutex::Autolock lock(mSessionsLock);
+ std::map<std::vector<uint8_t>, sp<Session>>::iterator itr = mSessions.find(sessionId);
+ if (itr != mSessions.end()) {
+ return itr->second;
+ } else {
+ return nullptr;
+ }
+}
+
+void SessionLibrary::destroySession(const sp<Session>& session) {
+ Mutex::Autolock lock(mSessionsLock);
+ mSessions.erase(session->sessionId());
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h b/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
index fe10fba..8911024 100644
--- a/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
+++ b/drm/mediadrm/plugins/clearkey/common/include/ClearKeyUUID.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 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.
@@ -13,9 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#ifndef CLEARKEY_UUID_H_
-#define CLEARKEY_UUID_H_
+#pragma once
#include <array>
#include <cstdint>
@@ -27,6 +25,4 @@
std::vector<std::array<uint8_t, 16>> getSupportedCryptoSchemes();
-} // namespace clearkeydrm
-
-#endif // CLEARKEY_UUID_H_
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/AesCtrDecryptor.h
new file mode 100644
index 0000000..dbf3098
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/AesCtrDecryptor.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <cstdint>
+
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+
+class AesCtrDecryptor {
+ public:
+ AesCtrDecryptor() {}
+
+ CdmResponseType decrypt(const std::vector<uint8_t>& key, const Iv iv, const uint8_t* source,
+ uint8_t* destination,
+ const std::vector<int32_t>& clearDataLengths,
+ const std::vector<int32_t>& encryptedDataLengths,
+ size_t* bytesDecryptedOut);
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(AesCtrDecryptor);
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Base64.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Base64.h
new file mode 100644
index 0000000..075d247
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Base64.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include "Buffer.h"
+
+namespace clearkeydrm {
+
+struct Buffer;
+
+::android::sp<Buffer> decodeBase64(const std::string& s);
+
+void encodeBase64(const void* data, size_t size, std::string* out);
+
+void encodeBase64Url(const void* data, size_t size, std::string* out);
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Buffer.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Buffer.h
new file mode 100644
index 0000000..d41c4f3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Buffer.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <utils/RefBase.h>
+
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+struct Buffer : public ::android::RefBase {
+ explicit Buffer(size_t capacity);
+
+ uint8_t* base() { return reinterpret_cast<uint8_t*>(mData); }
+ uint8_t* data() { return reinterpret_cast<uint8_t*>(mData) + mRangeOffset; }
+ size_t capacity() const { return mCapacity; }
+ size_t size() const { return mRangeLength; }
+ size_t offset() const { return mRangeOffset; }
+
+ protected:
+ virtual ~Buffer();
+
+ private:
+ void* mData;
+ size_t mCapacity;
+ size_t mRangeOffset;
+ size_t mRangeLength;
+
+ bool mOwnsData;
+
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Buffer);
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
new file mode 100644
index 0000000..9a22633
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <string>
+
+namespace clearkeydrm {
+static const std::string kVendorKey("vendor");
+static const std::string kVendorValue("Google");
+static const std::string kVersionKey("version");
+static const std::string kVersionValue("1.2");
+static const std::string kPluginDescriptionKey("description");
+static const std::string kPluginDescriptionValue("ClearKey CDM");
+static const std::string kAlgorithmsKey("algorithms");
+static const std::string kAlgorithmsValue("");
+static const std::string kListenerTestSupportKey("listenerTestSupport");
+static const std::string kListenerTestSupportValue("true");
+static const std::string kDrmErrorTestKey("drmErrorTest");
+static const std::string kDrmErrorTestValue("");
+static const std::string kResourceContentionValue("resourceContention");
+static const std::string kLostStateValue("lostState");
+static const std::string kFrameTooLargeValue("frameTooLarge");
+static const std::string kInvalidStateValue("invalidState");
+
+static const std::string kDeviceIdKey("deviceId");
+static const uint8_t kTestDeviceIdData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+
+// settable byte array property
+static const std::string kClientIdKey("clientId");
+
+// TODO stub out metrics for nw
+static const std::string kMetricsKey("metrics");
+static const uint8_t kMetricsData[] = {0};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyTypes.h
new file mode 100644
index 0000000..0cc9511
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyTypes.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <map>
+#include <vector>
+
+namespace clearkeydrm {
+
+const uint8_t kBlockSize = 16; // AES_BLOCK_SIZE;
+typedef uint8_t KeyId[kBlockSize];
+typedef uint8_t Iv[kBlockSize];
+
+typedef std::map<std::vector<uint8_t>, std::vector<uint8_t>> KeyMap;
+
+#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete;
+
+#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(TypeName) \
+ TypeName() = delete; \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete;
+
+enum CdmResponseType : int32_t {
+ OK = 0,
+ ERROR_NO_LICENSE = 1,
+ ERROR_SESSION_NOT_OPENED = 3,
+ ERROR_CANNOT_HANDLE = 4,
+ ERROR_INVALID_STATE = 5,
+ BAD_VALUE = 6,
+ ERROR_DECRYPT = 11,
+ ERROR_UNKNOWN = 12,
+ ERROR_INSUFFICIENT_SECURITY = 13,
+ ERROR_FRAME_TOO_LARGE = 14,
+ ERROR_SESSION_LOST_STATE = 15,
+ ERROR_RESOURCE_CONTENTION = 16,
+};
+
+enum CdmKeyType : int32_t {
+ KEY_TYPE_OFFLINE = 0,
+ KEY_TYPE_STREAMING = 1,
+ KEY_TYPE_RELEASE = 2,
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/DeviceFiles.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/DeviceFiles.h
new file mode 100644
index 0000000..5698441
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/DeviceFiles.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "ClearKeyTypes.h"
+#include "MemoryFileSystem.h"
+
+namespace clearkeydrm {
+class OfflineFile;
+class DeviceFiles {
+ public:
+ typedef enum {
+ kLicenseStateUnknown,
+ kLicenseStateActive,
+ kLicenseStateReleasing,
+ } LicenseState;
+
+ DeviceFiles(){};
+ virtual ~DeviceFiles(){};
+
+ virtual bool StoreLicense(const std::string& keySetId, LicenseState state,
+ const std::string& keyResponse);
+
+ virtual bool RetrieveLicense(const std::string& key_set_id, LicenseState* state,
+ std::string* offlineLicense);
+
+ virtual bool LicenseExists(const std::string& keySetId);
+
+ virtual std::vector<std::string> ListLicenses() const;
+
+ virtual bool DeleteLicense(const std::string& keySetId);
+
+ virtual bool DeleteAllLicenses();
+
+ private:
+ bool FileExists(const std::string& path) const;
+ ssize_t GetFileSize(const std::string& fileName) const;
+ bool RemoveFile(const std::string& fileName);
+
+ bool RetrieveHashedFile(
+ const std::string& fileName,
+ OfflineFile* deSerializedFile);
+ bool StoreFileRaw(const std::string& fileName, const std::string& serializedFile);
+ bool StoreFileWithHash(const std::string& fileName, const std::string& serializedFile);
+
+ MemoryFileSystem mFileHandle;
+
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DeviceFiles);
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/InitDataParser.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/InitDataParser.h
new file mode 100644
index 0000000..8ecc8e3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/InitDataParser.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+
+class InitDataParser {
+ public:
+ InitDataParser() {}
+
+ CdmResponseType parse(const std::vector<uint8_t>& initData, const std::string& mimeType,
+ CdmKeyType keyType, std::vector<uint8_t>* licenseRequest);
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(InitDataParser);
+
+ CdmResponseType parsePssh(const std::vector<uint8_t>& initData,
+ std::vector<const uint8_t*>* keyIds);
+
+ std::string generateRequest(CdmKeyType keyType, const std::vector<const uint8_t*>& keyIds);
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/JsonWebKey.h
new file mode 100644
index 0000000..6681553
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/JsonWebKey.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "jsmn.h"
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+
+class JsonWebKey {
+ public:
+ JsonWebKey();
+ virtual ~JsonWebKey();
+
+ bool extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet, KeyMap* keys);
+
+ private:
+ std::vector<jsmntok_t> mJsmnTokens;
+ std::vector<std::string> mJsonObjects;
+ std::vector<std::string> mTokens;
+
+ bool decodeBase64String(const std::string& encodedText, std::vector<uint8_t>* decodedText);
+ bool findKey(const std::string& jsonObject, std::string* keyId, std::string* encodedKey);
+ void findValue(const std::string& key, std::string* value);
+ bool isJsonWebKeySet(const std::string& jsonObject) const;
+ bool parseJsonObject(const std::string& jsonObject, std::vector<std::string>* tokens);
+ bool parseJsonWebKeySet(const std::string& jsonWebKeySet,
+ std::vector<std::string>* jsonObjects);
+
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(JsonWebKey);
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/MemoryFileSystem.h
new file mode 100644
index 0000000..5642a0f
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/MemoryFileSystem.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+
+// Using android file system requires clearkey plugin to update
+// its sepolicy. However, we are unable to update sepolicy for
+// older vendor partitions. To provide backward compatibility,
+// clearkey plugin implements a very simple file system in memory.
+// This memory file system does not support directory structure.
+class MemoryFileSystem {
+ public:
+ struct MemoryFile {
+ std::string fileName; // excludes path
+ std::string content;
+ size_t fileSize;
+
+ std::string getContent() const { return content; }
+ size_t getFileSize() const { return fileSize; }
+ void setContent(const std::string& file) { content = file; }
+ void setFileName(const std::string& name) { fileName = name; }
+ void setFileSize(size_t size) {
+ content.resize(size);
+ fileSize = size;
+ }
+ };
+
+ MemoryFileSystem(){};
+ virtual ~MemoryFileSystem(){};
+
+ bool FileExists(const std::string& fileName) const;
+ ssize_t GetFileSize(const std::string& fileName) const;
+ std::vector<std::string> ListFiles() const;
+ size_t Read(const std::string& pathName, std::string* buffer);
+ bool RemoveAllFiles();
+ bool RemoveFile(const std::string& fileName);
+ size_t Write(const std::string& pathName, const MemoryFile& memoryFile);
+
+ private:
+ // License file name is made up of a unique keySetId, therefore,
+ // the filename can be used as the key to locate licenses in the
+ // memory file system.
+ std::map<std::string, MemoryFile> mMemoryFileSystem;
+
+ std::string GetFileName(const std::string& path);
+
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(MemoryFileSystem);
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/MimeTypeStdStr.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/MimeTypeStdStr.h
new file mode 100644
index 0000000..dea2974
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/MimeTypeStdStr.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <string>
+
+namespace {
+const std::string kCencInitDataFormat("cenc");
+const std::string kIsoBmffAudioMimeType("audio/mp4");
+const std::string kIsoBmffVideoMimeType("video/mp4");
+const std::string kWebmInitDataFormat("webm");
+const std::string kWebmAudioMimeType("audio/webm");
+const std::string kWebmVideoMimeType("video/webm");
+} // namespace
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Session.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Session.h
new file mode 100644
index 0000000..e2d4e32
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/Session.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+#include <cstdint>
+#include <vector>
+
+#include "ClearKeyTypes.h"
+
+namespace clearkeydrm {
+
+class Session : public ::android::RefBase {
+ public:
+ explicit Session(const std::vector<uint8_t>& sessionId)
+ : mSessionId(sessionId), mMockError(clearkeydrm::OK) {}
+ virtual ~Session() {}
+
+ const std::vector<uint8_t>& sessionId() const { return mSessionId; }
+
+ CdmResponseType getKeyRequest(const std::vector<uint8_t>& initDataType,
+ const std::string& mimeType,
+ CdmKeyType keyType,
+ std::vector<uint8_t>* keyRequest) const;
+
+ CdmResponseType provideKeyResponse(const std::vector<uint8_t>& response);
+
+ CdmResponseType decrypt(const KeyId keyId, const Iv iv, const uint8_t* srcPtr, uint8_t* dstPtr,
+ const std::vector<int32_t>& clearDataLengths,
+ const std::vector<int32_t>& encryptedDataLengths,
+ size_t* bytesDecryptedOut);
+
+ void setMockError(CdmResponseType error) { mMockError = error; }
+ CdmResponseType getMockError() const { return mMockError; }
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Session);
+
+ const std::vector<uint8_t> mSessionId;
+ KeyMap mKeyMap;
+ ::android::Mutex mMapLock;
+
+ // For mocking error return scenarios
+ CdmResponseType mMockError;
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/SessionLibrary.h
new file mode 100644
index 0000000..987e328
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/SessionLibrary.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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.
+ */
+#pragma once
+
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+#include "ClearKeyTypes.h"
+#include "Session.h"
+
+namespace clearkeydrm {
+
+class SessionLibrary : public ::android::RefBase {
+ public:
+ static SessionLibrary* get();
+
+ ::android::sp<Session> createSession();
+
+ ::android::sp<Session> findSession(const std::vector<uint8_t>& sessionId);
+
+ void destroySession(const ::android::sp<Session>& session);
+
+ size_t numOpenSessions() const { return mSessions.size(); }
+
+ private:
+ CLEARKEY_DISALLOW_COPY_AND_ASSIGN(SessionLibrary);
+
+ SessionLibrary() : mNextSessionId(1) {}
+
+ static ::android::Mutex sSingletonLock;
+ static SessionLibrary* sSingleton;
+
+ ::android::Mutex mSessionsLock;
+ uint32_t mNextSessionId;
+ std::map<std::vector<uint8_t>, ::android::sp<Session>> mSessions;
+};
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/common/protos/DeviceFiles.proto b/drm/mediadrm/plugins/clearkey/common/protos/DeviceFiles.proto
new file mode 100644
index 0000000..2d98656
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/common/protos/DeviceFiles.proto
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 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.
+ */
+syntax = "proto2";
+
+package clearkeydrm;
+
+// need this if we are using libprotobuf-cpp-2.3.0-lite
+option optimize_for = LITE_RUNTIME;
+
+message License {
+ enum LicenseState {
+ ACTIVE = 1;
+ RELEASING = 2;
+ }
+
+ optional LicenseState state = 1;
+ optional bytes license = 2;
+}
+
+message OfflineFile {
+ enum FileType {
+ LICENSE = 1;
+ }
+
+ enum FileVersion {
+ VERSION_1 = 1;
+ }
+
+ optional FileType type = 1;
+ optional FileVersion version = 2 [default = VERSION_1];
+ optional License license = 3;
+
+}
+
+message HashedFile {
+ optional bytes file = 1;
+ // A raw (not hex-encoded) SHA256, taken over the bytes of 'file'.
+ optional bytes hash = 2;
+}
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index bd6db55..a1e1702 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -55,6 +55,7 @@
// for audio_track_cblk_t::mState, to match TrackBase.h
static inline constexpr int CBLK_STATE_IDLE = 0;
+static inline constexpr int CBLK_STATE_ACTIVE = 6;
static inline constexpr int CBLK_STATE_PAUSING = 7;
/**
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index ff6080d..ffe72dc 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -32,6 +32,8 @@
// codecname set and passed in as a compile flag from Android.bp
constexpr char COMPONENT_NAME[] = CODECNAME;
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
+
class C2SoftGav1Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
public:
explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
@@ -110,8 +112,7 @@
.build());
addParameter(DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
- .withDefault(new C2StreamMaxBufferSizeInfo::input(
- 0u, 320 * 240 * 3 / 4))
+ .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
.withFields({
C2F(mMaxInputSize, value).any(),
})
@@ -227,9 +228,9 @@
bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
(void)mayBlock;
- // assume compression ratio of 2
- me.set().value =
- (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072);
+ // assume compression ratio of 2, but enforce a floor
+ me.set().value = c2_max((((maxSize.v.width + 63) / 64)
+ * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
return C2R::Ok();
}
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 5f5b2ef..2a6adca 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -34,6 +34,7 @@
constexpr char COMPONENT_NAME[] = "c2.android.hevc.decoder";
constexpr uint32_t kDefaultOutputDelay = 8;
constexpr uint32_t kMaxOutputDelay = 16;
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
} // namespace
class C2SoftHevcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -108,7 +109,7 @@
addParameter(
DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
- .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+ .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
.withFields({
C2F(mMaxInputSize, value).any(),
})
@@ -220,8 +221,9 @@
static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
(void)mayBlock;
- // assume compression ratio of 2
- me.set().value = (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072);
+ // assume compression ratio of 2, but enforce a floor
+ me.set().value = c2_max((((maxSize.v.width + 63) / 64)
+ * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
return C2R::Ok();
}
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index feaa98c..16e507c 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -59,6 +59,7 @@
enum drc_compression_mode_t : int32_t; ///< DRC compression mode
enum drc_effect_type_t : int32_t; ///< DRC effect type
enum drc_album_mode_t : int32_t; ///< DRC album mode
+ enum hdr_dynamic_metadata_type_t : uint32_t; ///< HDR dynamic metadata type
enum intra_refresh_mode_t : uint32_t; ///< intra refresh modes
enum level_t : uint32_t; ///< coding level
enum ordinal_key_t : uint32_t; ///< work ordering keys
@@ -189,10 +190,13 @@
kParamIndexPictureTypeMask,
kParamIndexPictureType,
+ // deprecated
kParamIndexHdr10PlusMetadata,
kParamIndexPictureQuantization,
+ kParamIndexHdrDynamicMetadata,
+
/* ------------------------------------ video components ------------------------------------ */
kParamIndexFrameRate = C2_PARAM_INDEX_VIDEO_PARAM_START,
@@ -270,6 +274,9 @@
// encoding quality requirements
kParamIndexEncodingQualityLevel, // encoders, enum
+
+ // encoding statistics, average block qp of a frame
+ kParamIndexAverageBlockQuantization, // int32
};
}
@@ -1602,16 +1609,54 @@
C2FIELD(maxFall, "max-fall")
};
typedef C2StreamParam<C2Info, C2HdrStaticMetadataStruct, kParamIndexHdrStaticMetadata>
- C2StreamHdrStaticInfo;
+ C2StreamHdrStaticMetadataInfo;
+typedef C2StreamParam<C2Info, C2HdrStaticMetadataStruct, kParamIndexHdrStaticMetadata>
+ C2StreamHdrStaticInfo; // deprecated
constexpr char C2_PARAMKEY_HDR_STATIC_INFO[] = "raw.hdr-static-info";
/**
* HDR10+ Metadata Info.
+ *
+ * Deprecated. Use C2StreamHdrDynamicMetadataInfo with
+ * HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40
*/
typedef C2StreamParam<C2Info, C2BlobValue, kParamIndexHdr10PlusMetadata>
- C2StreamHdr10PlusInfo;
-constexpr char C2_PARAMKEY_INPUT_HDR10_PLUS_INFO[] = "input.hdr10-plus-info";
-constexpr char C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO[] = "output.hdr10-plus-info";
+ C2StreamHdr10PlusInfo; // deprecated
+constexpr char C2_PARAMKEY_INPUT_HDR10_PLUS_INFO[] = "input.hdr10-plus-info"; // deprecated
+constexpr char C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO[] = "output.hdr10-plus-info"; // deprecated
+
+/**
+ * HDR dynamic metadata types
+ */
+C2ENUM(C2Config::hdr_dynamic_metadata_type_t, uint32_t,
+ HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10, ///< SMPTE ST 2094-10
+ HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40, ///< SMPTE ST 2094-40
+)
+
+struct C2HdrDynamicMetadataStruct {
+ inline C2HdrDynamicMetadataStruct() { memset(this, 0, sizeof(*this)); }
+
+ inline C2HdrDynamicMetadataStruct(
+ size_t flexCount, C2Config::hdr_dynamic_metadata_type_t type)
+ : type_(type) {
+ memset(data, 0, flexCount);
+ }
+
+ C2Config::hdr_dynamic_metadata_type_t type_;
+ uint8_t data[];
+
+ DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(HdrDynamicMetadata, data)
+ C2FIELD(type_, "type")
+ C2FIELD(data, "data")
+};
+
+/**
+ * Dynamic HDR Metadata Info.
+ */
+typedef C2StreamParam<C2Info, C2HdrDynamicMetadataStruct, kParamIndexHdrDynamicMetadata>
+ C2StreamHdrDynamicMetadataInfo;
+constexpr char C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO[] = "input.hdr-dynamic-info";
+constexpr char C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO[] = "output.hdr-dynamic-info";
/* ------------------------------------ block-based coding ----------------------------------- */
@@ -2411,6 +2456,17 @@
S_HANDHELD = 1 // corresponds to VMAF=70
);
+/**
+ * Video Encoding Statistics Export
+ */
+
+/**
+ * Average block QP exported from video encoder.
+ */
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<int32_t>, kParamIndexAverageBlockQuantization>
+ C2AndroidStreamAverageBlockQuantizationInfo;
+constexpr char C2_PARAMKEY_AVERAGE_QP[] = "coded.average-qp";
+
/// @}
#endif // C2CONFIG_H_
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 2bc748f..feeddb5 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -42,12 +42,14 @@
"android.hardware.drm@1.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
+ "android.hardware.graphics.mapper@4.0",
"libbase",
"libbinder",
"libcodec2",
"libcodec2_client",
"libcodec2_vndk",
"libcutils",
+ "libgralloctypes",
"libgui",
"libhidlallocatorutils",
"libhidlbase",
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index c049187..ed7d69c 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -42,6 +42,7 @@
#include "utils/Codec2Mapper.h"
#include "C2OMXNode.h"
+#include "Codec2Buffer.h"
namespace android {
@@ -466,6 +467,18 @@
new Buffer2D(block->share(
C2Rect(block->width(), block->height()), ::C2Fence())));
work->input.buffers.push_back(c2Buffer);
+ std::shared_ptr<C2StreamHdrStaticInfo::input> staticInfo;
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> dynamicInfo;
+ GetHdrMetadataFromGralloc4Handle(
+ block->handle(),
+ &staticInfo,
+ &dynamicInfo);
+ if (staticInfo && *staticInfo) {
+ c2Buffer->setInfo(staticInfo);
+ }
+ if (dynamicInfo && *dynamicInfo) {
+ c2Buffer->setInfo(dynamicInfo);
+ }
}
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 5389339..1f8b33d 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1443,6 +1443,27 @@
config->mOutputFormat->setInt32("android._tunneled", 1);
}
+ // Convert an encoding statistics level to corresponding encoding statistics
+ // kinds
+ int32_t encodingStatisticsLevel = VIDEO_ENCODING_STATISTICS_LEVEL_NONE;
+ if ((config->mDomain & Config::IS_ENCODER)
+ && (config->mDomain & Config::IS_VIDEO)
+ && msg->findInt32(KEY_VIDEO_ENCODING_STATISTICS_LEVEL, &encodingStatisticsLevel)) {
+ // Higher level include all the enc stats belong to lower level.
+ switch (encodingStatisticsLevel) {
+ // case VIDEO_ENCODING_STATISTICS_LEVEL_2: // reserved for the future level 2
+ // with more enc stat kinds
+ // Future extended encoding statistics for the level 2 should be added here
+ case VIDEO_ENCODING_STATISTICS_LEVEL_1:
+ config->subscribeToConfigUpdate(comp,
+ {kParamIndexAverageBlockQuantization, kParamIndexPictureType});
+ break;
+ case VIDEO_ENCODING_STATISTICS_LEVEL_NONE:
+ break;
+ }
+ }
+ ALOGD("encoding statistics level = %d", encodingStatisticsLevel);
+
ALOGD("setup formats input: %s",
config->mInputFormat->debugString().c_str());
ALOGD("setup formats output: %s",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 0de0b77..99aa593 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -840,6 +840,35 @@
hdr10PlusInfo.reset();
}
+ // HDR dynamic info
+ std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> hdrDynamicInfo =
+ std::static_pointer_cast<const C2StreamHdrDynamicMetadataInfo::output>(
+ c2Buffer->getInfo(C2StreamHdrDynamicMetadataInfo::output::PARAM_TYPE));
+ // TODO: make this sticky & enable unset
+ if (hdrDynamicInfo && hdrDynamicInfo->flexCount() == 0) {
+ hdrDynamicInfo.reset();
+ }
+
+ if (hdr10PlusInfo) {
+ // C2StreamHdr10PlusInfo is deprecated; components should use
+ // C2StreamHdrDynamicMetadataInfo
+ // TODO: #metric
+ if (hdrDynamicInfo) {
+ // It is unexpected that C2StreamHdr10PlusInfo and
+ // C2StreamHdrDynamicMetadataInfo is both present.
+ // C2StreamHdrDynamicMetadataInfo takes priority.
+ // TODO: #metric
+ } else {
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::output> info =
+ C2StreamHdrDynamicMetadataInfo::output::AllocShared(
+ hdr10PlusInfo->flexCount(),
+ 0u,
+ C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
+ memcpy(info->m.data, hdr10PlusInfo->m.value, hdr10PlusInfo->flexCount());
+ hdrDynamicInfo = info;
+ }
+ }
+
std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
if (blocks.size() != 1u) {
ALOGD("[%s] expected 1 graphic block, but got %zu", mName, blocks.size());
@@ -859,7 +888,7 @@
videoScalingMode,
transform,
Fence::NO_FENCE, 0);
- if (hdrStaticInfo || hdr10PlusInfo) {
+ if (hdrStaticInfo || hdrDynamicInfo) {
HdrMetadata hdr;
if (hdrStaticInfo) {
// If mastering max and min luminance fields are 0, do not use them.
@@ -896,13 +925,16 @@
hdr.cta8613 = cta861_meta;
}
}
- if (hdr10PlusInfo) {
+ if (hdrDynamicInfo
+ && hdrDynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
hdr.validTypes |= HdrMetadata::HDR10PLUS;
hdr.hdr10plus.assign(
- hdr10PlusInfo->m.value,
- hdr10PlusInfo->m.value + hdr10PlusInfo->flexCount());
+ hdrDynamicInfo->m.data,
+ hdrDynamicInfo->m.data + hdrDynamicInfo->flexCount());
}
qbi.setHdrMetadata(hdr);
+
+ SetHdrMetadataToGralloc4Handle(hdrStaticInfo, hdrDynamicInfo, block.handle());
}
// we don't have dirty regions
qbi.setSurfaceDamage(Region::INVALID_REGION);
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 03418d9..0899e99 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -953,6 +953,12 @@
return value == 0 ? C2_FALSE : C2_TRUE;
}));
+ add(ConfigMapper(KEY_VIDEO_QP_AVERAGE, C2_PARAMKEY_AVERAGE_QP, "value")
+ .limitTo(D::ENCODER & D::VIDEO & D::READ));
+
+ add(ConfigMapper(KEY_PICTURE_TYPE, C2_PARAMKEY_PICTURE_TYPE, "value")
+ .limitTo(D::ENCODER & D::VIDEO & D::READ));
+
/* still to do
constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 417b773..88e6239 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -363,11 +363,6 @@
const std::vector<std::string> &names,
c2_blocking_t blocking = C2_DONT_BLOCK);
-private:
-
- /// initializes the standard MediaCodec to Codec 2.0 params mapping
- void initializeStandardParams();
-
/// Adds indices to the subscribed indices, and updated subscription to component
/// \param blocking blocking mode to use with the component
status_t subscribeToConfigUpdate(
@@ -375,6 +370,11 @@
const std::vector<C2Param::Index> &indices,
c2_blocking_t blocking = C2_DONT_BLOCK);
+private:
+
+ /// initializes the standard MediaCodec to Codec 2.0 params mapping
+ void initializeStandardParams();
+
/// Gets SDK format from codec 2.0 reflected configuration
/// \param domain input/output bitmask
sp<AMessage> getFormatForDomain(
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 4070478..7f9de21 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -18,9 +18,14 @@
#define LOG_TAG "Codec2Buffer"
#include <utils/Log.h>
+#include <aidl/android/hardware/graphics/common/Cta861_3.h>
+#include <aidl/android/hardware/graphics/common/Smpte2086.h>
#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <gralloctypes/Gralloc4.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/CodecBase.h>
@@ -941,4 +946,218 @@
return const_cast<native_handle_t *>(mBlock->handle());
}
+using ::aidl::android::hardware::graphics::common::Cta861_3;
+using ::aidl::android::hardware::graphics::common::Smpte2086;
+
+using ::android::gralloc4::MetadataType_Cta861_3;
+using ::android::gralloc4::MetadataType_Smpte2086;
+using ::android::gralloc4::MetadataType_Smpte2094_40;
+
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+
+using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
+using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
+
+namespace {
+
+sp<IMapper4> GetMapper4() {
+ static sp<IMapper4> sMapper = IMapper4::getService();
+ return sMapper;
+}
+
+class NativeHandleDeleter {
+public:
+ explicit NativeHandleDeleter(native_handle_t *handle) : mHandle(handle) {}
+ ~NativeHandleDeleter() {
+ if (mHandle) {
+ native_handle_delete(mHandle);
+ }
+ }
+private:
+ native_handle_t *mHandle;
+};
+
+} // namspace
+
+c2_status_t GetHdrMetadataFromGralloc4Handle(
+ const C2Handle *const handle,
+ std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
+ c2_status_t err = C2_OK;
+ native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
+ if (nativeHandle == nullptr) {
+ // Nothing to do
+ return err;
+ }
+ // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
+ // does not clone the fds. Thus we need to delete the handle
+ // without closing it when going out of scope.
+ // NativeHandle cannot solve this problem, as it would close and
+ // delete the handle, while we need delete only.
+ NativeHandleDeleter nhd(nativeHandle);
+ sp<IMapper4> mapper = GetMapper4();
+ if (!mapper) {
+ // Gralloc4 not supported; nothing to do
+ return err;
+ }
+ Error4 mapperErr = Error4::NONE;
+ if (staticInfo) {
+ staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
+ memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
+ (*staticInfo)->maxCll = 0;
+ (*staticInfo)->maxFall = 0;
+ IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
+ mapperErr = err;
+ if (err != Error4::NONE) {
+ return;
+ }
+
+ std::optional<Smpte2086> smpte2086;
+ gralloc4::decodeSmpte2086(vec, &smpte2086);
+ if (smpte2086) {
+ (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
+ (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
+ (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
+ (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
+ (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
+ (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
+ (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
+ (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
+
+ (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
+ (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
+ } else {
+ mapperErr = Error4::BAD_VALUE;
+ }
+ };
+ Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2086, cb);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (mapperErr != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
+ mapperErr = err;
+ if (err != Error4::NONE) {
+ return;
+ }
+
+ std::optional<Cta861_3> cta861_3;
+ gralloc4::decodeCta861_3(vec, &cta861_3);
+ if (cta861_3) {
+ (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
+ (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
+ } else {
+ mapperErr = Error4::BAD_VALUE;
+ }
+ };
+ ret = mapper->get(nativeHandle, MetadataType_Cta861_3, cb);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (mapperErr != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ }
+ if (dynamicInfo) {
+ dynamicInfo->reset();
+ IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
+ mapperErr = err;
+ if (err != Error4::NONE) {
+ return;
+ }
+ if (!dynamicInfo) {
+ return;
+ }
+ *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
+ vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
+ memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
+ };
+ Return<void> ret = mapper->get(nativeHandle, MetadataType_Smpte2094_40, cb);
+ if (!ret.isOk() || mapperErr != Error4::NONE) {
+ dynamicInfo->reset();
+ }
+ }
+
+ return err;
+}
+
+c2_status_t SetHdrMetadataToGralloc4Handle(
+ const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
+ const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
+ const C2Handle *const handle) {
+ c2_status_t err = C2_OK;
+ native_handle_t *nativeHandle = UnwrapNativeCodec2GrallocHandle(handle);
+ if (nativeHandle == nullptr) {
+ // Nothing to do
+ return err;
+ }
+ // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
+ // does not clone the fds. Thus we need to delete the handle
+ // without closing it when going out of scope.
+ NativeHandleDeleter nhd(nativeHandle);
+ sp<IMapper4> mapper = GetMapper4();
+ if (!mapper) {
+ // Gralloc4 not supported; nothing to do
+ return err;
+ }
+ if (staticInfo && *staticInfo) {
+ std::optional<Smpte2086> smpte2086 = Smpte2086{
+ {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
+ {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
+ {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
+ {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
+ staticInfo->mastering.maxLuminance,
+ staticInfo->mastering.minLuminance,
+ };
+ hidl_vec<uint8_t> vec;
+ if (gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
+ Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Smpte2086, vec);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (ret != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ }
+ std::optional<Cta861_3> cta861_3 = Cta861_3{
+ staticInfo->maxCll,
+ staticInfo->maxFall,
+ };
+ if (gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
+ Return<Error4> ret = mapper->set(nativeHandle, MetadataType_Cta861_3, vec);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (ret != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ }
+ }
+ if (dynamicInfo && *dynamicInfo) {
+ hidl_vec<uint8_t> vec;
+ vec.resize(dynamicInfo->flexCount());
+ memcpy(vec.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
+ std::optional<IMapper4::MetadataType> metadataType;
+ switch (dynamicInfo->m.type_) {
+ case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
+ // TODO
+ break;
+ case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
+ metadataType = MetadataType_Smpte2094_40;
+ break;
+ }
+ if (metadataType) {
+ Return<Error4> ret = mapper->set(nativeHandle, *metadataType, vec);
+ if (!ret.isOk()) {
+ err = C2_REFUSED;
+ } else if (ret != Error4::NONE) {
+ err = C2_CORRUPTED;
+ }
+ } else {
+ err = C2_BAD_VALUE;
+ }
+ }
+
+ return err;
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index dc788cd..b02b042 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -19,6 +19,7 @@
#define CODEC2_BUFFER_H_
#include <C2Buffer.h>
+#include <C2Config.h>
#include <binder/IMemory.h>
#include <media/hardware/VideoAPI.h>
@@ -391,6 +392,36 @@
int32_t mHeapSeqNum;
};
+/**
+ * Get HDR metadata from Gralloc4 handle.
+ *
+ * \param[in] handle handle of the allocation
+ * \param[out] staticInfo HDR static info to be filled. Ignored if null;
+ * if |handle| is invalid or does not contain the metadata,
+ * the shared_ptr is reset.
+ * \param[out] dynamicInfo HDR dynamic info to be filled. Ignored if null;
+ * if |handle| is invalid or does not contain the metadata,
+ * the shared_ptr is reset.
+ * \return C2_OK if successful
+ */
+c2_status_t GetHdrMetadataFromGralloc4Handle(
+ const C2Handle *const handle,
+ std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
+ std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo);
+
+/**
+ * Set HDR metadata to Gralloc4 handle.
+ *
+ * \param[in] staticInfo HDR static info to set. Ignored if null or invalid.
+ * \param[in] dynamicInfo HDR dynamic info to set. Ignored if null or invalid.
+ * \param[out] handle handle of the allocation.
+ * \return C2_OK if successful
+ */
+c2_status_t SetHdrMetadataToGralloc4Handle(
+ const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
+ const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
+ const C2Handle *const handle);
+
} // namespace android
#endif // CODEC2_BUFFER_H_
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index df7d4cf..d9f12a5 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -557,7 +557,7 @@
case AAUDIO_STREAM_STATE_STARTED:
result = mAudioRecord->getPosition(&position);
if (result == OK) {
- mFramesWritten.update32(position);
+ mFramesWritten.update32((int32_t)position);
}
break;
case AAUDIO_STREAM_STATE_STOPPING:
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 17a6d0c..6f1dc92 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -508,7 +508,7 @@
case AAUDIO_STREAM_STATE_PAUSED:
result = mAudioTrack->getPosition(&position);
if (result == OK) {
- mFramesRead.update32(position);
+ mFramesRead.update32((int32_t)position);
}
break;
default:
diff --git a/media/libaaudio/src/utility/MonotonicCounter.h b/media/libaaudio/src/utility/MonotonicCounter.h
index 313ccbd..51eb69b 100644
--- a/media/libaaudio/src/utility/MonotonicCounter.h
+++ b/media/libaaudio/src/utility/MonotonicCounter.h
@@ -41,7 +41,12 @@
}
/**
- * advance the current value to match the counter
+ * Advance the current value to match the counter.
+ *
+ * Note that it will take several million years for the 64-bit
+ * counters to wrap around.
+ * So we do not use __builtin_sub_overflow.
+ * We want to know if overflow happens because of a bug.
*/
void catchUpTo(int64_t counter) {
if ((counter - mCounter64) > 0) {
@@ -74,7 +79,8 @@
* @return current value of the 64-bit counter
*/
int64_t update32(int32_t counter32) {
- int32_t delta = counter32 - mCounter32;
+ int32_t delta;
+ __builtin_sub_overflow(counter32, mCounter32, &delta);
// protect against the mCounter64 going backwards
if (delta > 0) {
mCounter64 += delta;
@@ -108,5 +114,4 @@
int32_t mCounter32 = 0;
};
-
#endif //UTILITY_MONOTONIC_COUNTER_H
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index ea00a5a..4b45909 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -13,6 +13,11 @@
"-Wall",
"-Werror",
],
+
+ sanitize: {
+ integer_overflow: true,
+ misc_undefined: ["bounds"],
+ },
}
cc_test {
@@ -146,6 +151,18 @@
],
}
+cc_test {
+ name: "test_monotonic_counter",
+ defaults: ["libaaudio_tests_defaults"],
+ srcs: ["test_monotonic_counter.cpp"],
+ shared_libs: [
+ "libaaudio_internal",
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
+
cc_binary {
name: "test_return_stop",
defaults: ["libaaudio_tests_defaults"],
diff --git a/media/libaaudio/tests/test_monotonic_counter.cpp b/media/libaaudio/tests/test_monotonic_counter.cpp
new file mode 100644
index 0000000..5cbbaf7
--- /dev/null
+++ b/media/libaaudio/tests/test_monotonic_counter.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright 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.
+ */
+
+/*
+ * Test MonotonicCounter
+ */
+
+#include <iostream>
+
+#include <gtest/gtest.h>
+
+#include "utility/MonotonicCounter.h"
+
+TEST(test_monotonic_counter, builtin_wrap) {
+ int32_t x = 0x7FFFFFF0;
+ int32_t y = 0x80000010;
+ int32_t delta;
+ // delta = y - x; // This would cause a numeric overflow!
+ __builtin_sub_overflow(y, x, &delta);
+ ASSERT_EQ(0x20, delta);
+}
+
+// test updating past some overflow points
+TEST(test_monotonic_counter, mono_counter_update32_wrap) {
+ MonotonicCounter counter;
+ ASSERT_EQ(0, counter.get());
+
+ static constexpr uint32_t x = (uint32_t) 0x7FFFFFF0;
+ counter.update32(x);
+ ASSERT_EQ((int64_t)0x7FFFFFF0, counter.get());
+
+ static constexpr uint32_t y = (uint32_t) 0x80000010;
+ counter.update32(y);
+ ASSERT_EQ((int64_t)0x80000010, counter.get());
+
+ counter.update32(0);
+ ASSERT_EQ((int64_t)0x100000000, counter.get());
+}
+
+TEST(test_monotonic_counter, mono_counter_roundup) {
+ MonotonicCounter counter;
+ static constexpr uint32_t x = 2345;
+ counter.update32(x);
+ ASSERT_EQ((int64_t)x, counter.get());
+
+ counter.roundUp64(100);
+ ASSERT_EQ((int64_t)2400, counter.get());
+}
+
+TEST(test_monotonic_counter, mono_counter_catchup) {
+ MonotonicCounter counter;
+ counter.update32(7654);
+ counter.catchUpTo(5000); // already past 5000 so no change
+ ASSERT_EQ((int64_t)7654, counter.get());
+ counter.catchUpTo(9876); // jumps
+ ASSERT_EQ((int64_t)9876, counter.get());
+}
+
+TEST(test_monotonic_counter, mono_counter_increment) {
+ MonotonicCounter counter;
+ counter.update32(1000);
+ counter.increment(-234); // will not go backwards
+ ASSERT_EQ((int64_t)1000, counter.get());
+ counter.increment(96); // advances
+ ASSERT_EQ((int64_t)1096, counter.get());
+}
+
+TEST(test_monotonic_counter, mono_counter_reset) {
+ MonotonicCounter counter;
+ counter.update32(1000);
+ // Counter is monotonic and should not go backwards.
+ counter.update32(500); // No change because 32-bit counter is already past 1000.
+ ASSERT_EQ((int64_t)1000, counter.get());
+
+ counter.reset32();
+ counter.update32(500);
+ ASSERT_EQ((int64_t)1500, counter.get());
+}
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index b7be3ff..11724e0 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -601,6 +601,11 @@
AudioDeviceType::OUT_SPEAKER,
AudioDeviceDescription::CONNECTION_BT_LE())
},
+ {
+ AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
+ AudioDeviceType::OUT_BROADCAST,
+ AudioDeviceDescription::CONNECTION_BT_LE())
+ },
// AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
{
AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
@@ -1504,6 +1509,8 @@
return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
case AudioOutputFlags::ULTRASOUND:
return AUDIO_OUTPUT_FLAG_ULTRASOUND;
+ case AudioOutputFlags::SPATIALIZER:
+ return AUDIO_OUTPUT_FLAG_SPATIALIZER;
}
return unexpected(BAD_VALUE);
}
@@ -1547,6 +1554,8 @@
return AudioOutputFlags::GAPLESS_OFFLOAD;
case AUDIO_OUTPUT_FLAG_ULTRASOUND:
return AudioOutputFlags::ULTRASOUND;
+ case AUDIO_OUTPUT_FLAG_SPATIALIZER:
+ return AudioOutputFlags::SPATIALIZER;
}
return unexpected(BAD_VALUE);
}
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index ebd488a..edcb86a 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -69,8 +69,9 @@
// We double the size of input buffer for ping pong use of record buffer.
// Assumes audio_is_linear_pcm(format)
- if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) *
- audio_bytes_per_sample(format))) == 0) {
+ const auto sampleSize = audio_channel_count_from_in_mask(channelMask) *
+ audio_bytes_per_sample(format);
+ if (sampleSize == 0 || ((*frameCount = (size * 2) / sampleSize) == 0)) {
ALOGE("%s(): Unsupported configuration: sampleRate %u, format %#x, channelMask %#x",
__func__, sampleRate, format, channelMask);
return BAD_VALUE;
@@ -357,6 +358,12 @@
if (format == AUDIO_FORMAT_DEFAULT) {
format = AUDIO_FORMAT_PCM_16_BIT;
}
+ if (!audio_is_linear_pcm(format)) {
+ // Compressed capture requires direct
+ flags = (audio_input_flags_t) (flags | AUDIO_INPUT_FLAG_DIRECT);
+ ALOGI("%s(): Format %#x is not linear pcm. Setting DIRECT, using flags %#x", __func__,
+ format, flags);
+ }
mFormat = format;
mChannelMask = channelMask;
mSessionId = sessionId;
@@ -396,9 +403,8 @@
goto error;
}
- // AudioFlinger capture only supports linear PCM
- if (!audio_is_valid_format(mFormat) || !audio_is_linear_pcm(mFormat)) {
- errorMessage = StringPrintf("%s: Format %#x is not linear pcm", __func__, mFormat);
+ if (!audio_is_valid_format(mFormat)) {
+ errorMessage = StringPrintf("%s: Format %#x is not valid", __func__, mFormat);
status = BAD_VALUE;
goto error;
}
@@ -718,6 +724,11 @@
if (status == OK) {
timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesRead;
timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0;
+ if (!audio_is_linear_pcm(mFormat)) {
+ // Don't do retrograde corrections or server offset if track is
+ // compressed
+ return OK;
+ }
// server side frame offset in case AudioRecord has been restored.
for (int i = ExtendedTimestamp::LOCATION_SERVER;
i < ExtendedTimestamp::LOCATION_MAX; ++i) {
@@ -1184,7 +1195,13 @@
if (status == DEAD_OBJECT) {
// re-create track, unless someone else has already done so
if (newSequence == oldSequence) {
- status = restoreRecord_l("obtainBuffer");
+ if (!audio_is_linear_pcm(mFormat)) {
+ // If compressed capture, don't attempt to restore the track.
+ // Return a DEAD_OBJECT error and let the caller recreate.
+ tryCounter = 0;
+ } else {
+ status = restoreRecord_l("obtainBuffer");
+ }
if (status != NO_ERROR) {
buffer.mFrameCount = 0;
buffer.mRaw = NULL;
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 16e9ec3..be81481 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -2327,6 +2327,28 @@
return NO_ERROR;
}
+status_t AudioSystem::getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ std::vector<audio_profile>* audioProfiles) {
+ if (attr == nullptr) {
+ return BAD_VALUE;
+ }
+
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+
+ std::vector<media::audio::common::AudioProfile> audioProfilesAidl;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ aps->getDirectProfilesForAttributes(attrAidl, &audioProfilesAidl)));
+ *audioProfiles = VALUE_OR_RETURN_STATUS(convertContainer<std::vector<audio_profile>>(
+ audioProfilesAidl, aidl2legacy_AudioProfile_audio_profile, false /*isInput*/));
+
+ return NO_ERROR;
+}
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index bdf3147..de14e1c 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1120,8 +1120,16 @@
{
using namespace std::chrono_literals;
+ // We use atomic access here for state variables - these are used as hints
+ // to ensure we have ramped down audio.
+ const int priorState = mProxy->getState();
+ const uint32_t priorPosition = mProxy->getPosition().unsignedValue();
+
pause();
+ // Only if we were previously active, do we wait to ramp down the audio.
+ if (priorState != CBLK_STATE_ACTIVE) return true;
+
AutoMutex lock(mLock);
// offload and direct tracks do not wait because pause volume ramp is handled by hardware.
if (isOffloadedOrDirect_l()) return true;
@@ -1129,16 +1137,25 @@
// Wait for the track state to be anything besides pausing.
// This ensures that the volume has ramped down.
constexpr auto SLEEP_INTERVAL_MS = 10ms;
+ constexpr auto POSITION_TIMEOUT_MS = 40ms; // don't wait longer than this for position change.
auto begin = std::chrono::steady_clock::now();
while (true) {
- // wait for state to change
+ // Wait for state and position to change.
+ // After pause() the server state should be PAUSING, but that may immediately
+ // convert to PAUSED by prepareTracks before data is read into the mixer.
+ // Hence we check that the state is not PAUSING and that the server position
+ // has advanced to be a more reliable estimate that the volume ramp has completed.
const int state = mProxy->getState();
+ const uint32_t position = mProxy->getPosition().unsignedValue();
mLock.unlock(); // only local variables accessed until lock.
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - begin);
- if (state != CBLK_STATE_PAUSING) {
- ALOGV("%s: success state:%d after %lld ms", __func__, state, elapsed.count());
+ if (state != CBLK_STATE_PAUSING &&
+ (elapsed >= POSITION_TIMEOUT_MS || position != priorPosition)) {
+ ALOGV("%s: success state:%d, position:%u after %lld ms"
+ " (prior state:%d prior position:%u)",
+ __func__, state, position, elapsed.count(), priorState, priorPosition);
return true;
}
std::chrono::milliseconds remaining = timeout - elapsed;
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 0be7f1b..c3e8dfb 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -48,6 +48,7 @@
import android.media.audio.common.AudioDeviceDescription;
import android.media.audio.common.AudioFormatDescription;
import android.media.audio.common.AudioMode;
+import android.media.audio.common.AudioProfile;
import android.media.audio.common.AudioOffloadInfo;
import android.media.audio.common.AudioSource;
import android.media.audio.common.AudioStreamType;
@@ -383,6 +384,12 @@
/**
* Query how the direct playback is currently supported on the device.
*/
- AudioDirectMode getDirectPlaybackSupport(in AudioAttributesInternal attr,
+ AudioDirectMode getDirectPlaybackSupport(in AudioAttributesInternal attr,
in AudioConfig config);
+
+ /**
+ * Query audio profiles available for direct playback on the current output device(s)
+ * for the specified audio attributes.
+ */
+ AudioProfile[] getDirectProfilesForAttributes(in AudioAttributesInternal attr);
}
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index dfabd55..227d823 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -123,6 +123,21 @@
}
/**
+ * A generic template that helps convert containers of convertible types
+ * using an item conversion function with an additional parameter.
+ */
+template<typename OutputContainer, typename InputContainer, typename Func, typename Parameter>
+ConversionResult<OutputContainer>
+convertContainer(const InputContainer& input, const Func& itemConversion, const Parameter& param) {
+ OutputContainer output;
+ auto ins = std::inserter(output, output.begin());
+ for (const auto& item : input) {
+ *ins = VALUE_OR_RETURN(itemConversion(item, param));
+ }
+ return output;
+}
+
+/**
* A generic template that helps to "zip" two input containers of the same size
* into a single vector of converted types. The conversion function must
* thus accept two arguments.
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 8abd8fc..4280a6a 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -552,6 +552,16 @@
audio_direct_mode_t *directMode);
+ /**
+ * Query which direct audio profiles are available for the specified audio attributes.
+ * @param attr audio attributes describing the playback use case
+ * @param audioProfiles out: a vector of audio profiles
+ * @return NO_ERROR in case of success, DEAD_OBJECT, NO_INIT, BAD_VALUE, PERMISSION_DENIED
+ * in case of error.
+ */
+ static status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ std::vector<audio_profile>* audioProfiles);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 9a67bb7..734fa9c 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -154,6 +154,26 @@
ConversionResult<AudioProfile::Aidl>
AudioProfile::toParcelable(bool isInput) const {
+ media::audio::common::AudioProfile parcelable = VALUE_OR_RETURN(toCommonParcelable(isInput));
+ media::AudioProfileSys parcelableSys;
+ parcelableSys.isDynamicFormat = mIsDynamicFormat;
+ parcelableSys.isDynamicChannels = mIsDynamicChannels;
+ parcelableSys.isDynamicRate = mIsDynamicRate;
+ return std::make_pair(parcelable, parcelableSys);
+}
+
+ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
+ const AudioProfile::Aidl& aidl, bool isInput) {
+ sp<AudioProfile> legacy = VALUE_OR_RETURN(fromCommonParcelable(aidl.first, isInput));
+ const auto& parcelableSys = aidl.second;
+ legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
+ legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
+ legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
+ return legacy;
+}
+
+ConversionResult<media::audio::common::AudioProfile>
+AudioProfile::toCommonParcelable(bool isInput) const {
media::audio::common::AudioProfile parcelable;
parcelable.name = mName;
parcelable.format = VALUE_OR_RETURN(
@@ -164,44 +184,35 @@
// of using 'legacy2aidl_audio_profile_AudioProfile' from AidlConversion.
parcelable.channelMasks = VALUE_OR_RETURN(
convertContainer<std::vector<AudioChannelLayout>>(
- mChannelMasks,
- [isInput](audio_channel_mask_t m) {
- return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
- }));
+ mChannelMasks,
+ [isInput](audio_channel_mask_t m) {
+ return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+ }));
parcelable.sampleRates = VALUE_OR_RETURN(
convertContainer<std::vector<int32_t>>(mSamplingRates,
convertIntegral<int32_t, uint32_t>));
parcelable.encapsulationType = VALUE_OR_RETURN(
legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(mEncapsulationType));
- media::AudioProfileSys parcelableSys;
- parcelableSys.isDynamicFormat = mIsDynamicFormat;
- parcelableSys.isDynamicChannels = mIsDynamicChannels;
- parcelableSys.isDynamicRate = mIsDynamicRate;
- return std::make_pair(parcelable, parcelableSys);
+ return parcelable;
}
-ConversionResult<sp<AudioProfile>> AudioProfile::fromParcelable(
- const AudioProfile::Aidl& aidl, bool isInput) {
+ConversionResult<sp<AudioProfile>> AudioProfile::fromCommonParcelable(
+ const media::audio::common::AudioProfile& aidl, bool isInput) {
sp<AudioProfile> legacy = new AudioProfile();
- const auto& parcelable = aidl.first;
- legacy->mName = parcelable.name;
+ legacy->mName = aidl.name;
legacy->mFormat = VALUE_OR_RETURN(
- aidl2legacy_AudioFormatDescription_audio_format_t(parcelable.format));
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
legacy->mChannelMasks = VALUE_OR_RETURN(
- convertContainer<ChannelMaskSet>(parcelable.channelMasks,
- [isInput](const AudioChannelLayout& l) {
- return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
- }));
+ convertContainer<ChannelMaskSet>(aidl.channelMasks,
+ [isInput](const AudioChannelLayout& l) {
+ return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+ }));
legacy->mSamplingRates = VALUE_OR_RETURN(
- convertContainer<SampleRateSet>(parcelable.sampleRates,
+ convertContainer<SampleRateSet>(aidl.sampleRates,
convertIntegral<uint32_t, int32_t>));
legacy->mEncapsulationType = VALUE_OR_RETURN(
aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
- parcelable.encapsulationType));
- const auto& parcelableSys = aidl.second;
- legacy->mIsDynamicFormat = parcelableSys.isDynamicFormat;
- legacy->mIsDynamicChannels = parcelableSys.isDynamicChannels;
- legacy->mIsDynamicRate = parcelableSys.isDynamicRate;
+ aidl.encapsulationType));
return legacy;
}
@@ -215,6 +226,16 @@
return legacy->toParcelable(isInput);
}
+ConversionResult<sp<AudioProfile>>
+aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile& aidl, bool isInput) {
+ return AudioProfile::fromCommonParcelable(aidl, isInput);
+}
+
+ConversionResult<media::audio::common::AudioProfile>
+legacy2aidl_AudioProfile_common(const sp<AudioProfile>& legacy, bool isInput) {
+ return legacy->toCommonParcelable(isInput);
+}
+
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index d7cddb7..c3a0fb2 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -85,6 +85,11 @@
static ConversionResult<sp<AudioProfile>> fromParcelable(
const Aidl& aidl, bool isInput);
+ ConversionResult<media::audio::common::AudioProfile>
+ toCommonParcelable(bool isInput) const;
+ static ConversionResult<sp<AudioProfile>> fromCommonParcelable(
+ const media::audio::common::AudioProfile& aidl, bool isInput);
+
private:
std::string mName;
@@ -108,6 +113,11 @@
ConversionResult<AudioProfile::Aidl>
legacy2aidl_AudioProfile(const sp<AudioProfile>& legacy, bool isInput);
+ConversionResult<sp<AudioProfile>>
+aidl2legacy_AudioProfile_common(const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile>
+legacy2aidl_AudioProfile_common(const sp<AudioProfile>& legacy, bool isInput);
+
class AudioProfileVector : public std::vector<sp<AudioProfile>>
{
public:
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 47acb19..209094c 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -205,6 +205,16 @@
status != OK) {
return status;
}
+
+#if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1)
+ //TODO: b/193496180 use spatializer flag at audio HAL when available
+ if ((flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
+ flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_SPATIALIZER);
+ flags = (audio_output_flags_t)
+ (flags | AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+ }
+#endif
+
CoreUtils::AudioOutputFlags hidlFlags;
if (status_t status = CoreUtils::audioOutputFlagsFromHal(flags, &hidlFlags); status != OK) {
return status;
diff --git a/media/libheadtracking/PoseProcessingGraph.png b/media/libheadtracking/PoseProcessingGraph.png
index 0363068..2b4ea68 100644
--- a/media/libheadtracking/PoseProcessingGraph.png
+++ b/media/libheadtracking/PoseProcessingGraph.png
Binary files differ
diff --git a/media/libheadtracking/README.md b/media/libheadtracking/README.md
index 3d5b71a..5ec157b 100644
--- a/media/libheadtracking/README.md
+++ b/media/libheadtracking/README.md
@@ -157,6 +157,14 @@
module may indicate that the user is likely not in front of the screen via the
“valid” output.
+## Stillness Detector
+
+The stillness detector blocks detect when their incoming pose stream has been
+stable for a given amount of time (allowing for a configurable amount of error).
+When the head is considered still, we would trigger a recenter operation
+(“auto-recentering”) and when the screen is considered not still, the mode
+selector would use this information to force static mode.
+
### Mode Selector
The Mode Selector block aggregates the various sources of pose information into
@@ -168,7 +176,8 @@
- If the desired mode is static, the actual mode is static.
- If the desired mode is world-relative:
- - If head poses are fresh, the actual mode is world-relative.
+ - If head and screen poses are fresh and the screen is stable (stillness
+ detector output is true), the actual mode is world-relative.
- Otherwise the actual mode is static.
- If the desired mode is screen-relative:
- If head and screen poses are fresh and the ‘valid’ signal is asserted, the
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index ec5e1ec..0e96b03 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -133,14 +133,14 @@
{
std::lock_guard lock(mMutex);
- mEnabledSensorFormats.emplace(sensor, format);
+ mEnabledSensorsExtra.emplace(sensor, SensorExtra{ .format = format });
}
// Enable the sensor.
if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
ALOGE("Failed to enable sensor");
std::lock_guard lock(mMutex);
- mEnabledSensorFormats.erase(sensor);
+ mEnabledSensorsExtra.erase(sensor);
return false;
}
@@ -151,7 +151,7 @@
void stopSensor(int handle) override {
mEnabledSensors.erase(handle);
std::lock_guard lock(mMutex);
- mEnabledSensorFormats.erase(handle);
+ mEnabledSensorsExtra.erase(handle);
}
private:
@@ -159,6 +159,7 @@
kUnknown,
kQuaternion,
kRotationVectorsAndFlags,
+ kRotationVectorsAndDiscontinuityCount,
};
struct PoseEvent {
@@ -167,13 +168,18 @@
bool isNewReference;
};
+ struct SensorExtra {
+ DataFormat format;
+ std::optional<int32_t> discontinuityCount;
+ };
+
sp<Looper> mLooper;
Listener* const mListener;
SensorManager* const mSensorManager;
std::thread mThread;
std::mutex mMutex;
std::map<int32_t, SensorEnableGuard> mEnabledSensors;
- std::map<int32_t, DataFormat> mEnabledSensorFormats GUARDED_BY(mMutex);
+ std::map<int32_t, SensorExtra> mEnabledSensorsExtra GUARDED_BY(mMutex);
sp<SensorEventQueue> mQueue;
// We must do some of the initialization operations on the worker thread, because the API relies
@@ -248,17 +254,16 @@
}
void handleEvent(const ASensorEvent& event) {
- DataFormat format;
+ PoseEvent value;
{
std::lock_guard lock(mMutex);
- auto iter = mEnabledSensorFormats.find(event.sensor);
- if (iter == mEnabledSensorFormats.end()) {
+ auto iter = mEnabledSensorsExtra.find(event.sensor);
+ if (iter == mEnabledSensorsExtra.end()) {
// This can happen if we have any pending events shortly after stopping.
return;
}
- format = iter->second;
+ value = parseEvent(event, iter->second.format, &iter->second.discontinuityCount);
}
- auto value = parseEvent(event, format);
mListener->onPose(event.timestamp, event.sensor, value.pose, value.twist,
value.isNewReference);
}
@@ -274,6 +279,10 @@
return DataFormat::kQuaternion;
}
+ if (sensor->getType() == ASENSOR_TYPE_HEAD_TRACKER) {
+ return DataFormat::kRotationVectorsAndDiscontinuityCount;
+ }
+
if (sensor->getStringType() == "com.google.hardware.sensor.hid_dynamic.headtracker") {
return DataFormat::kRotationVectorsAndFlags;
}
@@ -313,8 +322,8 @@
return std::nullopt;
}
- static PoseEvent parseEvent(const ASensorEvent& event, DataFormat format) {
- // TODO(ytai): Add more types.
+ static PoseEvent parseEvent(const ASensorEvent& event, DataFormat format,
+ std::optional<int32_t>* discontinutyCount) {
switch (format) {
case DataFormat::kQuaternion: {
Eigen::Quaternionf quat(event.data[3], event.data[0], event.data[1], event.data[2]);
@@ -338,6 +347,21 @@
(flags & (1 << 0)) != 0};
}
+ case DataFormat::kRotationVectorsAndDiscontinuityCount: {
+ Eigen::Vector3f rotation = {event.head_tracker.rx, event.head_tracker.ry,
+ event.head_tracker.rz};
+ Eigen::Vector3f twist = {event.head_tracker.vx, event.head_tracker.vy,
+ event.head_tracker.rz};
+ Eigen::Quaternionf quat = rotationVectorToQuaternion(rotation);
+ bool isNewReference =
+ !discontinutyCount->has_value() ||
+ discontinutyCount->value() != event.head_tracker.discontinuity_count;
+ *discontinutyCount = event.head_tracker.discontinuity_count;
+
+ return PoseEvent{Pose3f(quat), Twist3f(Eigen::Vector3f::Zero(), twist),
+ isNewReference};
+ }
+
default:
LOG_ALWAYS_FATAL("Unexpected sensor type: %d", static_cast<int>(format));
}
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index fcac551..b28ae70 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -485,6 +485,11 @@
mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
break;
}
+ case kHeifColorFormat_RGBA_1010102:
+ {
+ mOutputColor = HAL_PIXEL_FORMAT_RGBA_1010102;
+ break;
+ }
default:
ALOGE("Unsupported output color format %d", heifColor);
return false;
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
index 9073672..fa51aef 100644
--- a/media/libheif/include/HeifDecoderAPI.h
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -23,9 +23,10 @@
* The output color pixel format of heif decoder.
*/
typedef enum {
- kHeifColorFormat_RGB565 = 0,
- kHeifColorFormat_RGBA_8888 = 1,
- kHeifColorFormat_BGRA_8888 = 2,
+ kHeifColorFormat_RGB565 = 0,
+ kHeifColorFormat_RGBA_8888 = 1,
+ kHeifColorFormat_BGRA_8888 = 2,
+ kHeifColorFormat_RGBA_1010102 = 3,
} HeifColorFormat;
/*
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 7f0a045..4247375 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -25,6 +25,9 @@
* 2) Consistent behavior and documentation.
*/
+#define AMEDIAMETRICS_INITIAL_MAX_VOLUME (0.f)
+#define AMEDIAMETRICS_INITIAL_MIN_VOLUME (1.f)
+
/*
* Taxonomy of audio keys
*
@@ -116,6 +119,11 @@
#define AMEDIAMETRICS_PROP_DEVICETIMENS "deviceTimeNs" // int64_t playback/record time
#define AMEDIAMETRICS_PROP_DEVICEVOLUME "deviceVolume" // double - average device volume
+#define AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS "deviceMaxVolumeDurationNs" // int64_t
+#define AMEDIAMETRICS_PROP_DEVICEMAXVOLUME "deviceMaxVolume" // double - maximum device volume
+#define AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS "deviceMinVolumeDurationNs" // int64_t
+#define AMEDIAMETRICS_PROP_DEVICEMINVOLUME "deviceMinVolume" // double - minimum device volume
+
#define AMEDIAMETRICS_PROP_DIRECTION "direction" // string AAudio input or output
#define AMEDIAMETRICS_PROP_DURATIONNS "durationNs" // int64 duration time span
#define AMEDIAMETRICS_PROP_ENCODING "encoding" // string value of format
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 05f7365..cd411ea 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -30,7 +30,7 @@
#include "MediaPlayerFactory.h"
#include "TestPlayerStub.h"
-#include "nuplayer/NuPlayerDriver.h"
+#include <nuplayer/NuPlayerDriver.h>
namespace android {
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c7a7a3a..3b5e1e2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -82,7 +82,7 @@
#include "MediaPlayerFactory.h"
#include "TestPlayerStub.h"
-#include "nuplayer/NuPlayerDriver.h"
+#include <nuplayer/NuPlayerDriver.h>
static const int kDumpLockRetries = 50;
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 89ba584..71b8c2b 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -37,6 +37,14 @@
"StreamingSource.cpp",
],
+ local_include_dirs: [
+ "include/nuplayer",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
header_libs: [
"libmediadrm_headers",
"libmediametrics_headers",
diff --git a/media/libmediaplayerservice/nuplayer/AWakeLock.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/AWakeLock.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/AWakeLock.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/AWakeLock.h
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/GenericSource.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/GenericSource.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/GenericSource.h
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/HTTPLiveSource.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/HTTPLiveSource.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayer.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayer.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayer.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerCCDecoder.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerCCDecoder.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDecoder.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDecoder.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDecoderBase.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDecoderBase.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDecoderPassThrough.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDecoderPassThrough.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDriver.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDriver.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerDrm.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerSource.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerSource.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerSource.h
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerStreamListener.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerStreamListener.h
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/RTPSource.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/RTPSource.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/RTPSource.h
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/RTSPSource.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/RTSPSource.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/RTSPSource.h
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/StreamingSource.h
similarity index 100%
rename from media/libmediaplayerservice/nuplayer/StreamingSource.h
rename to media/libmediaplayerservice/nuplayer/include/nuplayer/StreamingSource.h
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 3a01925..656267c 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -684,6 +684,7 @@
}
constexpr char FEATURE_AdaptivePlayback[] = "adaptive-playback";
+constexpr char FEATURE_EncodingStatistics[] = "encoding-statistics";
constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
constexpr char FEATURE_PartialFrame[] = "partial-frame";
constexpr char FEATURE_QpBounds[] = "qp-bounds";
@@ -737,6 +738,14 @@
constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
+constexpr int32_t PICTURE_TYPE_I = 1;
+constexpr int32_t PICTURE_TYPE_P = 2;
+constexpr int32_t PICTURE_TYPE_B = 3;
+constexpr int32_t PICTURE_TYPE_UNKNOWN = 0;
+
+constexpr int32_t VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1;
+constexpr int32_t VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0;
+
constexpr char KEY_AAC_DRC_ALBUM_MODE[] = "aac-drc-album-mode";
constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
@@ -795,6 +804,7 @@
constexpr char KEY_OPERATING_RATE[] = "operating-rate";
constexpr char KEY_OUTPUT_REORDER_DEPTH[] = "output-reorder-depth";
constexpr char KEY_PCM_ENCODING[] = "pcm-encoding";
+constexpr char KEY_PICTURE_TYPE[] = "picture_type";
constexpr char KEY_PIXEL_ASPECT_RATIO_HEIGHT[] = "sar-height";
constexpr char KEY_PIXEL_ASPECT_RATIO_WIDTH[] = "sar-width";
constexpr char KEY_PREPEND_HEADER_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames";
@@ -811,6 +821,8 @@
constexpr char KEY_TILE_HEIGHT[] = "tile-height";
constexpr char KEY_TILE_WIDTH[] = "tile-width";
constexpr char KEY_TRACK_ID[] = "track-id";
+constexpr char KEY_VIDEO_ENCODING_STATISTICS_LEVEL[] = "video-encoding-statistics-level";
+constexpr char KEY_VIDEO_QP_AVERAGE[] = "video-qp-average";
constexpr char KEY_VIDEO_QP_B_MAX[] = "video-qp-b-max";
constexpr char KEY_VIDEO_QP_B_MIN[] = "video-qp-b-min";
constexpr char KEY_VIDEO_QP_I_MAX[] = "video-qp-i-max";
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 69ab242..923453a 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -361,6 +361,7 @@
"mpegh-reference-channel-layout";
EXPORT const char* AMEDIAFORMAT_KEY_OPERATING_RATE = "operating-rate";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_ENCODING = "pcm-encoding";
+EXPORT const char* AMEDIAFORMAT_KEY_PICTURE_TYPE = "picture-type";
EXPORT const char* AMEDIAFORMAT_KEY_PRIORITY = "priority";
EXPORT const char* AMEDIAFORMAT_KEY_PROFILE = "profile";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN = "pcm-big-endian";
@@ -394,6 +395,9 @@
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
+EXPORT const char* AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL =
+ "video-encoding-statistics-level";
+EXPORT const char* AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE = "video-qp-average";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_B_MAX = "video-qp-b-max";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_B_MIN = "video-qp-b-min";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_I_MAX = "video-qp-i-max";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 2d2fcc0..2195657 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -311,6 +311,10 @@
extern const char* AMEDIAFORMAT_KEY_LAST_SAMPLE_INDEX_IN_CHUNK __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_SAMPLE_TIME_BEFORE_APPEND __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_PICTURE_TYPE __INTRODUCED_IN(33);
+extern const char* AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL __INTRODUCED_IN(33);
+extern const char* AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE __INTRODUCED_IN(33);
+
extern const char* AMEDIAFORMAT_VIDEO_QP_B_MAX __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_VIDEO_QP_B_MIN __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_VIDEO_QP_I_MAX __INTRODUCED_IN(31);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ed4666f..99f81c7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2590,7 +2590,7 @@
{
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
if (outHwDev == NULL) {
- return 0;
+ return nullptr;
}
if (*output == AUDIO_IO_HANDLE_NONE) {
@@ -2599,9 +2599,17 @@
// Audio Policy does not currently request a specific output handle.
// If this is ever needed, see openInput_l() for example code.
ALOGE("openOutput_l requested output handle %d is not AUDIO_IO_HANDLE_NONE", *output);
- return 0;
+ return nullptr;
}
+#ifndef MULTICHANNEL_EFFECT_CHAIN
+ if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
+ ALOGE("openOutput_l() cannot create spatializer thread "
+ "without #define MULTICHANNEL_EFFECT_CHAIN");
+ return nullptr;
+ }
+#endif
+
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
// FOR TESTING ONLY:
@@ -2646,18 +2654,11 @@
return thread;
} else {
sp<PlaybackThread> thread;
- //TODO: b/193496180 use spatializer flag at audio HAL when available
- if (flags == (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST
- | AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
-#ifdef MULTICHANNEL_EFFECT_CHAIN
+ if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
thread = new SpatializerThread(this, outputStream, *output,
mSystemReady, mixerConfig);
- ALOGD("openOutput_l() created spatializer output: ID %d thread %p",
+ ALOGV("openOutput_l() created spatializer output: ID %d thread %p",
*output, thread.get());
-#else
- ALOGE("openOutput_l() cannot create spatializer thread "
- "without #define MULTICHANNEL_EFFECT_CHAIN");
-#endif
} else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
thread = new OffloadThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created offload output: ID %d thread %p",
@@ -2683,7 +2684,7 @@
}
}
- return 0;
+ return nullptr;
}
status_t AudioFlinger::openOutput(const media::OpenOutputRequest& request,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 61537a8..982893d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1864,6 +1864,8 @@
bool isTimestampCorrectionEnabled() const override {
// checks popcount for exactly one device.
+ // Is currently disabled. Before enabling,
+ // verify compressed record timestamps.
return audio_is_input_device(mTimestampCorrectedDevice)
&& inDeviceType() == mTimestampCorrectedDevice;
}
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
index 7fb69be..30d69ab 100644
--- a/services/audioflinger/TrackMetrics.h
+++ b/services/audioflinger/TrackMetrics.h
@@ -116,6 +116,21 @@
mDeviceStartupMs.add(startupMs);
}
+ void updateMinMaxVolume(int64_t durationNs, double deviceVolume) {
+ if (deviceVolume > mMaxVolume) {
+ mMaxVolume = deviceVolume;
+ mMaxVolumeDurationNs = durationNs;
+ } else if (deviceVolume == mMaxVolume) {
+ mMaxVolumeDurationNs += durationNs;
+ }
+ if (deviceVolume < mMinVolume) {
+ mMinVolume = deviceVolume;
+ mMinVolumeDurationNs = durationNs;
+ } else if (deviceVolume == mMinVolume) {
+ mMinVolumeDurationNs += durationNs;
+ }
+ }
+
// may be called multiple times during an interval
void logVolume(float volume) {
const int64_t timeNs = systemTime();
@@ -123,10 +138,13 @@
if (mStartVolumeTimeNs == 0) {
mDeviceVolume = mVolume = volume;
mLastVolumeChangeTimeNs = mStartVolumeTimeNs = timeNs;
+ updateMinMaxVolume(0, mVolume);
return;
}
+ const int64_t durationNs = timeNs - mLastVolumeChangeTimeNs;
+ updateMinMaxVolume(durationNs, mVolume);
mDeviceVolume = (mDeviceVolume * (mLastVolumeChangeTimeNs - mStartVolumeTimeNs) +
- mVolume * (timeNs - mLastVolumeChangeTimeNs)) / (timeNs - mStartVolumeTimeNs);
+ mVolume * durationNs) / (timeNs - mStartVolumeTimeNs);
mVolume = volume;
mLastVolumeChangeTimeNs = timeNs;
}
@@ -157,7 +175,11 @@
.set(AMEDIAMETRICS_PROP_EVENT, eventName)
.set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
if (mIsOut) {
- item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume);
+ item.set(AMEDIAMETRICS_PROP_DEVICEVOLUME, mDeviceVolume)
+ .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, mMaxVolumeDurationNs)
+ .set(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, mMaxVolume)
+ .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, mMinVolumeDurationNs)
+ .set(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, mMinVolume);
}
if (mDeviceLatencyMs.getN() > 0) {
item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean())
@@ -185,6 +207,10 @@
mDeviceVolume = 0.f;
mStartVolumeTimeNs = 0;
mLastVolumeChangeTimeNs = 0;
+ mMinVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ mMaxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ mMinVolumeDurationNs = 0;
+ mMaxVolumeDurationNs = 0;
mDeviceLatencyMs.reset();
mDeviceStartupMs.reset();
@@ -214,6 +240,12 @@
int64_t mStartVolumeTimeNs GUARDED_BY(mLock) = 0;
int64_t mLastVolumeChangeTimeNs GUARDED_BY(mLock) = 0;
+ // Min/Max volume
+ double mMinVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ double mMaxVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ int64_t mMinVolumeDurationNs GUARDED_BY(mLock) = 0;
+ int64_t mMaxVolumeDurationNs GUARDED_BY(mLock) = 0;
+
// latency and startup for each interval.
audio_utils::Statistics<double> mDeviceLatencyMs GUARDED_BY(mLock);
audio_utils::Statistics<double> mDeviceStartupMs GUARDED_BY(mLock);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 233865f..279ff3d 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -2635,6 +2635,8 @@
// ALOGD("FrameTime: %lld %lld", (long long)ft.frames, (long long)ft.timeNs);
mKernelFrameTime.store(ft);
if (!audio_is_linear_pcm(mFormat)) {
+ // Stream is direct, return provided timestamp with no conversion
+ mServerProxy->setTimestamp(timestamp);
return;
}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 65ddf3a..e8e478b 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -406,8 +406,11 @@
*/
virtual audio_direct_mode_t getDirectPlaybackSupport(const audio_attributes_t *attr,
const audio_config_t *config) = 0;
-};
+ // retrieves the list of available direct audio profiles for the given audio attributes
+ virtual status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ AudioProfileVector& audioProfiles) = 0;
+};
// Audio Policy client Interface
class AudioPolicyClientInterface
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 736f8b2..f0636a0 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -127,6 +127,7 @@
case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
case AUDIO_DEVICE_OUT_USB_HEADSET:
case AUDIO_DEVICE_OUT_BLE_HEADSET:
+ case AUDIO_DEVICE_OUT_BLE_BROADCAST:
return DEVICE_CATEGORY_HEADSET;
case AUDIO_DEVICE_OUT_HEARING_AID:
return DEVICE_CATEGORY_HEARING_AID;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index a8fd856..cf1f64c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -202,20 +202,6 @@
{AUDIO_FORMAT_AC4, {}}};
}
- //TODO: b/193496180 use spatializer flag at audio HAL when available
- // until then, use DEEP_BUFFER+FAST flag combo to indicate the spatializer output profile
- void convertSpatializerFlag()
- {
- for (const auto& hwModule : mHwModules) {
- for (const auto& curProfile : hwModule->getOutputProfiles()) {
- if (curProfile->getFlags()
- == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
- curProfile->setFlags(AUDIO_OUTPUT_FLAG_SPATIALIZER);
- }
- }
- }
- }
-
private:
static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 235e4aa..663c80a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -565,10 +565,11 @@
mFlags = (audio_output_flags_t)(mFlags | flags);
- //TODO: b/193496180 use spatializer flag at audio HAL when available
- audio_output_flags_t halFlags = mFlags;
- if ((mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
- halFlags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+ // If no mixer config is specified for a spatializer output, default to 5.1 for proper
+ // configuration of the final downmixer or spatializer
+ if ((mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0
+ && mixerConfig == nullptr) {
+ lMixerConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
}
ALOGV("opening output for device %s profile %p name %s",
@@ -580,7 +581,7 @@
&lMixerConfig,
device,
&mLatency,
- halFlags);
+ mFlags);
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 4dfef73..69cad9b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -483,7 +483,14 @@
if (!flags.empty()) {
// Source role
if (portRole == AUDIO_PORT_ROLE_SOURCE) {
- mixPort->setFlags(OutputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str()));
+ //TODO: b/193496180 use spatializer flag at audio HAL when available until then,
+ // use DEEP_BUFFER+FAST flag combo to indicate the spatializer output profile
+ uint32_t intFlags =
+ OutputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str());
+ if (intFlags == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
+ intFlags = AUDIO_OUTPUT_FLAG_SPATIALIZER;
+ }
+ mixPort->setFlags(intFlags);
} else {
// Sink role
mixPort->setFlags(InputFlagConverter::maskFromString(flags, mFlagsSeparator.c_str()));
diff --git a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
index b3f8947..06cc799 100644
--- a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
+++ b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
@@ -85,6 +85,7 @@
case AUDIO_DEVICE_OUT_HEARING_AID:
case AUDIO_DEVICE_OUT_BLE_HEADSET:
case AUDIO_DEVICE_OUT_BLE_SPEAKER:
+ case AUDIO_DEVICE_OUT_BLE_BROADCAST:
return GROUP_BT_A2DP;
default:
return GROUP_NONE;
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 88d267f..4c3d92c 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -650,7 +650,7 @@
// there is a preferred device, is it available?
preferredAvailableDevVec =
availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
- if (preferredAvailableDevVec.size() == preferredAvailableDevVec.size()) {
+ if (preferredAvailableDevVec.size() == preferredStrategyDevices.size()) {
ALOGVV("%s using pref device %s for strategy %u",
__func__, preferredAvailableDevVec.toString().c_str(), strategy);
return preferredAvailableDevVec;
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 654e4bf..dff36e2 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -30,6 +30,7 @@
#include <libxml/parser.h>
#include <libxml/xinclude.h>
#include <media/AudioPolicy.h>
+#include <media/AudioProfile.h>
#include <media/PatchBuilder.h>
#include <media/RecordingActivityTracker.h>
@@ -842,6 +843,7 @@
void process() override;
void fuzzGetDirectPlaybackSupport();
+ void fuzzGetDirectProfilesForAttributes();
protected:
void setDeviceConnectionState();
@@ -909,11 +911,25 @@
}
}
+void AudioPolicyManagerFuzzerDeviceConnection::fuzzGetDirectProfilesForAttributes() {
+ const uint32_t numTestCases = mFdp->ConsumeIntegralInRange<uint32_t>(1, 10);
+ for (int i = 0; i < numTestCases; ++i) {
+ AudioProfileVector audioProfiles;
+ audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+ attr.content_type = getValueFromVector<audio_content_type_t>(mFdp, kAudioContentTypes);
+ attr.usage = getValueFromVector<audio_usage_t>(mFdp, kAudioUsages);
+ attr.source = getValueFromVector<audio_source_t>(mFdp, kAudioSources);
+ attr.flags = getValueFromVector<audio_flags_mask_t>(mFdp, kAudioFlagMasks);
+ mManager->getDirectProfilesForAttributes(&attr, audioProfiles);
+ }
+}
+
void AudioPolicyManagerFuzzerDeviceConnection::process() {
if (initialize()) {
setDeviceConnectionState();
explicitlyRoutingAfterConnection();
fuzzGetDirectPlaybackSupport();
+ fuzzGetDirectProfilesForAttributes();
fuzzPatchCreation();
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 5590ba2..bd295ce 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1392,7 +1392,8 @@
}
if (mSpatializerOutput != nullptr
- && canBeSpatialized(attr, config, devices.toTypeAddrVector())) {
+ && canBeSpatializedInt(attr, config,
+ devices.toTypeAddrVector(), false /* allowCurrentOutputReconfig */)) {
return mSpatializerOutput->mIoHandle;
}
@@ -1688,7 +1689,8 @@
// other criteria
static const audio_output_flags_t kFunctionalFlags = (audio_output_flags_t)
(AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_INCALL_MUSIC |
- AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM | AUDIO_OUTPUT_FLAG_ULTRASOUND);
+ AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM | AUDIO_OUTPUT_FLAG_ULTRASOUND |
+ AUDIO_OUTPUT_FLAG_SPATIALIZER);
// Flags expressing a performance request: have lower priority than serving
// requested sampling rate or channel mask
static const audio_output_flags_t kPerformanceFlags = (audio_output_flags_t)
@@ -2396,7 +2398,7 @@
break; // success
} else if (profileFlags & AUDIO_INPUT_FLAG_RAW) {
profileFlags = (audio_input_flags_t) (profileFlags & ~AUDIO_INPUT_FLAG_RAW); // retry
- } else if (profileFlags != AUDIO_INPUT_FLAG_NONE) {
+ } else if (profileFlags != AUDIO_INPUT_FLAG_NONE && audio_is_linear_pcm(config->format)) {
profileFlags = AUDIO_INPUT_FLAG_NONE; // retry
} else { // fail
ALOGW("%s could not find profile for device %s, sampling rate %u, format %#x, "
@@ -3831,6 +3833,47 @@
return directMode;
}
+status_t AudioPolicyManager::getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ AudioProfileVector& audioProfilesVector) {
+ AudioDeviceTypeAddrVector devices;
+ status_t status = getDevicesForAttributes(*attr, &devices);
+ if (status != OK) {
+ return status;
+ }
+ ALOGV("%s: found %zu output devices for attributes.", __func__, devices.size());
+ if (devices.empty()) {
+ return OK; // no output devices for the attributes
+ }
+
+ for (const auto& hwModule : mHwModules) {
+ for (const auto& curProfile : hwModule->getOutputProfiles()) {
+ if (!curProfile->asAudioPort()->isDirectOutput()) {
+ continue;
+ }
+ // Allow only profiles that support all the available and routed devices
+ DeviceVector supportedDevices = curProfile->getSupportedDevices();
+ if (supportedDevices.getDevicesFromDeviceTypeAddrVec(devices).size()
+ != devices.size()) {
+ continue;
+ }
+
+ const auto audioProfiles = curProfile->asAudioPort()->getAudioProfiles();
+ ALOGV("%s: found direct profile (%s) with %zu audio profiles.",
+ __func__, curProfile->getTagName().c_str(), audioProfiles.size());
+ for (const auto& audioProfile : audioProfiles) {
+ if (audioProfile->isValid() && !audioProfilesVector.contains(audioProfile)
+ // TODO - why do we have same PCM format with both dynamic and non dynamic format
+ && audioProfile->isDynamicFormat()) {
+ ALOGV("%s: adding audio profile with encoding (%d).",
+ __func__, audioProfile->getFormat());
+ audioProfilesVector.add(audioProfile);
+ }
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role,
audio_port_type_t type,
unsigned int *num_ports,
@@ -4989,9 +5032,10 @@
}
}
-bool AudioPolicyManager::canBeSpatialized(const audio_attributes_t *attr,
+bool AudioPolicyManager::canBeSpatializedInt(const audio_attributes_t *attr,
const audio_config_t *config,
- const AudioDeviceTypeAddrVector &devices) const
+ const AudioDeviceTypeAddrVector &devices,
+ bool allowCurrentOutputReconfig) const
{
// The caller can have the audio attributes criteria ignored by either passing a null ptr or
// the AUDIO_ATTRIBUTES_INITIALIZER value.
@@ -5027,7 +5071,8 @@
if (!isChannelMaskSpatialized(config->channel_mask)) {
return false;
}
- if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile) {
+ if (!allowCurrentOutputReconfig && mSpatializerOutput != nullptr
+ && mSpatializerOutput->mProfile == profile) {
if ((config->channel_mask & mSpatializerOutput->mMixerChannelMask)
!= config->channel_mask) {
return false;
@@ -5048,7 +5093,8 @@
audio_config_base_t clientConfig = client->config();
audio_config_t config = audio_config_initializer(&clientConfig);
if (desc != mSpatializerOutput
- && canBeSpatialized(&attr, &config, devicesTypeAddress)) {
+ && canBeSpatializedInt(&attr, &config,
+ devicesTypeAddress, false /* allowCurrentOutputReconfig */)) {
streamsToInvalidate.insert(client->stream());
}
}
@@ -5072,7 +5118,8 @@
config = audio_config_initializer(mixerConfig);
configPtr = &config;
}
- if (!canBeSpatialized(attr, configPtr, devicesTypeAddress)) {
+ if (!canBeSpatializedInt(
+ attr, configPtr, devicesTypeAddress)) {
ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__);
return BAD_VALUE;
}
@@ -5095,6 +5142,7 @@
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && desc->mProfile == profile) {
+ ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle);
mSpatializerOutput = desc;
break;
}
@@ -5114,39 +5162,29 @@
};
DeviceVector savedDevices = mSpatializerOutput->devices();
- closeOutput(mSpatializerOutput->mIoHandle);
- mSpatializerOutput.clear();
+ ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)",
+ __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask);
- const sp<SwAudioOutputDescriptor> desc =
- new SwAudioOutputDescriptor(profile, mpClientInterface);
- status_t status = desc->open(nullptr, mixerConfig, devices,
- mEngine->getStreamTypeForAttributes(*attr),
- AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
- if (status != NO_ERROR) {
- ALOGW("%s failed opening output: status %d, output %d", __func__, status, *output);
- if (*output != AUDIO_IO_HANDLE_NONE) {
- desc->close();
- }
+ closeOutput(mSpatializerOutput->mIoHandle);
+ //from now on mSpatializerOutput is null
+
+ sp<SwAudioOutputDescriptor> desc =
+ openOutputWithProfileAndDevice(profile, devices, mixerConfig);
+ if (desc == nullptr) {
// re open the spatializer output with previous channel mask
- status_t newStatus = desc->open(nullptr, &savedMixerConfig, savedDevices,
- mEngine->getStreamTypeForAttributes(*attr),
- AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
- if (newStatus != NO_ERROR) {
- if (*output != AUDIO_IO_HANDLE_NONE) {
- desc->close();
- }
- ALOGE("%s failed to re-open mSpatializerOutput, status %d", __func__, newStatus);
+ desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig);
+ if (desc == nullptr) {
+ ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__);
} else {
mSpatializerOutput = desc;
- addOutput(*output, desc);
}
mPreviousOutputs = mOutputs;
mpClientInterface->onAudioPortListUpdate();
*output = AUDIO_IO_HANDLE_NONE;
- return status;
+ ALOGW("%s could not open spatializer output with requested config", __func__);
+ return BAD_VALUE;
}
mSpatializerOutput = desc;
- addOutput(*output, desc);
mPreviousOutputs = mOutputs;
mpClientInterface->onAudioPortListUpdate();
}
@@ -5222,8 +5260,6 @@
ALOGE("could not load audio policy configuration file, setting defaults");
getConfig().setDefault();
}
- //TODO: b/193496180 use spatializer flag at audio HAL when available
- getConfig().convertSpatializerFlag();
}
status_t AudioPolicyManager::initialize() {
@@ -5339,7 +5375,8 @@
ALOGW("Output profile contains no device on module %s", hwModule->getName());
continue;
}
- if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+ if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0 ||
+ (outProfile->getFlags() & AUDIO_OUTPUT_FLAG_ULTRASOUND) != 0) {
mTtsOutputAvailable = true;
}
@@ -5818,6 +5855,9 @@
removeOutput(output);
mPreviousOutputs = mOutputs;
+ if (closingOutput == mSpatializerOutput) {
+ mSpatializerOutput.clear();
+ }
// MSD patches may have been released to support a non-MSD direct output. Reset MSD patch if
// no direct outputs are open.
@@ -6337,6 +6377,7 @@
return devices.types();
}
+// TODO - consider MSD routes b/214971780
status_t AudioPolicyManager::getDevicesForAttributes(
const audio_attributes_t &attr, AudioDeviceTypeAddrVector *devices) {
if (devices == nullptr) {
@@ -7371,7 +7412,8 @@
}
sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
- const sp<IOProfile>& profile, const DeviceVector& devices)
+ const sp<IOProfile>& profile, const DeviceVector& devices,
+ const audio_config_base_t *mixerConfig)
{
for (const auto& device : devices) {
// TODO: This should be checking if the profile supports the device combo.
@@ -7381,7 +7423,7 @@
}
sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = desc->open(nullptr /* halConfig */, nullptr /* mixerConfig */, devices,
+ status_t status = desc->open(nullptr /* halConfig */, mixerConfig, devices,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
return nullptr;
@@ -7411,7 +7453,7 @@
config.offload_info.channel_mask = config.channel_mask;
config.offload_info.format = config.format;
- status = desc->open(&config, nullptr /* mixerConfig */, devices,
+ status = desc->open(&config, mixerConfig, devices,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
return nullptr;
@@ -7419,6 +7461,7 @@
}
addOutput(output, desc);
+
if (audio_is_remote_submix_device(deviceType) && address != "0") {
sp<AudioPolicyMix> policyMix;
if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) {
@@ -7429,9 +7472,13 @@
address.string());
}
- } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) && hasPrimaryOutput()) {
- // no duplicated output for direct outputs and
- // outputs used by dynamic policy mixes
+ } else if (hasPrimaryOutput() && profile->getModule()
+ != mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)
+ && ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
+ // no duplicated output for:
+ // - direct outputs
+ // - outputs used by dynamic policy mixes
+ // - outputs opened on the primary HW module
audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
//TODO: configure audio effect output stage here
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index dba9707..165ac13 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -360,7 +360,9 @@
virtual bool canBeSpatialized(const audio_attributes_t *attr,
const audio_config_t *config,
- const AudioDeviceTypeAddrVector &devices) const;
+ const AudioDeviceTypeAddrVector &devices) const {
+ return canBeSpatializedInt(attr, config, devices);
+ }
virtual status_t getSpatializerOutput(const audio_config_base_t *config,
const audio_attributes_t *attr,
@@ -371,6 +373,9 @@
virtual audio_direct_mode_t getDirectPlaybackSupport(const audio_attributes_t *attr,
const audio_config_t *config);
+ virtual status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
+ AudioProfileVector& audioProfiles);
+
bool isCallScreenModeSupported() override;
void onNewAudioModulesAvailable() override;
@@ -859,7 +864,8 @@
uint32_t mBeaconMuteRefCount; // ref count for stream that would mute beacon
uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
bool mBeaconMuted; // has STREAM_TTS been muted
- bool mTtsOutputAvailable; // true if a dedicated output for TTS stream is available
+ // true if a dedicated output for TTS stream or Ultrasound is available
+ bool mTtsOutputAvailable;
bool mMasterMono; // true if we wish to force all outputs to mono
AudioPolicyMixCollection mPolicyMixes; // list of registered mixes
@@ -966,6 +972,30 @@
const DeviceVector &devices,
audio_io_handle_t *output);
+ /**
+ * @brief Queries if some kind of spatialization will be performed if the audio playback
+ * context described by the provided arguments is present.
+ * The context is made of:
+ * - The audio attributes describing the playback use case.
+ * - The audio configuration describing the audio format, channels, sampling rate ...
+ * - The devices describing the sink audio device selected for playback.
+ * All arguments are optional and only the specified arguments are used to match against
+ * supported criteria. For instance, supplying no argument will tell if spatialization is
+ * supported or not in general.
+ * @param attr audio attributes describing the playback use case
+ * @param config audio configuration describing the audio format, channels, sample rate...
+ * @param devices the sink audio device selected for playback
+ * @param allowCurrentOutputReconfig if true, the result will be considering it is possible
+ * to close and reopen an existing spatializer output stream to match the requested
+ * criteria. If false, the criteria must be compatible with the opened sptializer
+ * output.
+ * @return true if spatialization is possible for this context, false otherwise.
+ */
+ virtual bool canBeSpatializedInt(const audio_attributes_t *attr,
+ const audio_config_t *config,
+ const AudioDeviceTypeAddrVector &devices,
+ bool allowCurrentOutputReconfig = true) const;
+
sp<IOProfile> getSpatializerOutputProfile(const audio_config_t *config,
const AudioDeviceTypeAddrVector &devices) const;
@@ -1061,8 +1091,20 @@
bool areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output);
- sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(const sp<IOProfile>& profile,
- const DeviceVector& devices);
+ /**
+ * @brief Opens an output stream from the supplied IOProfile and route it to the
+ * supplied audio devices. If a mixer config is specified, it is forwarded to audio
+ * flinger. If not, a default config is derived from the output stream config.
+ * Also opens a duplicating output if needed and queries the audio HAL for supported
+ * audio profiles if the IOProfile is dynamic.
+ * @param[in] profile IOProfile to use as template
+ * @param[in] devices initial route to apply to this output stream
+ * @param[in] mixerConfig if not null, use this to configure the mixer
+ * @return an output descriptor for the newly opened stream or null in case of error.
+ */
+ sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(
+ const sp<IOProfile>& profile, const DeviceVector& devices,
+ const audio_config_base_t *mixerConfig = nullptr);
bool isOffloadPossible(const audio_offload_info_t& offloadInfo,
bool durationIgnored = false);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 63ea8c3..aba8884 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -2383,4 +2383,24 @@
return Status::ok();
}
+Status AudioPolicyService::getDirectProfilesForAttributes(
+ const media::AudioAttributesInternal& attrAidl,
+ std::vector<media::audio::common::AudioProfile>* _aidl_return) {
+ if (mAudioPolicyManager == nullptr) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ AudioProfileVector audioProfiles;
+
+ Mutex::Autolock _l(mLock);
+ RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
+ mAudioPolicyManager->getDirectProfilesForAttributes(&attr, audioProfiles)));
+ *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
+ convertContainer<std::vector<media::audio::common::AudioProfile>>(
+ audioProfiles, legacy2aidl_AudioProfile_common, false /*isInput*/));
+
+ return Status::ok();
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index ef7a83b..8add137 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -392,7 +392,8 @@
audio_config_base_t config = mSpatializer->getAudioInConfig();
status_t status =
mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
-
+ ALOGV("%s currentOutput %d newOutput %d channel_mask %#x",
+ __func__, currentOutput, newOutput, config.channel_mask);
if (status == NO_ERROR && currentOutput == newOutput) {
return;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 4b1f6e7..ac5af6b 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -277,6 +277,9 @@
const AudioConfig& config,
media::AudioDirectMode* _aidl_return) override;
+ binder::Status getDirectProfilesForAttributes(const media::AudioAttributesInternal& attr,
+ std::vector<media::audio::common::AudioProfile>* _aidl_return) override;
+
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
// IBinder::DeathRecipient
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 0fdbe20..54d9094 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -227,12 +227,8 @@
if (status != NO_ERROR) {
return status;
}
- status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
+ return getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
&mChannelMasks);
- if (status != NO_ERROR) {
- return status;
- }
- return NO_ERROR;
}
/** Gets the channel mask, sampling rate and format set for the spatializer input. */
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 9d0d558..ff06937 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -34,6 +34,7 @@
using AudioPolicyManager::setMsdOutputPatches;
using AudioPolicyManager::getAudioPatches;
using AudioPolicyManager::getDirectPlaybackSupport;
+ using AudioPolicyManager::getDirectProfilesForAttributes;
uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1b54e75..8428881 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -48,6 +48,7 @@
"common/CameraOfflineSessionBase.cpp",
"common/CameraProviderManager.cpp",
"common/FrameProcessorBase.cpp",
+ "common/hidl/HidlProviderInfo.cpp",
"api1/Camera2Client.cpp",
"api1/client2/Parameters.cpp",
"api1/client2/FrameProcessor.cpp",
@@ -80,6 +81,9 @@
"device3/Camera3DeviceInjectionMethods.cpp",
"device3/UHRCropAndMeteringRegionMapper.cpp",
"device3/PreviewFrameScheduler.cpp",
+ "device3/hidl/HidlCamera3Device.cpp",
+ "device3/hidl/HidlCamera3OfflineSession.cpp",
+ "device3/hidl/HidlCamera3OutputUtils.cpp",
"gui/RingBufferConsumer.cpp",
"hidl/AidlCameraDeviceCallbacks.cpp",
"hidl/AidlCameraServiceListener.cpp",
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index 015ae2f..ffd38be 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -32,8 +32,6 @@
namespace android {
-using hardware::camera::common::V1_0::TorchModeStatus;
-
/////////////////////////////////////////////////////////////////////
// CameraFlashlight implementation begins
// used by camera service to control flashflight.
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 97ec5d1..5740038 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -91,8 +91,6 @@
using hardware::ICamera;
using hardware::ICameraClient;
using hardware::ICameraServiceListener;
-using hardware::camera::common::V1_0::CameraDeviceStatus;
-using hardware::camera::common::V1_0::TorchModeStatus;
using hardware::camera2::ICameraInjectionCallback;
using hardware::camera2::ICameraInjectionSession;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
@@ -363,7 +361,7 @@
void CameraService::addStates(const String8 id) {
std::string cameraId(id.c_str());
- hardware::camera::common::V1_0::CameraResourceCost cost;
+ CameraResourceCost cost;
status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
if (res != OK) {
ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
@@ -2384,23 +2382,7 @@
ATRACE_CALL();
- using hardware::camera::provider::V2_5::DeviceState;
- hardware::hidl_bitfield<DeviceState> newDeviceState{};
- if (newState & ICameraService::DEVICE_STATE_BACK_COVERED) {
- newDeviceState |= DeviceState::BACK_COVERED;
- }
- if (newState & ICameraService::DEVICE_STATE_FRONT_COVERED) {
- newDeviceState |= DeviceState::FRONT_COVERED;
- }
- if (newState & ICameraService::DEVICE_STATE_FOLDED) {
- newDeviceState |= DeviceState::FOLDED;
- }
- // Only map vendor bits directly
- uint64_t vendorBits = static_cast<uint64_t>(newState) & 0xFFFFFFFF00000000l;
- newDeviceState |= vendorBits;
-
- ALOGV("%s: New device state 0x%" PRIx64, __FUNCTION__, newDeviceState);
- mCameraProviderManager->notifyDeviceStateChange(newDeviceState);
+ mCameraProviderManager->notifyDeviceStateChange(newState);
return Status::ok();
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 701d6b7..c73d28a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -106,19 +106,19 @@
// HAL Callbacks - implements CameraProviderManager::StatusListener
virtual void onDeviceStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
+ CameraDeviceStatus newHalStatus) override;
virtual void onDeviceStatusChanged(const String8 &cameraId,
const String8 &physicalCameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
+ CameraDeviceStatus newHalStatus) override;
// This method may hold CameraProviderManager::mInterfaceMutex as a part
// of calling getSystemCameraKind() internally. Care should be taken not to
// directly / indirectly call this from callers who also hold
// mInterfaceMutex.
virtual void onTorchStatusChanged(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
+ TorchModeStatus newStatus) override;
// Does not hold CameraProviderManager::mInterfaceMutex.
virtual void onTorchStatusChanged(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
+ TorchModeStatus newStatus,
SystemCameraKind kind) override;
virtual void onNewProviderRegistered() override;
@@ -558,8 +558,6 @@
private:
- typedef hardware::camera::common::V1_0::CameraDeviceStatus CameraDeviceStatus;
-
/**
* Typesafe version of device status, containing both the HAL-layer and the service interface-
* layer values.
@@ -1102,7 +1100,7 @@
// guard mTorchUidMap
Mutex mTorchUidMapMutex;
// camera id -> torch status
- KeyedVector<String8, hardware::camera::common::V1_0::TorchModeStatus>
+ KeyedVector<String8, TorchModeStatus>
mTorchStatusMap;
// camera id -> torch client binder
// only store the last client that turns on each camera's torch mode
@@ -1116,16 +1114,16 @@
// handle torch mode status change and invoke callbacks. mTorchStatusMutex
// should be locked.
void onTorchStatusChangedLocked(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
+ TorchModeStatus newStatus,
SystemCameraKind systemCameraKind);
// get a camera's torch status. mTorchStatusMutex should be locked.
status_t getTorchStatusLocked(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus *status) const;
+ TorchModeStatus *status) const;
// set a camera's torch status. mTorchStatusMutex should be locked.
status_t setTorchStatusLocked(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus status);
+ TorchModeStatus status);
// notify physical camera status when the physical camera is public.
// Expects mStatusListenerLock to be locked.
@@ -1236,14 +1234,13 @@
status_t checkCameraAccess(const String16& opPackageName);
static String8 toString(std::set<userid_t> intSet);
- static int32_t mapToInterface(hardware::camera::common::V1_0::TorchModeStatus status);
- static StatusInternal mapToInternal(hardware::camera::common::V1_0::CameraDeviceStatus status);
+ static int32_t mapToInterface(TorchModeStatus status);
+ static StatusInternal mapToInternal(CameraDeviceStatus status);
static int32_t mapToInterface(StatusInternal status);
void broadcastTorchModeStatus(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus status,
- SystemCameraKind systemCameraKind);
+ TorchModeStatus status, SystemCameraKind systemCameraKind);
void broadcastTorchStrengthLevel(const String8& cameraId, int32_t newTorchStrengthLevel);
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index a406e62..9a7ada2 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -75,23 +75,43 @@
// Treat the H.264 max size as the max supported video size.
MediaProfiles *videoEncoderProfiles = MediaProfiles::getInstance();
Vector<video_encoder> encoders = videoEncoderProfiles->getVideoEncoders();
+ int32_t minVideoWidth = MAX_PREVIEW_WIDTH;
+ int32_t minVideoHeight = MAX_PREVIEW_HEIGHT;
int32_t maxVideoWidth = 0;
int32_t maxVideoHeight = 0;
for (size_t i = 0; i < encoders.size(); i++) {
- int width = videoEncoderProfiles->getVideoEncoderParamByName(
+ int w0 = videoEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.width.min", encoders[i]);
+ int h0 = videoEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.height.min", encoders[i]);
+ int w1 = videoEncoderProfiles->getVideoEncoderParamByName(
"enc.vid.width.max", encoders[i]);
- int height = videoEncoderProfiles->getVideoEncoderParamByName(
+ int h1 = videoEncoderProfiles->getVideoEncoderParamByName(
"enc.vid.height.max", encoders[i]);
- // Treat width/height separately here to handle the case where different
- // profile might report max size of different aspect ratio
- if (width > maxVideoWidth) {
- maxVideoWidth = width;
+ // Assume the min size is 0 if it's not reported by encoder
+ if (w0 == -1) {
+ w0 = 0;
}
- if (height > maxVideoHeight) {
- maxVideoHeight = height;
+ if (h0 == -1) {
+ h0 = 0;
+ }
+ // Treat width/height separately here to handle the case where different
+ // profile might report min/max size of different aspect ratio
+ if (w0 < minVideoWidth) {
+ minVideoWidth = w0;
+ }
+ if (h0 < minVideoHeight) {
+ minVideoHeight = h0;
+ }
+ if (w1 > maxVideoWidth) {
+ maxVideoWidth = w1;
+ }
+ if (h1 > maxVideoHeight) {
+ maxVideoHeight = h1;
}
}
- // This is just an upper bound and may not be an actually valid video size
+ // These are upper/lower bounds and may not be an actually valid video size
+ const Size VIDEO_SIZE_LOWER_BOUND = {minVideoWidth, minVideoHeight};
Size videoSizeUpperBound = {maxVideoWidth, maxVideoHeight};
if (fastInfo.supportsPreferredConfigs) {
@@ -99,9 +119,10 @@
videoSizeUpperBound = getMaxSize(getPreferredVideoSizes());
}
- res = getFilteredSizes(maxPreviewSize, &availablePreviewSizes);
+ res = getFilteredSizes(Size{0, 0}, maxPreviewSize, &availablePreviewSizes);
if (res != OK) return res;
- res = getFilteredSizes(videoSizeUpperBound, &availableVideoSizes);
+ res = getFilteredSizes(
+ VIDEO_SIZE_LOWER_BOUND, videoSizeUpperBound, &availableVideoSizes);
if (res != OK) return res;
// Select initial preview and video size that's under the initial bound and
@@ -1055,7 +1076,8 @@
if (fastInfo.supportsPreferredConfigs) {
previewSizeBound = getMaxSize(getPreferredPreviewSizes());
}
- status_t res = getFilteredSizes(previewSizeBound, &supportedPreviewSizes);
+ status_t res = getFilteredSizes(
+ Size{0, 0}, previewSizeBound, &supportedPreviewSizes);
if (res != OK) return res;
for (size_t i=0; i < availableFpsRanges.count; i += 2) {
if (!isFpsSupported(supportedPreviewSizes,
@@ -2998,7 +3020,8 @@
}
}
-status_t Parameters::getFilteredSizes(Size limit, Vector<Size> *sizes) {
+status_t Parameters::getFilteredSizes(const Size &lower, const Size &upper,
+ Vector<Size> *sizes) {
if (info == NULL) {
ALOGE("%s: Static metadata is not initialized", __FUNCTION__);
return NO_INIT;
@@ -3014,7 +3037,8 @@
const StreamConfiguration &sc = scs[i];
if (sc.isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
sc.format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
- ((sc.width * sc.height) <= (limit.width * limit.height))) {
+ ((sc.width * sc.height) >= (lower.width * lower.height)) &&
+ ((sc.width * sc.height) <= (upper.width * upper.height))) {
int64_t minFrameDuration = getMinFrameDurationNs(
{sc.width, sc.height}, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
if (minFrameDuration > MAX_PREVIEW_RECORD_DURATION_NS) {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 1b2ceda..263025e 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -396,9 +396,10 @@
Vector<Size> availablePreviewSizes;
Vector<Size> availableVideoSizes;
- // Get size list (that are no larger than limit) from static metadata.
+ // Get size list (that fall within lower/upper bounds) from static metadata.
// This method filtered size with minFrameDuration < MAX_PREVIEW_RECORD_DURATION_NS
- status_t getFilteredSizes(Size limit, Vector<Size> *sizes);
+ status_t getFilteredSizes(const Size &lower, const Size &upper,
+ Vector<Size> *sizes);
// Get max size (from the size array) that matches the given aspect ratio.
Size getMaxSizeForRatio(float ratio, const int32_t* sizeArray, size_t count);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index a7ebcf4..f33ae97 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -710,27 +710,9 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
- hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
- bool earlyExit = false;
- camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
- return mDevice->infoPhysical(id);};
- std::vector<std::string> physicalCameraIds;
- mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
- res = SessionConfigurationUtils::convertToHALStreamCombination(sessionConfiguration,
- mCameraIdStr, mDevice->info(), getMetadata, physicalCameraIds, streamConfiguration,
- mOverrideForPerfClass, &earlyExit);
- if (!res.isOk()) {
- return res;
- }
-
- if (earlyExit) {
- *status = false;
- return binder::Status::ok();
- }
-
*status = false;
ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
- streamConfiguration, status);
+ sessionConfiguration, mOverrideForPerfClass, status);
switch (ret) {
case OK:
// Expected, do nothing.
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 5d17c11..55c7579 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -34,6 +34,7 @@
#include "api2/CameraDeviceClient.h"
#include "device3/Camera3Device.h"
+#include "device3/hidl/HidlCamera3Device.h"
#include "utils/CameraThreadState.h"
#include "utils/CameraServiceProxyWrapper.h"
@@ -62,14 +63,14 @@
servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
- mDevice(new Camera3Device(cameraId, overrideForPerfClass, legacyClient)),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
- LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
+ mOverrideForPerfClass = overrideForPerfClass;
+ mLegacyClient = legacyClient;
}
template <typename TClientBase>
@@ -104,7 +105,26 @@
if (res != OK) {
return res;
}
-
+ IPCTransport providerTransport = IPCTransport::INVALID;
+ res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr.string(),
+ &providerTransport);
+ if (res != OK) {
+ return res;
+ }
+ switch (providerTransport) {
+ case IPCTransport::HIDL:
+ mDevice =
+ new HidlCamera3Device(TClientBase::mCameraIdStr, mOverrideForPerfClass,
+ mLegacyClient);
+ break;
+ case IPCTransport::AIDL:
+ ALOGE("%s: AIDL camera3Devices not available yet", __FUNCTION__);
+ return NO_INIT;
+ default:
+ ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
+ TClientBase::mCameraIdStr.string());
+ return NO_INIT;
+ }
if (mDevice == NULL) {
ALOGE("%s: Camera %s: No device connected",
__FUNCTION__, TClientBase::mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 4688502..296ef43 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -126,6 +126,8 @@
// The PID provided in the constructor call
pid_t mInitialClientPid;
+ bool mOverrideForPerfClass = false;
+ bool mLegacyClient = false;
virtual sp<IBinder> asBinderWrapper() {
return IInterface::asBinder(this);
@@ -145,9 +147,12 @@
const int mDeviceVersion;
- // Set to const to avoid mDevice being updated (update of sp<> is racy) during
- // dumpDevice (which is important to be lock free for debugging purpose)
- const sp<CameraDeviceBase> mDevice;
+ // Note: This was previously set to const to avoid mDevice being updated -
+ // b/112639939 (update of sp<> is racy) during dumpDevice (which is important to be lock free
+ // for debugging purpose). The const has been removed since CameraDeviceBase
+ // needs to be set during initializeImpl(). This must not be set / cleared
+ // anywhere else.
+ sp<CameraDeviceBase> mDevice;
/** Utility members */
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 9831328..4227d28 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -25,6 +25,7 @@
#include <algorithm>
#include <chrono>
#include "common/DepthPhotoProcessor.h"
+#include "hidl/HidlProviderInfo.h"
#include <dlfcn.h>
#include <future>
#include <inttypes.h>
@@ -45,11 +46,11 @@
namespace android {
using namespace ::android::hardware::camera;
-using namespace ::android::hardware::camera::common::V1_0;
using namespace ::android::camera3;
+using android::hardware::camera::common::V1_0::Status;
+using namespace camera3::SessionConfigurationUtils;
using std::literals::chrono_literals::operator""s;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
-using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
namespace {
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
@@ -58,14 +59,14 @@
const float CameraProviderManager::kDepthARTolerance = .1f;
-CameraProviderManager::HardwareServiceInteractionProxy
-CameraProviderManager::sHardwareServiceInteractionProxy{};
+CameraProviderManager::HidlServiceInteractionProxyImpl
+CameraProviderManager::sHidlServiceInteractionProxy{};
CameraProviderManager::~CameraProviderManager() {
}
hardware::hidl_vec<hardware::hidl_string>
-CameraProviderManager::HardwareServiceInteractionProxy::listServices() {
+CameraProviderManager::HidlServiceInteractionProxyImpl::listServices() {
hardware::hidl_vec<hardware::hidl_string> ret;
auto manager = hardware::defaultServiceManager1_2();
if (manager != nullptr) {
@@ -78,19 +79,18 @@
}
status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
- ServiceInteractionProxy* proxy) {
+ HidlServiceInteractionProxy* hidlProxy) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- if (proxy == nullptr) {
+ if (hidlProxy == nullptr) {
ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
return BAD_VALUE;
}
mListener = listener;
- mServiceProxy = proxy;
- mDeviceState = static_cast<hardware::hidl_bitfield<provider::V2_5::DeviceState>>(
- provider::V2_5::DeviceState::NORMAL);
+ mHidlServiceProxy = hidlProxy;
+ mDeviceState = 0;
// Registering will trigger notifications for all already-known providers
- bool success = mServiceProxy->registerForNotifications(
+ bool success = mHidlServiceProxy->registerForNotifications(
/* instance name, empty means no filter */ "",
this);
if (!success) {
@@ -99,9 +99,8 @@
return INVALID_OPERATION;
}
-
- for (const auto& instance : mServiceProxy->listServices()) {
- this->addProviderLocked(instance);
+ for (const auto& instance : mHidlServiceProxy->listServices()) {
+ this->addHidlProviderLocked(instance);
}
IPCThreadState::self()->flushCommands();
@@ -268,7 +267,7 @@
}
status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_8::StreamConfiguration &configuration,
+ const SessionConfiguration &configuration, bool overrideForPerfClass,
bool *status /*out*/) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id);
@@ -276,7 +275,22 @@
return NAME_NOT_FOUND;
}
- return deviceInfo->isSessionConfigurationSupported(configuration, status);
+ return deviceInfo->isSessionConfigurationSupported(configuration, overrideForPerfClass, status);
+}
+
+status_t CameraProviderManager::getCameraIdIPCTransport(const std::string &id,
+ IPCTransport *providerTransport) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+ sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+ if (parentProvider == nullptr) {
+ return DEAD_OBJECT;
+ }
+ *providerTransport = parentProvider->getIPCTransport();
+ return OK;
}
status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
@@ -285,6 +299,9 @@
return getCameraCharacteristicsLocked(id, overrideForPerfClass, characteristics);
}
+// Till hidl is removed from the android source tree, we use this for aidl as
+// well. We artificially give aidl camera device version 1 a major version 3 and minor
+// version 8.
status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id,
hardware::hidl_version *v) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -375,11 +392,25 @@
if (parentProvider == nullptr) {
return DEAD_OBJECT;
}
- const sp<provider::V2_4::ICameraProvider> interface = parentProvider->startProviderInterface();
- if (interface == nullptr) {
- return DEAD_OBJECT;
+ std::shared_ptr<HalCameraProvider> halCameraProvider = nullptr;
+ IPCTransport providerTransport = parentProvider->getIPCTransport();
+ if (providerTransport == IPCTransport::HIDL) {
+ HidlProviderInfo * hidlProviderInfo = static_cast<HidlProviderInfo *>(parentProvider.get());
+ const sp<provider::V2_4::ICameraProvider> hidlInterface =
+ hidlProviderInfo->startProviderInterface();
+ if (hidlInterface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ halCameraProvider =
+ std::make_shared<HidlHalCameraProvider>(hidlInterface, hidlInterface->descriptor);
+ } else if (providerTransport == IPCTransport::AIDL) {
+ ALOGE("%s AIDL hal providers not supported yet", __FUNCTION__);
+ return INVALID_OPERATION;
+ } else {
+ ALOGE("%s Invalid provider transport", __FUNCTION__);
+ return INVALID_OPERATION;
}
- saveRef(DeviceMode::TORCH, deviceInfo->mId, interface);
+ saveRef(DeviceMode::TORCH, deviceInfo->mId, halCameraProvider);
return deviceInfo->setTorchMode(enabled);
}
@@ -402,9 +433,7 @@
for (const auto& providerInfo : mProviders) {
if (providerInfo->isExternalLazyHAL()) {
- const sp<provider::V2_4::ICameraProvider>
- interface = providerInfo->startProviderInterface();
- if (interface == nullptr) {
+ if (!providerInfo->successfullyStartedProviderInterface()) {
return nullptr;
} else {
return providerInfo;
@@ -463,8 +492,7 @@
return OK;
}
-status_t CameraProviderManager::notifyDeviceStateChange(
- hardware::hidl_bitfield<provider::V2_5::DeviceState> newState) {
+status_t CameraProviderManager::notifyDeviceStateChange(int64_t newState) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
mDeviceState = newState;
status_t res = OK;
@@ -490,7 +518,7 @@
return res;
}
-status_t CameraProviderManager::openSession(const std::string &id,
+status_t CameraProviderManager::openHidlSession(const std::string &id,
const sp<device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<device::V3_2::ICameraDeviceSession> *session) {
@@ -501,21 +529,23 @@
/*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
- auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
+ auto *hidlDeviceInfo3 = static_cast<HidlProviderInfo::HidlDeviceInfo3*>(deviceInfo);
sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
if (parentProvider == nullptr) {
return DEAD_OBJECT;
}
- const sp<provider::V2_4::ICameraProvider> provider = parentProvider->startProviderInterface();
+ const sp<provider::V2_4::ICameraProvider> provider =
+ static_cast<HidlProviderInfo *>(parentProvider.get())->startProviderInterface();
if (provider == nullptr) {
return DEAD_OBJECT;
}
- saveRef(DeviceMode::CAMERA, id, provider);
+ std::shared_ptr<HalCameraProvider> halCameraProvider =
+ std::make_shared<HidlHalCameraProvider>(provider, provider->descriptor);
+ saveRef(DeviceMode::CAMERA, id, halCameraProvider);
Status status;
hardware::Return<void> ret;
- auto interface = deviceInfo3->startDeviceInterface<
- CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+ auto interface = hidlDeviceInfo3->startDeviceInterface();
if (interface == nullptr) {
return DEAD_OBJECT;
}
@@ -533,17 +563,18 @@
__FUNCTION__, id.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
- return mapToStatusT(status);
+ return HidlProviderInfo::mapToStatusT(status);
}
void CameraProviderManager::saveRef(DeviceMode usageType, const std::string &cameraId,
- sp<provider::V2_4::ICameraProvider> provider) {
+ std::shared_ptr<HalCameraProvider> provider) {
if (!kEnableLazyHal) {
return;
}
- ALOGV("Saving camera provider %s for camera device %s", provider->descriptor, cameraId.c_str());
+ ALOGV("Saving camera provider %s for camera device %s", provider->mDescriptor.c_str(),
+ cameraId.c_str());
std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
- std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *primaryMap, *alternateMap;
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>> *primaryMap, *alternateMap;
if (usageType == DeviceMode::TORCH) {
primaryMap = &mTorchProviderByCameraId;
alternateMap = &mCameraProviderByCameraId;
@@ -566,7 +597,7 @@
return;
}
ALOGV("Removing camera device %s", cameraId.c_str());
- std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *providerMap;
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>> *providerMap;
if (usageType == DeviceMode::TORCH) {
providerMap = &mTorchProviderByCameraId;
} else {
@@ -600,7 +631,7 @@
{
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- res = addProviderLocked(name, preexisting);
+ res = addHidlProviderLocked(name, preexisting);
}
sp<StatusListener> listener = getStatusListener();
@@ -1356,10 +1387,10 @@
return falseRet;
}
-status_t CameraProviderManager::tryToInitializeProviderLocked(
+status_t CameraProviderManager::tryToInitializeHidlProviderLocked(
const std::string& providerName, const sp<ProviderInfo>& providerInfo) {
sp<provider::V2_4::ICameraProvider> interface;
- interface = mServiceProxy->tryGetService(providerName);
+ interface = mHidlServiceProxy->tryGetService(providerName);
if (interface == nullptr) {
// The interface may not be started yet. In that case, this is not a
@@ -1369,10 +1400,11 @@
return BAD_VALUE;
}
- return providerInfo->initialize(interface, mDeviceState);
+ HidlProviderInfo *hidlProviderInfo = static_cast<HidlProviderInfo *>(providerInfo.get());
+ return hidlProviderInfo->initializeHidlProvider(interface, mDeviceState);
}
-status_t CameraProviderManager::addProviderLocked(const std::string& newProvider,
+status_t CameraProviderManager::addHidlProviderLocked(const std::string& newProvider,
bool preexisting) {
// Several camera provider instances can be temporarily present.
// Defer initialization of a new instance until the older instance is properly removed.
@@ -1394,9 +1426,9 @@
}
}
- sp<ProviderInfo> providerInfo = new ProviderInfo(newProvider, providerInstance, this);
+ sp<HidlProviderInfo> providerInfo = new HidlProviderInfo(newProvider, providerInstance, this);
if (!providerPresent) {
- status_t res = tryToInitializeProviderLocked(newProvider, providerInfo);
+ status_t res = tryToInitializeHidlProviderLocked(newProvider, providerInfo);
if (res != OK) {
return res;
}
@@ -1434,7 +1466,13 @@
// initialize.
for (const auto& providerInfo : mProviders) {
if (providerInfo->mProviderName == removedProviderName) {
- return tryToInitializeProviderLocked(removedProviderName, providerInfo);
+ IPCTransport providerTransport = providerInfo->getIPCTransport();
+ switch(providerTransport) {
+ case IPCTransport::HIDL:
+ return tryToInitializeHidlProviderLocked(removedProviderName, providerInfo);
+ default:
+ ALOGE("%s Unsupported Transport %d", __FUNCTION__, providerTransport);
+ }
}
}
@@ -1456,7 +1494,6 @@
sp<CameraProviderManager::StatusListener> CameraProviderManager::getStatusListener() const {
return mListener.promote();
}
-
/**** Methods for ProviderInfo ****/
@@ -1472,327 +1509,10 @@
(void) mManager;
}
-status_t CameraProviderManager::ProviderInfo::initialize(
- sp<provider::V2_4::ICameraProvider>& interface,
- hardware::hidl_bitfield<provider::V2_5::DeviceState> currentDeviceState) {
- status_t res = parseProviderName(mProviderName, &mType, &mId);
- if (res != OK) {
- ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
- return BAD_VALUE;
- }
- ALOGI("Connecting to new camera provider: %s, isRemote? %d",
- mProviderName.c_str(), interface->isRemote());
-
- // Determine minor version
- mMinorVersion = 4;
- auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
- sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
- if (cast2_6.isOk()) {
- interface2_6 = cast2_6;
- if (interface2_6 != nullptr) {
- mMinorVersion = 6;
- }
- }
- // We need to check again since cast2_6.isOk() succeeds even if the provider
- // version isn't actually 2.6.
- if (interface2_6 == nullptr){
- auto cast2_5 =
- provider::V2_5::ICameraProvider::castFrom(interface);
- sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
- if (cast2_5.isOk()) {
- interface2_5 = cast2_5;
- if (interface != nullptr) {
- mMinorVersion = 5;
- }
- }
- } else {
- auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
- if (cast2_7.isOk()) {
- sp<provider::V2_7::ICameraProvider> interface2_7 = cast2_7;
- if (interface2_7 != nullptr) {
- mMinorVersion = 7;
- }
- }
- }
-
- // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
- // before setCallback returns
- hardware::Return<Status> status = interface->setCallback(this);
- if (!status.isOk()) {
- ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), status.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to register callbacks with camera provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
-
- hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
- if (!linked.isOk()) {
- ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
- __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
- return DEAD_OBJECT;
- } else if (!linked) {
- ALOGW("%s: Unable to link to provider '%s' death notifications",
- __FUNCTION__, mProviderName.c_str());
- }
-
- if (!kEnableLazyHal) {
- // Save HAL reference indefinitely
- mSavedInterface = interface;
- } else {
- mActiveInterface = interface;
- }
-
- ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
- __FUNCTION__, mProviderName.c_str(), mDeviceState);
- notifyDeviceStateChange(currentDeviceState);
-
- res = setUpVendorTags();
- if (res != OK) {
- ALOGE("%s: Unable to set up vendor tags from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return res;
- }
-
- // Get initial list of camera devices, if any
- std::vector<std::string> devices;
- hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
- Status idStatus,
- const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
- status = idStatus;
- if (status == Status::OK) {
- for (auto& name : cameraDeviceNames) {
- uint16_t major, minor;
- std::string type, id;
- status_t res = parseDeviceName(name, &major, &minor, &type, &id);
- if (res != OK) {
- ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
- status = Status::INTERNAL_ERROR;
- } else {
- devices.push_back(name);
- mProviderPublicCameraIds.push_back(id);
- }
- }
- } });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to query for camera devices from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
-
- // Get list of concurrent streaming camera device combinations
- if (mMinorVersion >= 6) {
- res = getConcurrentCameraIdsInternalLocked(interface2_6);
- if (res != OK) {
- return res;
- }
- }
-
- ret = interface->isSetTorchModeSupported(
- [this](auto status, bool supported) {
- if (status == Status::OK) {
- mSetTorchModeSupported = supported;
- }
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error checking torch mode support '%s': %s",
- __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
- return DEAD_OBJECT;
- }
-
- mIsRemote = interface->isRemote();
-
- sp<StatusListener> listener = mManager->getStatusListener();
- for (auto& device : devices) {
- std::string id;
- status_t res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
- if (res != OK) {
- ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
- __FUNCTION__, device.c_str(), strerror(-res), res);
- continue;
- }
- }
-
- ALOGI("Camera provider %s ready with %zu camera devices",
- mProviderName.c_str(), mDevices.size());
-
- // Process cached status callbacks
- std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
- std::make_unique<std::vector<CameraStatusInfoT>>();
- {
- std::lock_guard<std::mutex> lock(mInitLock);
-
- for (auto& statusInfo : mCachedStatus) {
- std::string id, physicalId;
- status_t res = OK;
- if (statusInfo.isPhysicalCameraStatus) {
- res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
- statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
- } else {
- res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
- }
- if (res == OK) {
- cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
- id.c_str(), physicalId.c_str(), statusInfo.status);
- }
- }
- mCachedStatus.clear();
-
- mInitialized = true;
- }
-
- // The cached status change callbacks cannot be fired directly from this
- // function, due to same-thread deadlock trying to acquire mInterfaceMutex
- // twice.
- if (listener != nullptr) {
- mInitialStatusCallbackFuture = std::async(std::launch::async,
- &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
- listener, std::move(cachedStatus));
- }
-
- return OK;
-}
-
-const sp<provider::V2_4::ICameraProvider>
-CameraProviderManager::ProviderInfo::startProviderInterface() {
- ATRACE_CALL();
- ALOGV("Request to start camera provider: %s", mProviderName.c_str());
- if (mSavedInterface != nullptr) {
- return mSavedInterface;
- }
- if (!kEnableLazyHal) {
- ALOGE("Bad provider state! Should not be here on a non-lazy HAL!");
- return nullptr;
- }
-
- auto interface = mActiveInterface.promote();
- if (interface == nullptr) {
- // Try to get service without starting
- interface = mManager->mServiceProxy->tryGetService(mProviderName);
- if (interface == nullptr) {
- ALOGV("Camera provider actually needs restart, calling getService(%s)",
- mProviderName.c_str());
- interface = mManager->mServiceProxy->getService(mProviderName);
-
- // Set all devices as ENUMERATING, provider should update status
- // to PRESENT after initializing.
- // This avoids failing getCameraDeviceInterface_V3_x before devices
- // are ready.
- for (auto& device : mDevices) {
- device->mIsDeviceAvailable = false;
- }
-
- interface->setCallback(this);
- hardware::Return<bool>
- linked = interface->linkToDeath(this, /*cookie*/ mId);
- if (!linked.isOk()) {
- ALOGE(
- "%s: Transaction error in linking to camera provider '%s' death: %s",
- __FUNCTION__,
- mProviderName.c_str(),
- linked.description().c_str());
- mManager->removeProvider(mProviderName);
- return nullptr;
- } else if (!linked) {
- ALOGW("%s: Unable to link to provider '%s' death notifications",
- __FUNCTION__, mProviderName.c_str());
- }
- // Send current device state
- if (mMinorVersion >= 5) {
- auto castResult =
- provider::V2_5::ICameraProvider::castFrom(interface);
- if (castResult.isOk()) {
- sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
- if (interface_2_5 != nullptr) {
- ALOGV("%s: Initial device state for %s: 0x %" PRIx64,
- __FUNCTION__, mProviderName.c_str(), mDeviceState);
- interface_2_5->notifyDeviceStateChange(mDeviceState);
- }
- }
- }
- }
- mActiveInterface = interface;
- } else {
- ALOGV("Camera provider (%s) already in use. Re-using instance.",
- mProviderName.c_str());
- }
-
- return interface;
-}
-
const std::string& CameraProviderManager::ProviderInfo::getType() const {
return mType;
}
-status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
- CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
-
- ALOGI("Enumerating new camera device: %s", name.c_str());
-
- uint16_t major, minor;
- std::string type, id;
-
- status_t res = parseDeviceName(name, &major, &minor, &type, &id);
- if (res != OK) {
- return res;
- }
- if (type != mType) {
- ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
- type.c_str(), mType.c_str());
- return BAD_VALUE;
- }
- if (mManager->isValidDeviceLocked(id, major)) {
- ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
- name.c_str(), id.c_str(), major);
- return BAD_VALUE;
- }
-
- std::unique_ptr<DeviceInfo> deviceInfo;
- switch (major) {
- case 1:
- ALOGE("%s: Device %s: Unsupported HIDL device HAL major version %d:", __FUNCTION__,
- name.c_str(), major);
- return BAD_VALUE;
- case 3:
- deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
- id, minor);
- break;
- default:
- ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
- name.c_str(), major);
- return BAD_VALUE;
- }
- if (deviceInfo == nullptr) return BAD_VALUE;
- deviceInfo->notifyDeviceStateChange(mDeviceState);
- deviceInfo->mStatus = initialStatus;
- bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
-
- mDevices.push_back(std::move(deviceInfo));
-
- mUniqueCameraIds.insert(id);
- if (isAPI1Compatible) {
- // addDevice can be called more than once for the same camera id if HAL
- // supports openLegacy.
- if (std::find(mUniqueAPI1CompatibleCameraIds.begin(), mUniqueAPI1CompatibleCameraIds.end(),
- id) == mUniqueAPI1CompatibleCameraIds.end()) {
- mUniqueAPI1CompatibleCameraIds.push_back(id);
- }
- }
-
- if (parsedId != nullptr) {
- *parsedId = id;
- }
- return OK;
-}
-
void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
if ((*it)->mId == id) {
@@ -1917,425 +1637,20 @@
return OK;
}
-status_t CameraProviderManager::ProviderInfo::getConcurrentCameraIdsInternalLocked(
- sp<provider::V2_6::ICameraProvider> &interface2_6) {
- if (interface2_6 == nullptr) {
- ALOGE("%s: null interface provided", __FUNCTION__);
- return BAD_VALUE;
- }
- Status status = Status::OK;
- hardware::Return<void> ret =
- interface2_6->getConcurrentStreamingCameraIds([&status, this](
- Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
- const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
- cameraDeviceIdCombinations) {
- status = concurrentIdStatus;
- if (status == Status::OK) {
- mConcurrentCameraIdCombinations.clear();
- for (auto& combination : cameraDeviceIdCombinations) {
- std::unordered_set<std::string> deviceIds;
- for (auto &cameraDeviceId : combination) {
- deviceIds.insert(cameraDeviceId.c_str());
- }
- mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
- }
- } });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to query for camera devices from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
- return OK;
-}
-
-status_t CameraProviderManager::ProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
- if (mMinorVersion < 6) {
- // Unsupported operation, nothing to do here
- return OK;
- }
- // Check if the provider is currently active - not going to start it up for this notification
- auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
- if (interface == nullptr) {
- ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
- mProviderName.c_str());
- return INVALID_OPERATION;
- }
- auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
-
- if (castResult.isOk()) {
- sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
- if (interface2_6 != nullptr) {
- return getConcurrentCameraIdsInternalLocked(interface2_6);
- } else {
- // This should not happen since mMinorVersion >= 6
- ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
- return UNKNOWN_ERROR;
- }
- }
- return OK;
-}
-
std::vector<std::unordered_set<std::string>>
CameraProviderManager::ProviderInfo::getConcurrentCameraIdCombinations() {
std::lock_guard<std::mutex> lock(mLock);
return mConcurrentCameraIdCombinations;
}
-hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- CameraDeviceStatus newStatus) {
- sp<StatusListener> listener;
- std::string id;
- std::lock_guard<std::mutex> lock(mInitLock);
-
- if (!mInitialized) {
- mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
- cameraDeviceName.c_str(), std::string().c_str(), newStatus);
- return hardware::Void();
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
- return hardware::Void();
- }
- listener = mManager->getStatusListener();
- }
-
- // Call without lock held to allow reentrancy into provider manager
- if (listener != nullptr) {
- listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
- }
-
- return hardware::Void();
-}
-
-status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
- std::string* id, const hardware::hidl_string& cameraDeviceName,
- CameraDeviceStatus newStatus) {
- bool known = false;
- std::string cameraId;
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- Mutex::Autolock l(deviceInfo->mDeviceAvailableLock);
- ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
- deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
- deviceInfo->mStatus = newStatus;
- // TODO: Handle device removal (NOT_PRESENT)
- cameraId = deviceInfo->mId;
- known = true;
- deviceInfo->mIsDeviceAvailable =
- (newStatus == CameraDeviceStatus::PRESENT);
- deviceInfo->mDeviceAvailableSignal.signal();
- break;
- }
- }
- // Previously unseen device; status must not be NOT_PRESENT
- if (!known) {
- if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
- ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str());
- return BAD_VALUE;
- }
- addDevice(cameraDeviceName, newStatus, &cameraId);
- } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
- removeDevice(cameraId);
- } else if (isExternalLazyHAL()) {
- // Do not notify CameraService for PRESENT->PRESENT (lazy HAL restart)
- // because NOT_AVAILABLE is set on CameraService::connect and a PRESENT
- // notif. would overwrite it
- return BAD_VALUE;
- }
- if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
- ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
- __FUNCTION__, mProviderName.c_str());
- }
- *id = cameraId;
- return OK;
-}
-
-hardware::Return<void> CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- CameraDeviceStatus newStatus) {
- sp<StatusListener> listener;
- std::string id;
- std::string physicalId;
- std::lock_guard<std::mutex> lock(mInitLock);
-
- if (!mInitialized) {
- mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
- physicalCameraDeviceName, newStatus);
- return hardware::Void();
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
-
- if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
- physicalCameraDeviceName, newStatus)) {
- return hardware::Void();
- }
-
- listener = mManager->getStatusListener();
- }
- // Call without lock held to allow reentrancy into provider manager
- if (listener != nullptr) {
- listener->onDeviceStatusChanged(String8(id.c_str()),
- String8(physicalId.c_str()), newStatus);
- }
- return hardware::Void();
-}
-
-status_t CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeLocked(
- std::string* id, std::string* physicalId,
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- CameraDeviceStatus newStatus) {
- bool known = false;
- std::string cameraId;
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- cameraId = deviceInfo->mId;
- if (!deviceInfo->mIsLogicalCamera) {
- ALOGE("%s: Invalid combination of camera id %s, physical id %s",
- __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
- return BAD_VALUE;
- }
- if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
- physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
- ALOGE("%s: Invalid combination of camera id %s, physical id %s",
- __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
- return BAD_VALUE;
- }
- ALOGI("Camera device %s physical device %s status is now %s",
- cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
- deviceStatusToString(newStatus));
- known = true;
- break;
- }
- }
- // Previously unseen device; status must not be NOT_PRESENT
- if (!known) {
- ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str(),
- physicalCameraDeviceName.c_str());
- return BAD_VALUE;
- }
-
- *id = cameraId;
- *physicalId = physicalCameraDeviceName.c_str();
- return OK;
-}
-
-hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- TorchModeStatus newStatus) {
- sp<StatusListener> listener;
- SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
- std::string id;
- bool known = false;
- {
- // Hold mLock for accessing mDevices
- std::lock_guard<std::mutex> lock(mLock);
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
- torchStatusToString(newStatus));
- id = deviceInfo->mId;
- known = true;
- systemCameraKind = deviceInfo->mSystemCameraKind;
- if (TorchModeStatus::AVAILABLE_ON != newStatus) {
- mManager->removeRef(DeviceMode::TORCH, id);
- }
- break;
- }
- }
- if (!known) {
- ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
- return hardware::Void();
- }
- // no lock needed since listener is set up only once during
- // CameraProviderManager initialization and then never changed till it is
- // destructed.
- listener = mManager->getStatusListener();
- }
- // Call without lock held to allow reentrancy into provider manager
- // The problem with holding mLock here is that we
- // might be limiting re-entrancy : CameraService::onTorchStatusChanged calls
- // back into CameraProviderManager which might try to hold mLock again (eg:
- // findDeviceInfo, which should be holding mLock while iterating through
- // each provider's devices).
- if (listener != nullptr) {
- listener->onTorchStatusChanged(String8(id.c_str()), newStatus, systemCameraKind);
- }
- return hardware::Void();
-}
-
-void CameraProviderManager::ProviderInfo::serviceDied(uint64_t cookie,
- const wp<hidl::base::V1_0::IBase>& who) {
- (void) who;
- ALOGI("Camera provider '%s' has died; removing it", mProviderInstance.c_str());
- if (cookie != mId) {
- ALOGW("%s: Unexpected serviceDied cookie %" PRIu64 ", expected %" PRIu32,
- __FUNCTION__, cookie, mId);
- }
- mManager->removeProvider(mProviderInstance);
-}
-
-status_t CameraProviderManager::ProviderInfo::setUpVendorTags() {
- if (mVendorTagDescriptor != nullptr)
- return OK;
-
- hardware::hidl_vec<VendorTagSection> vts;
- Status status;
- hardware::Return<void> ret;
- const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- ret = interface->getVendorTags(
- [&](auto s, const auto& vendorTagSecs) {
- status = s;
- if (s == Status::OK) {
- vts = vendorTagSecs;
- }
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- return mapToStatusT(status);
- }
-
- // Read all vendor tag definitions into a descriptor
- status_t res;
- if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/mVendorTagDescriptor))
- != OK) {
- ALOGE("%s: Could not generate descriptor from vendor tag operations,"
- "received error %s (%d). Camera clients will not be able to use"
- "vendor tags", __FUNCTION__, strerror(res), res);
- return res;
- }
-
- return OK;
-}
-
void CameraProviderManager::ProviderInfo::notifyDeviceInfoStateChangeLocked(
- hardware::hidl_bitfield<provider::V2_5::DeviceState> newDeviceState) {
+ int64_t newDeviceState) {
std::lock_guard<std::mutex> lock(mLock);
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
(*it)->notifyDeviceStateChange(newDeviceState);
}
}
-status_t CameraProviderManager::ProviderInfo::notifyDeviceStateChange(
- hardware::hidl_bitfield<provider::V2_5::DeviceState> newDeviceState) {
- mDeviceState = newDeviceState;
- if (mMinorVersion >= 5) {
- // Check if the provider is currently active - not going to start it up for this notification
- auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
- if (interface != nullptr) {
- // Send current device state
- auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
- if (castResult.isOk()) {
- sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
- if (interface_2_5 != nullptr) {
- interface_2_5->notifyDeviceStateChange(mDeviceState);
- }
- }
- }
- }
- return OK;
-}
-
-status_t CameraProviderManager::ProviderInfo::isConcurrentSessionConfigurationSupported(
- const hardware::hidl_vec<CameraIdAndStreamCombination> &halCameraIdsAndStreamCombinations,
- bool *isSupported) {
- status_t res = OK;
- if (mMinorVersion >= 6) {
- // Check if the provider is currently active - not going to start it up for this notification
- auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
- if (interface == nullptr) {
- // TODO: This might be some other problem
- return INVALID_OPERATION;
- }
- auto castResult2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
- auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
- Status callStatus;
- auto cb =
- [&isSupported, &callStatus](Status s, bool supported) {
- callStatus = s;
- *isSupported = supported; };
-
- ::android::hardware::Return<void> ret;
- sp<provider::V2_7::ICameraProvider> interface_2_7;
- sp<provider::V2_6::ICameraProvider> interface_2_6;
- if (mMinorVersion >= 7 && castResult2_7.isOk()) {
- interface_2_7 = castResult2_7;
- if (interface_2_7 != nullptr) {
- ret = interface_2_7->isConcurrentStreamCombinationSupported_2_7(
- halCameraIdsAndStreamCombinations, cb);
- }
- } else if (mMinorVersion == 6 && castResult2_6.isOk()) {
- interface_2_6 = castResult2_6;
- if (interface_2_6 != nullptr) {
- hardware::hidl_vec<provider::V2_6::CameraIdAndStreamCombination>
- halCameraIdsAndStreamCombinations_2_6;
- size_t numStreams = halCameraIdsAndStreamCombinations.size();
- halCameraIdsAndStreamCombinations_2_6.resize(numStreams);
- for (size_t i = 0; i < numStreams; i++) {
- using namespace camera3;
- auto const& combination = halCameraIdsAndStreamCombinations[i];
- halCameraIdsAndStreamCombinations_2_6[i].cameraId = combination.cameraId;
- bool success =
- SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
- halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
- combination.streamConfiguration);
- if (!success) {
- *isSupported = false;
- return OK;
- }
- }
- ret = interface_2_6->isConcurrentStreamCombinationSupported(
- halCameraIdsAndStreamCombinations_2_6, cb);
- }
- }
-
- if (interface_2_7 != nullptr || interface_2_6 != nullptr) {
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
- callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
- return res;
- }
- }
- // unsupported operation
- return INVALID_OPERATION;
-}
-
void CameraProviderManager::ProviderInfo::notifyInitialStatusChange(
sp<StatusListener> listener,
std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus) {
@@ -2350,322 +1665,16 @@
}
}
-template<class DeviceInfoT>
-std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
- CameraProviderManager::ProviderInfo::initializeDeviceInfo(
- const std::string &name, const metadata_vendor_id_t tagId,
- const std::string &id, uint16_t minorVersion) {
- Status status;
-
- auto cameraInterface =
- startDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
- if (cameraInterface == nullptr) return nullptr;
-
- CameraResourceCost resourceCost;
- cameraInterface->getResourceCost([&status, &resourceCost](
- Status s, CameraResourceCost cost) {
- status = s;
- resourceCost = cost;
- });
- if (status != Status::OK) {
- ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
- name.c_str(), statusToString(status));
- return nullptr;
- }
-
- for (auto& conflictName : resourceCost.conflictingDevices) {
- uint16_t major, minor;
- std::string type, id;
- status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
- if (res != OK) {
- ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
- return nullptr;
- }
- conflictName = id;
- }
-
- return std::unique_ptr<DeviceInfo>(
- new DeviceInfoT(name, tagId, id, minorVersion, resourceCost, this,
- mProviderPublicCameraIds, cameraInterface));
-}
-
-template<class InterfaceT>
-sp<InterfaceT>
-CameraProviderManager::ProviderInfo::startDeviceInterface(const std::string &name) {
- ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
- name.c_str(), InterfaceT::version.get_major());
- return nullptr;
-}
-
-template<>
-sp<device::V3_2::ICameraDevice>
-CameraProviderManager::ProviderInfo::startDeviceInterface
- <device::V3_2::ICameraDevice>(const std::string &name) {
- Status status;
- sp<device::V3_2::ICameraDevice> cameraInterface;
- hardware::Return<void> ret;
- const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
- if (interface == nullptr) {
- return nullptr;
- }
- ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
- Status s, sp<device::V3_2::ICameraDevice> interface) {
- status = s;
- cameraInterface = interface;
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
- __FUNCTION__, name.c_str(), ret.description().c_str());
- return nullptr;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
- name.c_str(), statusToString(status));
- return nullptr;
- }
- return cameraInterface;
-}
-
-CameraProviderManager::ProviderInfo::DeviceInfo::~DeviceInfo() {}
-
-template<class InterfaceT>
-sp<InterfaceT> CameraProviderManager::ProviderInfo::DeviceInfo::startDeviceInterface() {
- Mutex::Autolock l(mDeviceAvailableLock);
- sp<InterfaceT> device;
- ATRACE_CALL();
- if (mSavedInterface == nullptr) {
- sp<ProviderInfo> parentProvider = mParentProvider.promote();
- if (parentProvider != nullptr) {
- // Wait for lazy HALs to confirm device availability
- if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
- ALOGV("%s: Wait for external device to become available %s",
- __FUNCTION__,
- mId.c_str());
-
- auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
- kDeviceAvailableTimeout);
- if (res != OK) {
- ALOGE("%s: Failed waiting for device to become available",
- __FUNCTION__);
- return nullptr;
- }
- }
-
- device = parentProvider->startDeviceInterface<InterfaceT>(mName);
- }
- } else {
- device = (InterfaceT *) mSavedInterface.get();
- }
- return device;
-}
-
-template<class InterfaceT>
-status_t CameraProviderManager::ProviderInfo::DeviceInfo::setTorchMode(InterfaceT& interface,
- bool enabled) {
- Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
- return mapToStatusT(s);
-}
-
CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& name,
const metadata_vendor_id_t tagId, const std::string &id,
uint16_t minorVersion,
const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider,
- const std::vector<std::string>& publicCameraIds,
- sp<InterfaceT> interface) :
+ const std::vector<std::string>& publicCameraIds) :
DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
- publicCameraIds, resourceCost, parentProvider) {
- // Get camera characteristics and initialize flash unit availability
- Status status;
- hardware::Return<void> ret;
- ret = interface->getCameraCharacteristics([&status, this](Status s,
- device::V3_2::CameraMetadata metadata) {
- status = s;
- if (s == Status::OK) {
- camera_metadata_t *buffer =
- reinterpret_cast<camera_metadata_t*>(metadata.data());
- size_t expectedSize = metadata.size();
- int res = validate_camera_metadata_structure(buffer, &expectedSize);
- if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
- set_camera_metadata_vendor_id(buffer, mProviderTagid);
- mCameraCharacteristics = buffer;
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
- status = Status::INTERNAL_ERROR;
- }
- }
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error getting camera characteristics for device %s"
- " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
- ret.description().c_str());
- return;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
- __FUNCTION__, id.c_str(), CameraProviderManager::statusToString(status), status);
- return;
- }
+ publicCameraIds, resourceCost, parentProvider) { }
- if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
- const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
- if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
- for (size_t i = 0; i < stateMap.count; i += 2) {
- mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
- }
- } else {
- ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
- stateMap.count);
- }
- }
-
- mSystemCameraKind = getSystemCameraKind();
-
- status_t res = fixupMonochromeTags();
- if (OK != res) {
- ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return;
- }
- auto stat = addDynamicDepthTags();
- if (OK != stat) {
- ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat),
- stat);
- }
- res = deriveHeicTags();
- if (OK != res) {
- ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
-
- if (SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
- status_t status = addDynamicDepthTags(/*maxResolution*/true);
- if (OK != status) {
- ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
- __FUNCTION__, strerror(-status), status);
- }
-
- status = deriveHeicTags(/*maxResolution*/true);
- if (OK != status) {
- ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for"
- "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status);
- }
- }
-
- res = addRotateCropTags();
- if (OK != res) {
- ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
- strerror(-res), res);
- }
- res = addPreCorrectionActiveArraySize();
- if (OK != res) {
- ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
- strerror(-res), res);
- }
- res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
- &mCameraCharacteristics, &mSupportNativeZoomRatio);
- if (OK != res) {
- ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
-
- camera_metadata_entry flashAvailable =
- mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
- if (flashAvailable.count == 1 &&
- flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
- mHasFlashUnit = true;
- } else {
- mHasFlashUnit = false;
- }
-
- camera_metadata_entry entry =
- mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
- if (entry.count == 1) {
- mTorchDefaultStrengthLevel = entry.data.i32[0];
- } else {
- mTorchDefaultStrengthLevel = 0;
- }
-
- entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
- if (entry.count == 1) {
- mTorchMaximumStrengthLevel = entry.data.i32[0];
- } else {
- mTorchMaximumStrengthLevel = 0;
- }
-
- mTorchStrengthLevel = 0;
- queryPhysicalCameraIds();
-
- // Get physical camera characteristics if applicable
- auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
- if (!castResult.isOk()) {
- ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
- return;
- }
- sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
- if (interface_3_5 == nullptr) {
- ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
- return;
- }
-
- if (mIsLogicalCamera) {
- for (auto& id : mPhysicalIds) {
- if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
- mPublicCameraIds.end()) {
- continue;
- }
-
- hardware::hidl_string hidlId(id);
- ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId,
- [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) {
- status = s;
- if (s == Status::OK) {
- camera_metadata_t *buffer =
- reinterpret_cast<camera_metadata_t*>(metadata.data());
- size_t expectedSize = metadata.size();
- int res = validate_camera_metadata_structure(buffer, &expectedSize);
- if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
- set_camera_metadata_vendor_id(buffer, mProviderTagid);
- mPhysicalCameraCharacteristics[id] = buffer;
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
- status = Status::INTERNAL_ERROR;
- }
- }
- });
-
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
- __FUNCTION__, id.c_str(), id.c_str(), ret.description().c_str());
- return;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
- __FUNCTION__, id.c_str(), mId.c_str(),
- CameraProviderManager::statusToString(status), status);
- return;
- }
-
- res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
- &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
- if (OK != res) {
- ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
- }
- }
-
- if (!kEnableLazyHal) {
- // Save HAL reference indefinitely
- mSavedInterface = interface;
- }
-}
-
-CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
-
-void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> newState) {
-
+void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(int64_t newState) {
if (!mDeviceStateOrientationMap.empty() &&
(mDeviceStateOrientationMap.find(newState) != mDeviceStateOrientationMap.end())) {
mCameraCharacteristics.update(ANDROID_SENSOR_ORIENTATION,
@@ -2673,84 +1682,6 @@
}
}
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::setTorchMode(bool enabled) {
- return setTorchModeForDevice<InterfaceT>(enabled);
-}
-
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::turnOnTorchWithStrengthLevel(
- int32_t torchStrength) {
- const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
- startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
- auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
- if (castResult_3_8.isOk()) {
- interface_3_8 = castResult_3_8;
- }
-
- if (interface_3_8 == nullptr) {
- return INVALID_OPERATION;
- }
-
- Status s = interface_3_8->turnOnTorchWithStrengthLevel(torchStrength);
- if (s == Status::OK) {
- mTorchStrengthLevel = torchStrength;
- }
- return mapToStatusT(s);
-}
-
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getTorchStrengthLevel(
- int32_t *torchStrength) {
- if (torchStrength == nullptr) {
- return BAD_VALUE;
- }
- const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
- startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
- if (castResult_3_8.isOk()) {
- interface_3_8 = castResult_3_8;
- }
-
- if (interface_3_8 == nullptr) {
- return INVALID_OPERATION;
- }
-
- Status callStatus;
- status_t res;
- hardware::Return<void> ret = interface_3_8->getTorchStrengthLevel([&callStatus, &torchStrength]
- (Status status, const int32_t& torchStrengthLevel) {
- callStatus = status;
- if (status == Status::OK) {
- *torchStrength = torchStrengthLevel;
- } });
-
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Get torch strength level failed: %d", __FUNCTION__, callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
-
- return res;
-}
-
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
hardware::CameraInfo *info) const {
if (info == nullptr) return BAD_VALUE;
@@ -2806,21 +1737,6 @@
return isBackwardCompatible;
}
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::dumpState(int fd) {
- native_handle_t* handle = native_handle_create(1,0);
- handle->data[0] = fd;
- const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- auto ret = interface->dumpState(handle);
- native_handle_delete(handle);
- if (!ret.isOk()) {
- return INVALID_OPERATION;
- }
- return OK;
-}
-
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacteristics(
bool overrideForPerfClass, CameraMetadata *characteristics) const {
if (characteristics == nullptr) return BAD_VALUE;
@@ -2846,81 +1762,6 @@
return OK;
}
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::isSessionConfigurationSupported(
- const hardware::camera::device::V3_8::StreamConfiguration &configuration,
- bool *status /*out*/) {
-
- const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
- this->startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- auto castResult_3_5 = device::V3_5::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult_3_5;
- auto castResult_3_7 = device::V3_7::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_7::ICameraDevice> interface_3_7 = castResult_3_7;
- auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = castResult_3_8;
-
- status_t res;
- Status callStatus;
- ::android::hardware::Return<void> ret;
- auto halCb =
- [&callStatus, &status] (Status s, bool combStatus) {
- callStatus = s;
- *status = combStatus;
- };
- if (interface_3_8 != nullptr) {
- ret = interface_3_8->isStreamCombinationSupported_3_8(configuration, halCb);
- } else if (interface_3_7 != nullptr) {
- hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
- bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
- configuration_3_7, configuration);
- if (!success) {
- *status = false;
- return OK;
- }
- ret = interface_3_7->isStreamCombinationSupported_3_7(configuration_3_7, halCb);
- } else if (interface_3_5 != nullptr) {
- hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
- bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
- configuration_3_7, configuration);
- if (!success) {
- *status = false;
- return OK;
- }
- hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
- success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
- configuration_3_4, configuration_3_7);
- if (!success) {
- *status = false;
- return OK;
- }
- ret = interface_3_5->isStreamCombinationSupported(configuration_3_4, halCb);
- } else {
- return INVALID_OPERATION;
- }
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
-
- return res;
-}
-
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::filterSmallJpegSizes() {
int32_t thresholdW = SessionConfigurationUtils::PERF_CLASS_JPEG_THRESH_W;
int32_t thresholdH = SessionConfigurationUtils::PERF_CLASS_JPEG_THRESH_H;
@@ -3172,8 +2013,6 @@
return OK;
}
-
-
CameraProviderManager::ProviderInfo::~ProviderInfo() {
if (mInitialStatusCallbackFuture.valid()) {
mInitialStatusCallbackFuture.wait();
@@ -3182,167 +2021,6 @@
// CameraProvider interface dies, so do not unregister callbacks.
}
-status_t CameraProviderManager::mapToStatusT(const Status& s) {
- switch(s) {
- case Status::OK:
- return OK;
- case Status::ILLEGAL_ARGUMENT:
- return BAD_VALUE;
- case Status::CAMERA_IN_USE:
- return -EBUSY;
- case Status::MAX_CAMERAS_IN_USE:
- return -EUSERS;
- case Status::METHOD_NOT_SUPPORTED:
- return UNKNOWN_TRANSACTION;
- case Status::OPERATION_NOT_SUPPORTED:
- return INVALID_OPERATION;
- case Status::CAMERA_DISCONNECTED:
- return DEAD_OBJECT;
- case Status::INTERNAL_ERROR:
- return INVALID_OPERATION;
- }
- ALOGW("Unexpected HAL status code %d", s);
- return INVALID_OPERATION;
-}
-
-const char* CameraProviderManager::statusToString(const Status& s) {
- switch(s) {
- case Status::OK:
- return "OK";
- case Status::ILLEGAL_ARGUMENT:
- return "ILLEGAL_ARGUMENT";
- case Status::CAMERA_IN_USE:
- return "CAMERA_IN_USE";
- case Status::MAX_CAMERAS_IN_USE:
- return "MAX_CAMERAS_IN_USE";
- case Status::METHOD_NOT_SUPPORTED:
- return "METHOD_NOT_SUPPORTED";
- case Status::OPERATION_NOT_SUPPORTED:
- return "OPERATION_NOT_SUPPORTED";
- case Status::CAMERA_DISCONNECTED:
- return "CAMERA_DISCONNECTED";
- case Status::INTERNAL_ERROR:
- return "INTERNAL_ERROR";
- }
- ALOGW("Unexpected HAL status code %d", s);
- return "UNKNOWN_ERROR";
-}
-
-const char* CameraProviderManager::deviceStatusToString(const CameraDeviceStatus& s) {
- switch(s) {
- case CameraDeviceStatus::NOT_PRESENT:
- return "NOT_PRESENT";
- case CameraDeviceStatus::PRESENT:
- return "PRESENT";
- case CameraDeviceStatus::ENUMERATING:
- return "ENUMERATING";
- }
- ALOGW("Unexpected HAL device status code %d", s);
- return "UNKNOWN_STATUS";
-}
-
-const char* CameraProviderManager::torchStatusToString(const TorchModeStatus& s) {
- switch(s) {
- case TorchModeStatus::NOT_AVAILABLE:
- return "NOT_AVAILABLE";
- case TorchModeStatus::AVAILABLE_OFF:
- return "AVAILABLE_OFF";
- case TorchModeStatus::AVAILABLE_ON:
- return "AVAILABLE_ON";
- }
- ALOGW("Unexpected HAL torch mode status code %d", s);
- return "UNKNOWN_STATUS";
-}
-
-
-status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
- const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
- /*out*/
- sp<VendorTagDescriptor>& descriptor) {
-
- int 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);
- return BAD_VALUE;
- }
-
- Vector<uint32_t> tagArray;
- LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
- "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
-
-
- sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
- desc->mTagCount = tagCount;
-
- SortedVector<String8> sections;
- KeyedVector<uint32_t, String8> tagToSectionMap;
-
- int idx = 0;
- for (size_t s = 0; s < vts.size(); s++) {
- const common::V1_0::VendorTagSection& section = vts[s];
- const char *sectionName = section.sectionName.c_str();
- if (sectionName == NULL) {
- ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
- return BAD_VALUE;
- }
- String8 sectionString(sectionName);
- sections.add(sectionString);
-
- for (size_t j = 0; j < section.tags.size(); j++) {
- uint32_t tag = section.tags[j].tagId;
- if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
- ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
- return BAD_VALUE;
- }
-
- tagArray.editItemAt(idx++) = section.tags[j].tagId;
-
- const char *tagName = section.tags[j].tagName.c_str();
- if (tagName == NULL) {
- 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);
-
- int tagType = (int) section.tags[j].tagType;
- if (tagType < 0 || tagType >= NUM_TYPES) {
- ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
- return BAD_VALUE;
- }
- desc->mTagToTypeMap.add(tag, tagType);
- }
- }
-
- desc->mSections = sections;
-
- for (size_t i = 0; i < tagArray.size(); ++i) {
- uint32_t tag = tagArray[i];
- String8 sectionString = tagToSectionMap.valueFor(tag);
-
- // Set up tag to section index map
- ssize_t index = sections.indexOf(sectionString);
- LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
- desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
-
- // Set up reverse mapping
- ssize_t reverseIndex = -1;
- if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
- KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
- reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
- }
- desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
- }
-
- descriptor = std::move(desc);
- return OK;
-}
-
// Expects to have mInterfaceMutex locked
std::vector<std::unordered_set<std::string>>
CameraProviderManager::getConcurrentCameraIds() const {
@@ -3356,60 +2034,6 @@
return deviceIdCombinations;
}
-status_t CameraProviderManager::convertToHALStreamCombinationAndCameraIdsLocked(
- const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
- const std::set<std::string>& perfClassPrimaryCameraIds,
- int targetSdkVersion,
- hardware::hidl_vec<CameraIdAndStreamCombination> *halCameraIdsAndStreamCombinations,
- bool *earlyExit) {
- binder::Status bStatus = binder::Status::ok();
- std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
- bool shouldExit = false;
- status_t res = OK;
- for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
- const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
- hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
- CameraMetadata deviceInfo;
- bool overrideForPerfClass =
- SessionConfigurationUtils::targetPerfClassPrimaryCamera(
- perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
- res = getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo);
- if (res != OK) {
- return res;
- }
- camera3::metadataGetter getMetadata =
- [this](const String8 &id, bool overrideForPerfClass) {
- CameraMetadata physicalDeviceInfo;
- getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
- &physicalDeviceInfo);
- return physicalDeviceInfo;
- };
- std::vector<std::string> physicalCameraIds;
- isLogicalCameraLocked(cameraId, &physicalCameraIds);
- bStatus =
- SessionConfigurationUtils::convertToHALStreamCombination(
- cameraIdAndSessionConfig.mSessionConfiguration,
- String8(cameraId.c_str()), deviceInfo, getMetadata,
- physicalCameraIds, streamConfiguration,
- overrideForPerfClass, &shouldExit);
- if (!bStatus.isOk()) {
- ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
- return INVALID_OPERATION;
- }
- if (shouldExit) {
- *earlyExit = true;
- return OK;
- }
- CameraIdAndStreamCombination halCameraIdAndStream;
- halCameraIdAndStream.cameraId = cameraId;
- SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
- halCameraIdAndStream.streamConfiguration, streamConfiguration);
- halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
- }
- *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
- return OK;
-}
-
// Checks if the containing vector of sets has any set that contains all of the
// camera ids in cameraIdsAndSessionConfigs.
static bool checkIfSetContainsAll(
@@ -3444,27 +2068,9 @@
for (auto &provider : mProviders) {
if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
provider->getConcurrentCameraIdCombinations())) {
- // For each camera device in cameraIdsAndSessionConfigs collect
- // the streamConfigs and create the HAL
- // CameraIdAndStreamCombination, exit early if needed
- hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
- bool knowUnsupported = false;
- status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
- cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
- targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
- if (res != OK) {
- ALOGE("%s unable to convert session configurations provided to HAL stream"
- "combinations", __FUNCTION__);
- return res;
- }
- if (knowUnsupported) {
- // We got to know the streams aren't valid before doing the HAL
- // call itself.
- *isSupported = false;
- return OK;
- }
return provider->isConcurrentSessionConfigurationSupported(
- halCameraIdsAndStreamCombinations, isSupported);
+ cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds, targetSdkVersion,
+ isSupported);
}
}
*isSupported = false;
@@ -3474,7 +2080,7 @@
status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
bool overrideForPerfClass, CameraMetadata* characteristics) const {
- auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});
+ auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3, 0}, /*maxVersion*/ {5, 0});
if (deviceInfo != nullptr) {
return deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics);
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index ac710bf..64f5abf 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -32,6 +32,7 @@
#include <utils/Condition.h>
#include <utils/Errors.h>
#include <android/hardware/ICameraService.h>
+#include <utils/IPCTransport.h>
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
@@ -40,26 +41,28 @@
#include <android/hardware/camera/device/3.7/types.h>
#include <android/hardware/camera/device/3.8/types.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <binder/IServiceManager.h>
#include <camera/VendorTagDescriptor.h>
namespace android {
-/**
- * The vendor tag descriptor class that takes HIDL vendor tag information as
- * input. Not part of VendorTagDescriptor class because that class is used
- * in AIDL generated sources which don't have access to HIDL headers.
- */
-class HidlVendorTagDescriptor : public VendorTagDescriptor {
-public:
- /**
- * Create a VendorTagDescriptor object from the HIDL VendorTagSection
- * vector.
- *
- * Returns OK on success, or a negative error code.
- */
- static status_t createDescriptorFromHidl(
- const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
- /*out*/
- sp<VendorTagDescriptor>& descriptor);
+
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+
+enum class CameraDeviceStatus : uint32_t {
+ NOT_PRESENT = 0,
+ PRESENT = 1,
+ ENUMERATING = 2
+};
+
+enum class TorchModeStatus : uint32_t {
+ NOT_AVAILABLE = 0,
+ AVAILABLE_OFF = 1,
+ AVAILABLE_ON = 2
+};
+
+struct CameraResourceCost {
+ uint32_t resourceCost;
+ std::vector<std::string> conflictingDevices;
};
enum SystemCameraKind {
@@ -105,12 +108,14 @@
*/
class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotification {
public:
-
+ // needs to be made friend strict since HidlProviderInfo needs to inherit
+ // from CameraProviderManager::ProviderInfo which isn't a public member.
+ friend struct HidlProviderInfo;
~CameraProviderManager();
// Tiny proxy for the static methods in a HIDL interface that communicate with the hardware
// service manager, to be replacable in unit tests with a fake.
- struct ServiceInteractionProxy {
+ struct HidlServiceInteractionProxy {
virtual bool registerForNotifications(
const std::string &serviceName,
const sp<hidl::manager::V1_0::IServiceNotification>
@@ -122,12 +127,12 @@
virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
const std::string &serviceName) = 0;
virtual hardware::hidl_vec<hardware::hidl_string> listServices() = 0;
- virtual ~ServiceInteractionProxy() {}
+ virtual ~HidlServiceInteractionProxy() {}
};
// Standard use case - call into the normal generated static methods which invoke
// the real hardware service manager
- struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
+ struct HidlServiceInteractionProxyImpl : public HidlServiceInteractionProxy {
virtual bool registerForNotifications(
const std::string &serviceName,
const sp<hidl::manager::V1_0::IServiceNotification>
@@ -154,15 +159,15 @@
~StatusListener() {}
virtual void onDeviceStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+ CameraDeviceStatus newStatus) = 0;
virtual void onDeviceStatusChanged(const String8 &cameraId,
const String8 &physicalCameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+ CameraDeviceStatus newStatus) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
+ TorchModeStatus newStatus,
SystemCameraKind kind) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus) = 0;
+ TorchModeStatus newStatus) = 0;
virtual void onNewProviderRegistered() = 0;
};
@@ -182,7 +187,10 @@
* used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
*/
status_t initialize(wp<StatusListener> listener,
- ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
+ HidlServiceInteractionProxy *hidlProxy = &sHidlServiceInteractionProxy);
+
+ status_t getCameraIdIPCTransport(const std::string &id,
+ IPCTransport *providerTransport) const;
/**
* Retrieve the total number of available cameras.
@@ -220,7 +228,7 @@
* Return the resource cost of this camera device
*/
status_t getResourceCost(const std::string &id,
- hardware::camera::common::V1_0::CameraResourceCost* cost) const;
+ CameraResourceCost* cost) const;
/**
* Return the old camera API camera info
@@ -246,7 +254,8 @@
* Check for device support of specific stream combination.
*/
status_t isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_8::StreamConfiguration &configuration,
+ const SessionConfiguration &configuration,
+ bool overrideForPerfClass,
bool *status /*out*/) const;
/**
@@ -304,8 +313,7 @@
/**
* Inform registered providers about a device state change, such as folding or unfolding
*/
- status_t notifyDeviceStateChange(
- android::hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> newState);
+ status_t notifyDeviceStateChange(int64_t newState);
/**
* Open an active session to a camera device.
@@ -313,7 +321,7 @@
* This fully powers on the camera device hardware, and returns a handle to a
* session to be used for hardware configuration and operation.
*/
- status_t openSession(const std::string &id,
+ status_t openHidlSession(const std::string &id,
const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session);
@@ -368,35 +376,48 @@
mutable std::mutex mInterfaceMutex;
wp<StatusListener> mListener;
- ServiceInteractionProxy* mServiceProxy;
+ HidlServiceInteractionProxy* mHidlServiceProxy;
// Current overall Android device physical status
- android::hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> mDeviceState;
+ int64_t mDeviceState;
// mProviderLifecycleLock is locked during onRegistration and removeProvider
mutable std::mutex mProviderLifecycleLock;
- static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;
+ static HidlServiceInteractionProxyImpl sHidlServiceInteractionProxy;
+
+ struct HalCameraProvider {
+ // Empty parent struct for storing either aidl / hidl camera provider reference
+ HalCameraProvider(const char *descriptor) : mDescriptor(descriptor) { };
+ virtual ~HalCameraProvider() {};
+ std::string mDescriptor;
+ };
+
+ struct HidlHalCameraProvider : public HalCameraProvider {
+ HidlHalCameraProvider(
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> &provider,
+ const char *descriptor) :
+ HalCameraProvider(descriptor), mCameraProvider(provider) { };
+ private:
+ sp<hardware::camera::provider::V2_4::ICameraProvider> mCameraProvider;
+ };
// Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
// ICameraProvider alive while it is in use by the camera with the given ID for camera
// capabilities
- std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>>
mCameraProviderByCameraId;
// Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
// ICameraProvider alive while it is in use by the camera with the given ID for torch
// capabilities
- std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>>
mTorchProviderByCameraId;
// Lock for accessing mCameraProviderByCameraId and mTorchProviderByCameraId
std::mutex mProviderInterfaceMapLock;
-
- struct ProviderInfo :
- virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
- virtual public hardware::hidl_death_recipient
- {
+ struct ProviderInfo : public virtual RefBase {
+ friend struct HidlProviderInfo;
const std::string mProviderName;
const std::string mProviderInstance;
const metadata_vendor_id_t mProviderTagid;
@@ -405,61 +426,20 @@
bool mSetTorchModeSupported;
bool mIsRemote;
- // Current overall Android device physical status
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> mDeviceState;
-
- // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
- wp<hardware::camera::provider::V2_4::ICameraProvider> mActiveInterface;
-
- sp<hardware::camera::provider::V2_4::ICameraProvider> mSavedInterface;
-
ProviderInfo(const std::string &providerName, const std::string &providerInstance,
CameraProviderManager *manager);
~ProviderInfo();
- status_t initialize(sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- currentDeviceState);
-
- const sp<hardware::camera::provider::V2_4::ICameraProvider> startProviderInterface();
+ virtual IPCTransport getIPCTransport() = 0;
const std::string& getType() const;
- status_t addDevice(const std::string& name,
- hardware::camera::common::V1_0::CameraDeviceStatus initialStatus =
- hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT,
- /*out*/ std::string *parsedId = nullptr);
-
status_t dump(int fd, const Vector<String16>& args) const;
- // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
- hardware::Return<void> cameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
- hardware::Return<void> torchModeStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
- hardware::Return<void> physicalCameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
-
- status_t cameraDeviceStatusChangeLocked(
- std::string* id, const hardware::hidl_string& cameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
- status_t physicalCameraDeviceStatusChangeLocked(
- std::string* id, std::string* physicalId,
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
-
- // hidl_death_recipient interface - this locks the parent mInterfaceMutex
- virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
-
/**
* Setup vendor tags for this provider
*/
- status_t setUpVendorTags();
+ virtual status_t setUpVendorTags() = 0;
/**
* Notify provider about top-level device physical state changes
@@ -468,9 +448,9 @@
* It is possible for camera providers to add/remove devices and try to
* acquire it.
*/
- status_t notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- newDeviceState);
+ virtual status_t notifyDeviceStateChange(int64_t newDeviceState) = 0;
+
+ virtual bool successfullyStartedProviderInterface() = 0;
std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
@@ -479,18 +459,16 @@
*
* Note that 'mInterfaceMutex' should be held when calling this method.
*/
- void notifyDeviceInfoStateChangeLocked(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- newDeviceState);
+ void notifyDeviceInfoStateChangeLocked(int64_t newDeviceState);
/**
* Query the camera provider for concurrent stream configuration support
*/
- status_t isConcurrentSessionConfigurationSupported(
- const hardware::hidl_vec<
- hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
- &halCameraIdsAndStreamCombinations,
- bool *isSupported);
+ virtual status_t isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) = 0;
+
/**
* Remove all devices associated with this provider and notify listeners
@@ -507,17 +485,18 @@
struct DeviceInfo {
const std::string mName; // Full instance name
const std::string mId; // ID section of full name
+ //Both hidl and aidl DeviceInfos. Aidl deviceInfos get {3, 8} to
+ //start off.
const hardware::hidl_version mVersion;
const metadata_vendor_id_t mProviderTagid;
bool mIsLogicalCamera;
std::vector<std::string> mPhysicalIds;
hardware::CameraInfo mInfo;
- sp<IBase> mSavedInterface;
SystemCameraKind mSystemCameraKind = SystemCameraKind::PUBLIC;
- const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
+ const CameraResourceCost mResourceCost;
- hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
+ CameraDeviceStatus mStatus;
wp<ProviderInfo> mParentProvider;
// Torch strength default, maximum levels if the torch strength control
@@ -554,46 +533,32 @@
}
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_8::StreamConfiguration &/*configuration*/,
+ const SessionConfiguration &/*configuration*/,
+ bool /*overrideForPerfClass*/,
bool * /*status*/) {
return INVALID_OPERATION;
}
virtual status_t filterSmallJpegSizes() = 0;
- virtual void notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- /*newState*/) {}
-
- template<class InterfaceT>
- sp<InterfaceT> startDeviceInterface();
+ virtual void notifyDeviceStateChange(int64_t /*newState*/) {}
DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, const hardware::hidl_version& version,
const std::vector<std::string>& publicCameraIds,
- const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+ const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider) :
mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
mIsLogicalCamera(false), mResourceCost(resourceCost),
- mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
+ mStatus(CameraDeviceStatus::PRESENT),
mParentProvider(parentProvider), mTorchStrengthLevel(0),
mTorchMaximumStrengthLevel(0), mTorchDefaultStrengthLevel(0),
mHasFlashUnit(false), mSupportNativeZoomRatio(false),
mPublicCameraIds(publicCameraIds) {}
- virtual ~DeviceInfo();
+ virtual ~DeviceInfo() {}
protected:
+
bool mHasFlashUnit; // const after constructor
bool mSupportNativeZoomRatio; // const after constructor
const std::vector<std::string>& mPublicCameraIds;
-
- template<class InterfaceT>
- static status_t setTorchMode(InterfaceT& interface, bool enabled);
-
- template<class InterfaceT>
- status_t setTorchModeForDevice(bool enabled) {
- // Don't save the ICameraProvider interface here because we assume that this was
- // called from CameraProviderManager::setTorchMode(), which does save it.
- const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
- return DeviceInfo::setTorchMode(interface, enabled);
- }
};
std::vector<std::unique_ptr<DeviceInfo>> mDevices;
std::unordered_set<std::string> mUniqueCameraIds;
@@ -608,36 +573,33 @@
// HALv3-specific camera fields, including the actual device interface
struct DeviceInfo3 : public DeviceInfo {
- typedef hardware::camera::device::V3_2::ICameraDevice InterfaceT;
- virtual status_t setTorchMode(bool enabled) override;
- virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) override;
- virtual status_t getTorchStrengthLevel(int32_t *torchStrength) override;
-
+ virtual status_t setTorchMode(bool enabled) = 0;
+ virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) = 0;
+ virtual status_t getTorchStrengthLevel(int32_t *torchStrength) = 0;
virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
virtual bool isAPI1Compatible() const override;
- virtual status_t dumpState(int fd) override;
+ virtual status_t dumpState(int fd) = 0;
virtual status_t getCameraCharacteristics(
bool overrideForPerfClass,
CameraMetadata *characteristics) const override;
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const override;
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_8::StreamConfiguration &configuration,
- bool *status /*out*/)
- override;
+ const SessionConfiguration &configuration, bool /*overrideForPerfClass*/,
+ bool *status /*out*/) = 0;
virtual status_t filterSmallJpegSizes() override;
virtual void notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- newState) override;
+ int64_t newState) override;
DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,
- const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+ const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider,
- const std::vector<std::string>& publicCameraIds, sp<InterfaceT> interface);
- virtual ~DeviceInfo3();
- private:
+ const std::vector<std::string>& publicCameraIds);
+ virtual ~DeviceInfo3() {};
+ protected:
+ // Modified by derived transport specific (hidl / aidl) class
CameraMetadata mCameraCharacteristics;
// Map device states to sensor orientations
std::unordered_map<int64_t, int32_t> mDeviceStateOrientationMap;
@@ -677,8 +639,7 @@
const camera_metadata_entry& halStreamConfigs,
const camera_metadata_entry& halStreamDurations);
};
-
- private:
+ protected:
std::string mType;
uint32_t mId;
@@ -688,12 +649,12 @@
struct CameraStatusInfoT {
bool isPhysicalCameraStatus = false;
- hardware::hidl_string cameraId;
- hardware::hidl_string physicalCameraId;
- hardware::camera::common::V1_0::CameraDeviceStatus status;
- CameraStatusInfoT(bool isForPhysicalCamera, const hardware::hidl_string& id,
- const hardware::hidl_string& physicalId,
- hardware::camera::common::V1_0::CameraDeviceStatus s) :
+ std::string cameraId;
+ std::string physicalCameraId;
+ CameraDeviceStatus status;
+ CameraStatusInfoT(bool isForPhysicalCamera, const std::string& id,
+ const std::string& physicalId,
+ CameraDeviceStatus s) :
isPhysicalCameraStatus(isForPhysicalCamera), cameraId(id),
physicalCameraId(physicalId), status(s) {}
};
@@ -710,17 +671,6 @@
std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
- // Templated method to instantiate the right kind of DeviceInfo and call the
- // right CameraProvider getCameraDeviceInterface_* method.
- template<class DeviceInfoT>
- std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &name,
- const metadata_vendor_id_t tagId, const std::string &id,
- uint16_t minorVersion);
-
- // Helper for initializeDeviceInfo to use the right CameraProvider get method.
- template<class InterfaceT>
- sp<InterfaceT> startDeviceInterface(const std::string &name);
-
// Parse provider instance name for type and id
static status_t parseProviderName(const std::string& name,
std::string *type, uint32_t *id);
@@ -734,18 +684,13 @@
void removeDevice(std::string id);
- // Expects to have mLock locked
- status_t reCacheConcurrentStreamingCameraIdsLocked();
- // Expects to have mLock locked
- status_t getConcurrentCameraIdsInternalLocked(
- sp<hardware::camera::provider::V2_6::ICameraProvider> &interface2_6);
};
/**
* Save the ICameraProvider while it is being used by a camera or torch client
*/
void saveRef(DeviceMode usageType, const std::string &cameraId,
- sp<hardware::camera::provider::V2_4::ICameraProvider> provider);
+ std::shared_ptr<HalCameraProvider> provider);
// Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
// and the calling code doesn't mutate the list of providers or their lists of devices.
@@ -762,9 +707,9 @@
mExternalUsbDevicesForProvider;
sp<ProviderInfo> startExternalLazyProvider() const;
- status_t addProviderLocked(const std::string& newProvider, bool preexisting = false);
+ status_t addHidlProviderLocked(const std::string& newProvider, bool preexisting = false);
- status_t tryToInitializeProviderLocked(const std::string& providerName,
+ status_t tryToInitializeHidlProviderLocked(const std::string& providerName,
const sp<ProviderInfo>& providerInfo);
bool isLogicalCameraLocked(const std::string& id, std::vector<std::string>* physicalCameraIds);
@@ -777,14 +722,6 @@
size_t mProviderInstanceId = 0;
std::vector<sp<ProviderInfo>> mProviders;
- void addProviderToMap(
- const std::string &cameraId,
- sp<hardware::camera::provider::V2_4::ICameraProvider> provider,
- bool isTorchUsage);
- void removeCameraIdFromMap(
- std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>> &map,
- const std::string &cameraId);
-
static const char* deviceStatusToString(
const hardware::camera::common::V1_0::CameraDeviceStatus&);
static const char* torchStatusToString(
@@ -795,21 +732,13 @@
void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
status_t getSystemCameraKindLocked(const std::string& id, SystemCameraKind *kind) const;
- std::pair<bool, ProviderInfo::DeviceInfo *> isHiddenPhysicalCameraInternal(const std::string& cameraId) const;
+ std::pair<bool, ProviderInfo::DeviceInfo *> isHiddenPhysicalCameraInternal(
+ const std::string& cameraId) const;
void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
std::vector<std::string>& normalDeviceIds,
std::vector<std::string>& systemCameraDeviceIds) const;
- status_t convertToHALStreamCombinationAndCameraIdsLocked(
- const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
- &cameraIdsAndSessionConfigs,
- const std::set<std::string>& perfClassPrimaryCameraIds,
- int targetSdkVersion,
- hardware::hidl_vec<hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
- *halCameraIdsAndStreamCombinations,
- bool *earlyExit);
-
status_t usbDeviceDetached(const std::string &usbDeviceId);
};
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
new file mode 100644
index 0000000..e8432a6
--- /dev/null
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -0,0 +1,1564 @@
+/*
+ * 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 "HidlProviderInfo.h"
+
+#include <cutils/properties.h>
+
+#include <android/hardware/ICameraService.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/ZoomRatioMapper.h"
+#include <utils/SessionConfigurationUtils.h>
+#include <utils/Trace.h>
+
+#include <android/hardware/camera/device/3.7/ICameraDevice.h>
+#include <android/hardware/camera/device/3.8/ICameraDevice.h>
+
+namespace {
+const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+} // anonymous namespace
+
+namespace android {
+
+using namespace android::camera3;
+using namespace hardware::camera;
+using hardware::camera::common::V1_0::VendorTagSection;
+using hardware::camera::common::V1_0::Status;
+using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+
+
+using StatusListener = CameraProviderManager::StatusListener;
+
+using hardware::camera::provider::V2_5::DeviceState;
+using hardware::ICameraService;
+
+status_t HidlProviderInfo::mapToStatusT(const Status& s) {
+ switch(s) {
+ case Status::OK:
+ return OK;
+ case Status::ILLEGAL_ARGUMENT:
+ return BAD_VALUE;
+ case Status::CAMERA_IN_USE:
+ return -EBUSY;
+ case Status::MAX_CAMERAS_IN_USE:
+ return -EUSERS;
+ case Status::METHOD_NOT_SUPPORTED:
+ return UNKNOWN_TRANSACTION;
+ case Status::OPERATION_NOT_SUPPORTED:
+ return INVALID_OPERATION;
+ case Status::CAMERA_DISCONNECTED:
+ return DEAD_OBJECT;
+ case Status::INTERNAL_ERROR:
+ return INVALID_OPERATION;
+ }
+ ALOGW("Unexpected HAL status code %d", s);
+ return INVALID_OPERATION;
+}
+
+static hardware::hidl_bitfield<DeviceState> mapToHidlDeviceState(int64_t newState) {
+ hardware::hidl_bitfield<DeviceState> newDeviceState{};
+ if (newState & ICameraService::DEVICE_STATE_BACK_COVERED) {
+ newDeviceState |= DeviceState::BACK_COVERED;
+ }
+ if (newState & ICameraService::DEVICE_STATE_FRONT_COVERED) {
+ newDeviceState |= DeviceState::FRONT_COVERED;
+ }
+ if (newState & ICameraService::DEVICE_STATE_FOLDED) {
+ newDeviceState |= DeviceState::FOLDED;
+ }
+ // Only map vendor bits directly
+ uint64_t vendorBits = static_cast<uint64_t>(newState) & 0xFFFFFFFF00000000l;
+ newDeviceState |= vendorBits;
+
+ ALOGV("%s: New device state 0x%" PRIx64, __FUNCTION__, newDeviceState);
+ return newDeviceState;
+}
+
+const char* statusToString(const Status& s) {
+ switch(s) {
+ case Status::OK:
+ return "OK";
+ case Status::ILLEGAL_ARGUMENT:
+ return "ILLEGAL_ARGUMENT";
+ case Status::CAMERA_IN_USE:
+ return "CAMERA_IN_USE";
+ case Status::MAX_CAMERAS_IN_USE:
+ return "MAX_CAMERAS_IN_USE";
+ case Status::METHOD_NOT_SUPPORTED:
+ return "METHOD_NOT_SUPPORTED";
+ case Status::OPERATION_NOT_SUPPORTED:
+ return "OPERATION_NOT_SUPPORTED";
+ case Status::CAMERA_DISCONNECTED:
+ return "CAMERA_DISCONNECTED";
+ case Status::INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ }
+ ALOGW("Unexpected HAL status code %d", s);
+ return "UNKNOWN_ERROR";
+}
+
+static common::V1_0::CameraDeviceStatus mapToHidlCameraDeviceStatus(const CameraDeviceStatus& s) {
+ switch(s) {
+ case CameraDeviceStatus::PRESENT:
+ return common::V1_0::CameraDeviceStatus::PRESENT;
+ case CameraDeviceStatus::NOT_PRESENT:
+ return common::V1_0::CameraDeviceStatus::NOT_PRESENT;
+ case CameraDeviceStatus::ENUMERATING:
+ return common::V1_0::CameraDeviceStatus::ENUMERATING;
+ }
+ ALOGW("Unexpectedcamera device status code %d", s);
+ return common::V1_0::CameraDeviceStatus::NOT_PRESENT;
+}
+
+static CameraDeviceStatus hidlToInternalCameraDeviceStatus(
+ const common::V1_0::CameraDeviceStatus& s) {
+ switch(s) {
+ case common::V1_0::CameraDeviceStatus::PRESENT:
+ return CameraDeviceStatus::PRESENT;
+ case common::V1_0::CameraDeviceStatus::NOT_PRESENT:
+ return CameraDeviceStatus::NOT_PRESENT;
+ case common::V1_0::CameraDeviceStatus::ENUMERATING:
+ return CameraDeviceStatus::ENUMERATING;
+ }
+ ALOGW("Unexpectedcamera device status code %d", s);
+ return CameraDeviceStatus::NOT_PRESENT;
+}
+
+static TorchModeStatus hidlToInternalTorchModeStatus(
+ const common::V1_0::TorchModeStatus& s) {
+ switch(s) {
+ case common::V1_0::TorchModeStatus::NOT_AVAILABLE:
+ return TorchModeStatus::NOT_AVAILABLE;
+ case common::V1_0::TorchModeStatus::AVAILABLE_OFF:
+ return TorchModeStatus::AVAILABLE_OFF;
+ case common::V1_0::TorchModeStatus::AVAILABLE_ON:
+ return TorchModeStatus::AVAILABLE_ON;
+ }
+ ALOGW("Unexpectedcamera torch mode status code %d", s);
+ return TorchModeStatus::NOT_AVAILABLE;
+}
+
+static CameraResourceCost hidlToInternalResourceCost(
+ const common::V1_0::CameraResourceCost& s) {
+ CameraResourceCost internalResourceCost;
+ internalResourceCost.resourceCost = s.resourceCost;
+ for (const auto device : s.conflictingDevices) {
+ internalResourceCost.conflictingDevices.emplace_back(device.c_str());
+ }
+ return internalResourceCost;
+}
+
+static const char* deviceStatusToString(const common::V1_0::CameraDeviceStatus& s) {
+ switch(s) {
+ case common::V1_0::CameraDeviceStatus::NOT_PRESENT:
+ return "NOT_PRESENT";
+ case common::V1_0::CameraDeviceStatus::PRESENT:
+ return "PRESENT";
+ case common::V1_0::CameraDeviceStatus::ENUMERATING:
+ return "ENUMERATING";
+ }
+ ALOGW("Unexpected HAL device status code %d", s);
+ return "UNKNOWN_STATUS";
+}
+
+static const char* torchStatusToString(const common::V1_0::TorchModeStatus& s) {
+ switch(s) {
+ case common::V1_0::TorchModeStatus::NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case common::V1_0::TorchModeStatus::AVAILABLE_OFF:
+ return "AVAILABLE_OFF";
+ case common::V1_0::TorchModeStatus::AVAILABLE_ON:
+ return "AVAILABLE_ON";
+ }
+ ALOGW("Unexpected HAL torch mode status code %d", s);
+ return "UNKNOWN_STATUS";
+}
+
+status_t HidlProviderInfo::initializeHidlProvider(
+ sp<provider::V2_4::ICameraProvider>& interface,
+ int64_t currentDeviceState) {
+ status_t res = parseProviderName(mProviderName, &mType, &mId);
+ if (res != OK) {
+ ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ ALOGI("Connecting to new camera provider: %s, isRemote? %d",
+ mProviderName.c_str(), interface->isRemote());
+
+ // Determine minor version
+ mMinorVersion = 4;
+ auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+ sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
+ if (cast2_6.isOk()) {
+ interface2_6 = cast2_6;
+ if (interface2_6 != nullptr) {
+ mMinorVersion = 6;
+ }
+ }
+ // We need to check again since cast2_6.isOk() succeeds even if the provider
+ // version isn't actually 2.6.
+ if (interface2_6 == nullptr){
+ auto cast2_5 =
+ provider::V2_5::ICameraProvider::castFrom(interface);
+ sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
+ if (cast2_5.isOk()) {
+ interface2_5 = cast2_5;
+ if (interface != nullptr) {
+ mMinorVersion = 5;
+ }
+ }
+ } else {
+ auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
+ if (cast2_7.isOk()) {
+ sp<provider::V2_7::ICameraProvider> interface2_7 = cast2_7;
+ if (interface2_7 != nullptr) {
+ mMinorVersion = 7;
+ }
+ }
+ }
+
+ // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+ // before setCallback returns
+ hardware::Return<Status> status = interface->setCallback(this);
+ if (!status.isOk()) {
+ ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), status.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+
+ hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
+ if (!linked.isOk()) {
+ ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
+ __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+ return DEAD_OBJECT;
+ } else if (!linked) {
+ ALOGW("%s: Unable to link to provider '%s' death notifications",
+ __FUNCTION__, mProviderName.c_str());
+ }
+
+ if (!kEnableLazyHal) {
+ // Save HAL reference indefinitely
+ mSavedInterface = interface;
+ } else {
+ mActiveInterface = interface;
+ }
+
+ ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
+ __FUNCTION__, mProviderName.c_str(), mDeviceState);
+ notifyDeviceStateChange(currentDeviceState);
+
+ res = setUpVendorTags();
+ if (res != OK) {
+ ALOGE("%s: Unable to set up vendor tags from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return res;
+ }
+
+ // Get initial list of camera devices, if any
+ std::vector<std::string> devices;
+ hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
+ Status idStatus,
+ const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
+ status = idStatus;
+ if (status == Status::OK) {
+ for (auto& name : cameraDeviceNames) {
+ uint16_t major, minor;
+ std::string type, id;
+ status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+ if (res != OK) {
+ ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
+ status = Status::INTERNAL_ERROR;
+ } else {
+ devices.push_back(name);
+ mProviderPublicCameraIds.push_back(id);
+ }
+ }
+ } });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+
+ // Get list of concurrent streaming camera device combinations
+ if (mMinorVersion >= 6) {
+ res = getConcurrentCameraIdsInternalLocked(interface2_6);
+ if (res != OK) {
+ return res;
+ }
+ }
+
+ ret = interface->isSetTorchModeSupported(
+ [this](auto status, bool supported) {
+ if (status == Status::OK) {
+ mSetTorchModeSupported = supported;
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error checking torch mode support '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ mIsRemote = interface->isRemote();
+
+ sp<StatusListener> listener = mManager->getStatusListener();
+ for (auto& device : devices) {
+ std::string id;
+ status_t res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
+ if (res != OK) {
+ ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
+ __FUNCTION__, device.c_str(), strerror(-res), res);
+ continue;
+ }
+ }
+
+ ALOGI("Camera provider %s ready with %zu camera devices",
+ mProviderName.c_str(), mDevices.size());
+
+ // Process cached status callbacks
+ std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
+ std::make_unique<std::vector<CameraStatusInfoT>>();
+ {
+ std::lock_guard<std::mutex> lock(mInitLock);
+
+ for (auto& statusInfo : mCachedStatus) {
+ std::string id, physicalId;
+ status_t res = OK;
+ if (statusInfo.isPhysicalCameraStatus) {
+ res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
+ statusInfo.cameraId, statusInfo.physicalCameraId,
+ mapToHidlCameraDeviceStatus(statusInfo.status));
+ } else {
+ res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId,
+ mapToHidlCameraDeviceStatus(statusInfo.status));
+ }
+ if (res == OK) {
+ cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
+ id.c_str(), physicalId.c_str(), statusInfo.status);
+ }
+ }
+ mCachedStatus.clear();
+
+ mInitialized = true;
+ }
+
+ // The cached status change callbacks cannot be fired directly from this
+ // function, due to same-thread deadlock trying to acquire mInterfaceMutex
+ // twice.
+ if (listener != nullptr) {
+ mInitialStatusCallbackFuture = std::async(std::launch::async,
+ &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
+ listener, std::move(cachedStatus));
+ }
+
+ return OK;
+}
+
+status_t HidlProviderInfo::setUpVendorTags() {
+ if (mVendorTagDescriptor != nullptr)
+ return OK;
+
+ hardware::hidl_vec<VendorTagSection> vts;
+ Status status;
+ hardware::Return<void> ret;
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> interface =
+ startProviderInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ ret = interface->getVendorTags(
+ [&](auto s, const auto& vendorTagSecs) {
+ status = s;
+ if (s == Status::OK) {
+ vts = vendorTagSecs;
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ return mapToStatusT(status);
+ }
+
+ // Read all vendor tag definitions into a descriptor
+ status_t res;
+ if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/mVendorTagDescriptor))
+ != OK) {
+ ALOGE("%s: Could not generate descriptor from vendor tag operations,"
+ "received error %s (%d). Camera clients will not be able to use"
+ "vendor tags", __FUNCTION__, strerror(res), res);
+ return res;
+ }
+
+ return OK;
+}
+
+status_t HidlProviderInfo::notifyDeviceStateChange(int64_t newDeviceState) {
+ mDeviceState = mapToHidlDeviceState(newDeviceState);
+ if (mMinorVersion >= 5) {
+ // Check if the provider is currently active - not going to start it for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface != nullptr) {
+ // Send current device state
+ auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
+ if (castResult.isOk()) {
+ sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
+ if (interface_2_5 != nullptr) {
+ interface_2_5->notifyDeviceStateChange(mDeviceState);
+ }
+ }
+ }
+ }
+ return OK;
+}
+
+sp<device::V3_2::ICameraDevice>
+HidlProviderInfo::startDeviceInterface(const std::string &name) {
+ Status status;
+ sp<device::V3_2::ICameraDevice> cameraInterface;
+ hardware::Return<void> ret;
+ const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+ if (interface == nullptr) {
+ return nullptr;
+ }
+ ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
+ Status s, sp<device::V3_2::ICameraDevice> interface) {
+ status = s;
+ cameraInterface = interface;
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
+ __FUNCTION__, name.c_str(), ret.description().c_str());
+ return nullptr;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+ return cameraInterface;
+}
+
+bool HidlProviderInfo::successfullyStartedProviderInterface() {
+ return startProviderInterface() != nullptr;
+}
+
+const sp<provider::V2_4::ICameraProvider>
+HidlProviderInfo::startProviderInterface() {
+ ATRACE_CALL();
+ ALOGV("Request to start camera provider: %s", mProviderName.c_str());
+ if (mSavedInterface != nullptr) {
+ return mSavedInterface;
+ }
+ if (!kEnableLazyHal) {
+ ALOGE("Bad provider state! Should not be here on a non-lazy HAL!");
+ return nullptr;
+ }
+
+ auto interface = mActiveInterface.promote();
+ if (interface == nullptr) {
+ // Try to get service without starting
+ interface = mManager->mHidlServiceProxy->tryGetService(mProviderName);
+ if (interface == nullptr) {
+ ALOGV("Camera provider actually needs restart, calling getService(%s)",
+ mProviderName.c_str());
+ interface = mManager->mHidlServiceProxy->getService(mProviderName);
+
+ // Set all devices as ENUMERATING, provider should update status
+ // to PRESENT after initializing.
+ // This avoids failing getCameraDeviceInterface_V3_x before devices
+ // are ready.
+ for (auto& device : mDevices) {
+ device->mIsDeviceAvailable = false;
+ }
+
+ interface->setCallback(this);
+ hardware::Return<bool>
+ linked = interface->linkToDeath(this, /*cookie*/ mId);
+ if (!linked.isOk()) {
+ ALOGE(
+ "%s: Transaction error in linking to camera provider '%s' death: %s",
+ __FUNCTION__,
+ mProviderName.c_str(),
+ linked.description().c_str());
+ mManager->removeProvider(mProviderName);
+ return nullptr;
+ } else if (!linked) {
+ ALOGW("%s: Unable to link to provider '%s' death notifications",
+ __FUNCTION__, mProviderName.c_str());
+ }
+ // Send current device state
+ if (mMinorVersion >= 5) {
+ auto castResult =
+ provider::V2_5::ICameraProvider::castFrom(interface);
+ if (castResult.isOk()) {
+ sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
+ if (interface_2_5 != nullptr) {
+ ALOGV("%s: Initial device state for %s: 0x %" PRIx64,
+ __FUNCTION__, mProviderName.c_str(), mDeviceState);
+ interface_2_5->notifyDeviceStateChange(mDeviceState);
+ }
+ }
+ }
+ }
+ mActiveInterface = interface;
+ } else {
+ ALOGV("Camera provider (%s) already in use. Re-using instance.",
+ mProviderName.c_str());
+ }
+
+ return interface;
+}
+
+hardware::Return<void> HidlProviderInfo::cameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ std::lock_guard<std::mutex> lock(mInitLock);
+ CameraDeviceStatus internalNewStatus = hidlToInternalCameraDeviceStatus(newStatus);
+ if (!mInitialized) {
+ mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
+ cameraDeviceName.c_str(), std::string().c_str(),
+ internalNewStatus);
+ return hardware::Void();
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
+ return hardware::Void();
+ }
+ listener = mManager->getStatusListener();
+ }
+
+ // Call without lock held to allow reentrancy into provider manager
+ if (listener != nullptr) {
+ listener->onDeviceStatusChanged(String8(id.c_str()), internalNewStatus);
+ }
+
+ return hardware::Void();
+}
+
+status_t HidlProviderInfo::addDevice(const std::string& name,
+ common::V1_0::CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
+
+ ALOGI("Enumerating new camera device: %s", name.c_str());
+
+ uint16_t major, minor;
+ std::string type, id;
+
+ status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+ if (res != OK) {
+ return res;
+ }
+ if (type != mType) {
+ ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
+ type.c_str(), mType.c_str());
+ return BAD_VALUE;
+ }
+ if (mManager->isValidDeviceLocked(id, major)) {
+ ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
+ name.c_str(), id.c_str(), major);
+ return BAD_VALUE;
+ }
+
+ std::unique_ptr<DeviceInfo> deviceInfo;
+ switch (major) {
+ case 1:
+ ALOGE("%s: Device %s: Unsupported HIDL device HAL major version %d:", __FUNCTION__,
+ name.c_str(), major);
+ return BAD_VALUE;
+ case 3:
+ deviceInfo = initializeDeviceInfo(name, mProviderTagid, id, minor);
+ break;
+ default:
+ ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
+ name.c_str(), major);
+ return BAD_VALUE;
+ }
+ if (deviceInfo == nullptr) return BAD_VALUE;
+ deviceInfo->notifyDeviceStateChange(mDeviceState);
+ deviceInfo->mStatus = hidlToInternalCameraDeviceStatus(initialStatus);
+ bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
+
+ mDevices.push_back(std::move(deviceInfo));
+
+ mUniqueCameraIds.insert(id);
+ if (isAPI1Compatible) {
+ // addDevice can be called more than once for the same camera id if HAL
+ // supports openLegacy.
+ if (std::find(mUniqueAPI1CompatibleCameraIds.begin(), mUniqueAPI1CompatibleCameraIds.end(),
+ id) == mUniqueAPI1CompatibleCameraIds.end()) {
+ mUniqueAPI1CompatibleCameraIds.push_back(id);
+ }
+ }
+
+ if (parsedId != nullptr) {
+ *parsedId = id;
+ }
+ return OK;
+}
+
+status_t HidlProviderInfo::cameraDeviceStatusChangeLocked(
+ std::string* id, const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ bool known = false;
+ std::string cameraId;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ Mutex::Autolock l(deviceInfo->mDeviceAvailableLock);
+ ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
+ deviceStatusToString(newStatus),
+ deviceStatusToString(mapToHidlCameraDeviceStatus(deviceInfo->mStatus)));
+ deviceInfo->mStatus = hidlToInternalCameraDeviceStatus(newStatus);
+ // TODO: Handle device removal (NOT_PRESENT)
+ cameraId = deviceInfo->mId;
+ known = true;
+ deviceInfo->mIsDeviceAvailable =
+ (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT);
+ deviceInfo->mDeviceAvailableSignal.signal();
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ if (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT) {
+ ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ addDevice(cameraDeviceName, newStatus, &cameraId);
+ } else if (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT) {
+ removeDevice(cameraId);
+ } else if (isExternalLazyHAL()) {
+ // Do not notify CameraService for PRESENT->PRESENT (lazy HAL restart)
+ // because NOT_AVAILABLE is set on CameraService::connect and a PRESENT
+ // notif. would overwrite it
+ return BAD_VALUE;
+ }
+ if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+ ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+ __FUNCTION__, mProviderName.c_str());
+ }
+ *id = cameraId;
+ return OK;
+}
+
+hardware::Return<void> HidlProviderInfo::physicalCameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ std::string physicalId;
+ std::lock_guard<std::mutex> lock(mInitLock);
+ CameraDeviceStatus newInternalStatus = hidlToInternalCameraDeviceStatus(newStatus);
+ if (!mInitialized) {
+ mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
+ physicalCameraDeviceName, newInternalStatus);
+ return hardware::Void();
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
+ physicalCameraDeviceName, newStatus)) {
+ return hardware::Void();
+ }
+
+ listener = mManager->getStatusListener();
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ if (listener != nullptr) {
+ listener->onDeviceStatusChanged(String8(id.c_str()),
+ String8(physicalId.c_str()), newInternalStatus);
+ }
+ return hardware::Void();
+}
+
+status_t HidlProviderInfo::physicalCameraDeviceStatusChangeLocked(
+ std::string* id, std::string* physicalId,
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ bool known = false;
+ std::string cameraId;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ cameraId = deviceInfo->mId;
+ if (!deviceInfo->mIsLogicalCamera) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+ physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ ALOGI("Camera device %s physical device %s status is now %s",
+ cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+ deviceStatusToString(newStatus));
+ known = true;
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(),
+ physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+
+ *id = cameraId;
+ *physicalId = physicalCameraDeviceName.c_str();
+ return OK;
+}
+
+hardware::Return<void> HidlProviderInfo::torchModeStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::TorchModeStatus newStatus) {
+ sp<StatusListener> listener;
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ std::string id;
+ bool known = false;
+ {
+ // Hold mLock for accessing mDevices
+ std::lock_guard<std::mutex> lock(mLock);
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
+ torchStatusToString(newStatus));
+ id = deviceInfo->mId;
+ known = true;
+ systemCameraKind = deviceInfo->mSystemCameraKind;
+ if (hardware::camera::common::V1_0::TorchModeStatus::AVAILABLE_ON != newStatus) {
+ mManager->removeRef(CameraProviderManager::DeviceMode::TORCH, id);
+ }
+ break;
+ }
+ }
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
+ return hardware::Void();
+ }
+ // no lock needed since listener is set up only once during
+ // CameraProviderManager initialization and then never changed till it is
+ // destructed.
+ listener = mManager->getStatusListener();
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ // The problem with holding mLock here is that we
+ // might be limiting re-entrancy : CameraService::onTorchStatusChanged calls
+ // back into CameraProviderManager which might try to hold mLock again (eg:
+ // findDeviceInfo, which should be holding mLock while iterating through
+ // each provider's devices).
+ if (listener != nullptr) {
+ listener->onTorchStatusChanged(String8(id.c_str()),
+ hidlToInternalTorchModeStatus(newStatus), systemCameraKind);
+ }
+ return hardware::Void();
+}
+
+void HidlProviderInfo::serviceDied(uint64_t cookie,
+ const wp<hidl::base::V1_0::IBase>& who) {
+ (void) who;
+ ALOGI("Camera provider '%s' has died; removing it", mProviderInstance.c_str());
+ if (cookie != mId) {
+ ALOGW("%s: Unexpected serviceDied cookie %" PRIu64 ", expected %" PRIu32,
+ __FUNCTION__, cookie, mId);
+ }
+ mManager->removeProvider(mProviderInstance);
+}
+
+std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
+ HidlProviderInfo::initializeDeviceInfo(
+ const std::string &name, const metadata_vendor_id_t tagId,
+ const std::string &id, uint16_t minorVersion) {
+ Status status;
+
+ auto cameraInterface = startDeviceInterface(name);
+ if (cameraInterface == nullptr) return nullptr;
+
+ common::V1_0::CameraResourceCost resourceCost;
+ cameraInterface->getResourceCost([&status, &resourceCost](
+ Status s, common::V1_0::CameraResourceCost cost) {
+ status = s;
+ resourceCost = cost;
+ });
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+
+ for (auto& conflictName : resourceCost.conflictingDevices) {
+ uint16_t major, minor;
+ std::string type, id;
+ status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
+ if (res != OK) {
+ ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
+ return nullptr;
+ }
+ conflictName = id;
+ }
+
+ return std::unique_ptr<DeviceInfo3>(
+ new HidlDeviceInfo3(name, tagId, id, minorVersion, hidlToInternalResourceCost(resourceCost),
+ this, mProviderPublicCameraIds, cameraInterface));
+}
+
+status_t HidlProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+ if (mMinorVersion < 6) {
+ // Unsupported operation, nothing to do here
+ return OK;
+ }
+ // Check if the provider is currently active - not going to start it up for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface == nullptr) {
+ ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+ mProviderName.c_str());
+ return INVALID_OPERATION;
+ }
+ auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+
+ if (castResult.isOk()) {
+ sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
+ if (interface2_6 != nullptr) {
+ return getConcurrentCameraIdsInternalLocked(interface2_6);
+ } else {
+ // This should not happen since mMinorVersion >= 6
+ ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
+ return UNKNOWN_ERROR;
+ }
+ }
+ return OK;
+}
+
+status_t HidlProviderInfo::getConcurrentCameraIdsInternalLocked(
+ sp<provider::V2_6::ICameraProvider> &interface2_6) {
+ if (interface2_6 == nullptr) {
+ ALOGE("%s: null interface provided", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ Status status = Status::OK;
+ hardware::Return<void> ret =
+ interface2_6->getConcurrentStreamingCameraIds([&status, this](
+ Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+ const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+ cameraDeviceIdCombinations) {
+ status = concurrentIdStatus;
+ if (status == Status::OK) {
+ mConcurrentCameraIdCombinations.clear();
+ for (auto& combination : cameraDeviceIdCombinations) {
+ std::unordered_set<std::string> deviceIds;
+ for (auto &cameraDeviceId : combination) {
+ deviceIds.insert(cameraDeviceId.c_str());
+ }
+ mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+ }
+ } });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+ return OK;
+}
+
+HidlProviderInfo::HidlDeviceInfo3::HidlDeviceInfo3(
+ const std::string& name,
+ const metadata_vendor_id_t tagId,
+ const std::string &id, uint16_t minorVersion,
+ const CameraResourceCost& resourceCost,
+ sp<CameraProviderManager::ProviderInfo> parentProvider,
+ const std::vector<std::string>& publicCameraIds,
+ sp<hardware::camera::device::V3_2::ICameraDevice> interface) :
+ DeviceInfo3(name, tagId, id, minorVersion, resourceCost, parentProvider, publicCameraIds) {
+
+ // Get camera characteristics and initialize flash unit availability
+ Status status;
+ hardware::Return<void> ret;
+ ret = interface->getCameraCharacteristics([&status, this](Status s,
+ device::V3_2::CameraMetadata metadata) {
+ status = s;
+ if (s == Status::OK) {
+ camera_metadata_t *buffer =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ size_t expectedSize = metadata.size();
+ int res = validate_camera_metadata_structure(buffer, &expectedSize);
+ if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ set_camera_metadata_vendor_id(buffer, mProviderTagid);
+ mCameraCharacteristics = buffer;
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = Status::INTERNAL_ERROR;
+ }
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error getting camera characteristics for device %s"
+ " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
+ ret.description().c_str());
+ return;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
+ __FUNCTION__, id.c_str(), statusToString(status), status);
+ return;
+ }
+
+ if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
+ const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
+ if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
+ for (size_t i = 0; i < stateMap.count; i += 2) {
+ mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
+ }
+ } else {
+ ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
+ stateMap.count);
+ }
+ }
+
+ mSystemCameraKind = getSystemCameraKind();
+
+ status_t res = fixupMonochromeTags();
+ if (OK != res) {
+ ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return;
+ }
+ auto stat = addDynamicDepthTags();
+ if (OK != stat) {
+ ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat),
+ stat);
+ }
+ res = deriveHeicTags();
+ if (OK != res) {
+ ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+
+ if (SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
+ status_t status = addDynamicDepthTags(/*maxResolution*/true);
+ if (OK != status) {
+ ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
+ __FUNCTION__, strerror(-status), status);
+ }
+
+ status = deriveHeicTags(/*maxResolution*/true);
+ if (OK != status) {
+ ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for"
+ "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status);
+ }
+ }
+
+ res = addRotateCropTags();
+ if (OK != res) {
+ ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ }
+ res = addPreCorrectionActiveArraySize();
+ if (OK != res) {
+ ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ }
+ res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+ &mCameraCharacteristics, &mSupportNativeZoomRatio);
+ if (OK != res) {
+ ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+
+ camera_metadata_entry flashAvailable =
+ mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
+ if (flashAvailable.count == 1 &&
+ flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
+ mHasFlashUnit = true;
+ } else {
+ mHasFlashUnit = false;
+ }
+
+ camera_metadata_entry entry =
+ mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
+ if (entry.count == 1) {
+ mTorchDefaultStrengthLevel = entry.data.i32[0];
+ } else {
+ mTorchDefaultStrengthLevel = 0;
+ }
+ entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
+ if (entry.count == 1) {
+ mTorchMaximumStrengthLevel = entry.data.i32[0];
+ } else {
+ mTorchMaximumStrengthLevel = 0;
+ }
+
+ mTorchStrengthLevel = 0;
+
+ queryPhysicalCameraIds();
+
+ // Get physical camera characteristics if applicable
+ auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
+ if (!castResult.isOk()) {
+ ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
+ return;
+ }
+ sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
+ if (interface_3_5 == nullptr) {
+ ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
+ return;
+ }
+
+ if (mIsLogicalCamera) {
+ for (auto& id : mPhysicalIds) {
+ if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
+ mPublicCameraIds.end()) {
+ continue;
+ }
+
+ hardware::hidl_string hidlId(id);
+ ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId,
+ [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) {
+ status = s;
+ if (s == Status::OK) {
+ camera_metadata_t *buffer =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ size_t expectedSize = metadata.size();
+ int res = validate_camera_metadata_structure(buffer, &expectedSize);
+ if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ set_camera_metadata_vendor_id(buffer, mProviderTagid);
+ mPhysicalCameraCharacteristics[id] = buffer;
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = Status::INTERNAL_ERROR;
+ }
+ }
+ });
+
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
+ __FUNCTION__, id.c_str(), id.c_str(), ret.description().c_str());
+ return;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
+ __FUNCTION__, id.c_str(), mId.c_str(),
+ statusToString(status), status);
+ return;
+ }
+
+ res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+ &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
+ if (OK != res) {
+ ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ }
+ }
+
+ if (!kEnableLazyHal) {
+ // Save HAL reference indefinitely
+ mSavedInterface = interface;
+ }
+
+
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::setTorchMode(bool enabled) {
+ using hardware::camera::common::V1_0::TorchMode;
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
+ Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
+ return mapToStatusT(s);
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::turnOnTorchWithStrengthLevel(
+ int32_t torchStrength) {
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ if (castResult_3_8.isOk()) {
+ interface_3_8 = castResult_3_8;
+ }
+
+ if (interface_3_8 == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ Status s = interface_3_8->turnOnTorchWithStrengthLevel(torchStrength);
+ if (s == Status::OK) {
+ mTorchStrengthLevel = torchStrength;
+ }
+ return mapToStatusT(s);
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::getTorchStrengthLevel(int32_t *torchStrength) {
+ if (torchStrength == nullptr) {
+ return BAD_VALUE;
+ }
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
+ if (castResult_3_8.isOk()) {
+ interface_3_8 = castResult_3_8;
+ }
+
+ if (interface_3_8 == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ Status callStatus;
+ status_t res;
+ hardware::Return<void> ret = interface_3_8->getTorchStrengthLevel([&callStatus, &torchStrength]
+ (Status status, const int32_t& torchStrengthLevel) {
+ callStatus = status;
+ if (status == Status::OK) {
+ *torchStrength = torchStrengthLevel;
+ } });
+
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Get torch strength level failed: %d", __FUNCTION__, callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+
+ return res;
+}
+
+sp<hardware::camera::device::V3_2::ICameraDevice>
+HidlProviderInfo::HidlDeviceInfo3::startDeviceInterface() {
+ Mutex::Autolock l(mDeviceAvailableLock);
+ sp<hardware::camera::device::V3_2::ICameraDevice> device;
+ ATRACE_CALL();
+ if (mSavedInterface == nullptr) {
+ sp<HidlProviderInfo> parentProvider =
+ static_cast<HidlProviderInfo *>(mParentProvider.promote().get());
+ if (parentProvider != nullptr) {
+ // Wait for lazy HALs to confirm device availability
+ if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
+ ALOGV("%s: Wait for external device to become available %s",
+ __FUNCTION__,
+ mId.c_str());
+
+ auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
+ kDeviceAvailableTimeout);
+ if (res != OK) {
+ ALOGE("%s: Failed waiting for device to become available",
+ __FUNCTION__);
+ return nullptr;
+ }
+ }
+
+ device = parentProvider->startDeviceInterface(mName);
+ }
+ } else {
+ device = (hardware::camera::device::V3_2::ICameraDevice *) mSavedInterface.get();
+ }
+ return device;
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::dumpState(int fd) {
+ native_handle_t* handle = native_handle_create(1,0);
+ handle->data[0] = fd;
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface =
+ startDeviceInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ auto ret = interface->dumpState(handle);
+ native_handle_delete(handle);
+ if (!ret.isOk()) {
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::isSessionConfigurationSupported(
+ const SessionConfiguration &configuration, bool overrideForPerfClass, bool *status) {
+
+ hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
+ bool earlyExit = false;
+ camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
+ CameraMetadata physicalChars;
+ getPhysicalCameraCharacteristics(id.c_str(), &physicalChars);
+ return physicalChars;
+ };
+ auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
+ String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds,
+ streamConfiguration, overrideForPerfClass, &earlyExit);
+
+ if (!bRes.isOk()) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (earlyExit) {
+ *status = false;
+ return OK;
+ }
+
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface =
+ startDeviceInterface();
+
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+
+ auto castResult_3_5 = device::V3_5::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult_3_5;
+ auto castResult_3_7 = device::V3_7::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_7::ICameraDevice> interface_3_7 = castResult_3_7;
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = castResult_3_8;
+
+ status_t res;
+ Status callStatus;
+ ::android::hardware::Return<void> ret;
+ auto halCb =
+ [&callStatus, &status] (Status s, bool combStatus) {
+ callStatus = s;
+ *status = combStatus;
+ };
+ if (interface_3_8 != nullptr) {
+ ret = interface_3_8->isStreamCombinationSupported_3_8(streamConfiguration, halCb);
+ } else if (interface_3_7 != nullptr) {
+ hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ configuration_3_7, streamConfiguration);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+ ret = interface_3_7->isStreamCombinationSupported_3_7(configuration_3_7, halCb);
+ } else if (interface_3_5 != nullptr) {
+ hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ configuration_3_7, streamConfiguration);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+ hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
+ success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ configuration_3_4, configuration_3_7);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+ ret = interface_3_5->isStreamCombinationSupported(configuration_3_4, halCb);
+ } else {
+ return INVALID_OPERATION;
+ }
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+
+ return res;
+}
+
+status_t HidlProviderInfo::convertToHALStreamCombinationAndCameraIdsLocked(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion,
+ hardware::hidl_vec<CameraIdAndStreamCombination> *halCameraIdsAndStreamCombinations,
+ bool *earlyExit) {
+ binder::Status bStatus = binder::Status::ok();
+ std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
+ bool shouldExit = false;
+ status_t res = OK;
+ for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+ const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
+ hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
+ CameraMetadata deviceInfo;
+ bool overrideForPerfClass =
+ SessionConfigurationUtils::targetPerfClassPrimaryCamera(
+ perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
+ res = mManager->getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo);
+ if (res != OK) {
+ return res;
+ }
+ camera3::metadataGetter getMetadata =
+ [this](const String8 &id, bool overrideForPerfClass) {
+ CameraMetadata physicalDeviceInfo;
+ mManager->getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
+ &physicalDeviceInfo);
+ return physicalDeviceInfo;
+ };
+ std::vector<std::string> physicalCameraIds;
+ mManager->isLogicalCameraLocked(cameraId, &physicalCameraIds);
+ bStatus =
+ SessionConfigurationUtils::convertToHALStreamCombination(
+ cameraIdAndSessionConfig.mSessionConfiguration,
+ String8(cameraId.c_str()), deviceInfo, getMetadata,
+ physicalCameraIds, streamConfiguration,
+ overrideForPerfClass, &shouldExit);
+ if (!bStatus.isOk()) {
+ ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (shouldExit) {
+ *earlyExit = true;
+ return OK;
+ }
+ CameraIdAndStreamCombination halCameraIdAndStream;
+ halCameraIdAndStream.cameraId = cameraId;
+ SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ halCameraIdAndStream.streamConfiguration, streamConfiguration);
+ halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
+ }
+ *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
+ return OK;
+}
+
+status_t HidlProviderInfo::isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) {
+
+ hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
+ bool knowUnsupported = false;
+ status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
+ cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
+ targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
+ if (res != OK) {
+ ALOGE("%s unable to convert session configurations provided to HAL stream"
+ "combinations", __FUNCTION__);
+ return res;
+ }
+ if (knowUnsupported) {
+ // We got to know the streams aren't valid before doing the HAL
+ // call itself.
+ *isSupported = false;
+ return OK;
+ }
+
+ if (mMinorVersion >= 6) {
+ // Check if the provider is currently active - not going to start it for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface == nullptr) {
+ // TODO: This might be some other problem
+ return INVALID_OPERATION;
+ }
+ auto castResult2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+ auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
+ Status callStatus;
+ auto cb =
+ [&isSupported, &callStatus](Status s, bool supported) {
+ callStatus = s;
+ *isSupported = supported; };
+
+ ::android::hardware::Return<void> ret;
+ sp<provider::V2_7::ICameraProvider> interface_2_7;
+ sp<provider::V2_6::ICameraProvider> interface_2_6;
+ if (mMinorVersion >= 7 && castResult2_7.isOk()) {
+ interface_2_7 = castResult2_7;
+ if (interface_2_7 != nullptr) {
+ ret = interface_2_7->isConcurrentStreamCombinationSupported_2_7(
+ halCameraIdsAndStreamCombinations, cb);
+ }
+ } else if (mMinorVersion == 6 && castResult2_6.isOk()) {
+ interface_2_6 = castResult2_6;
+ if (interface_2_6 != nullptr) {
+ hardware::hidl_vec<provider::V2_6::CameraIdAndStreamCombination>
+ halCameraIdsAndStreamCombinations_2_6;
+ size_t numStreams = halCameraIdsAndStreamCombinations.size();
+ halCameraIdsAndStreamCombinations_2_6.resize(numStreams);
+ for (size_t i = 0; i < numStreams; i++) {
+ using namespace camera3;
+ auto const& combination = halCameraIdsAndStreamCombinations[i];
+ halCameraIdsAndStreamCombinations_2_6[i].cameraId = combination.cameraId;
+ bool success =
+ SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
+ combination.streamConfiguration);
+ if (!success) {
+ *isSupported = false;
+ return OK;
+ }
+ }
+ ret = interface_2_6->isConcurrentStreamCombinationSupported(
+ halCameraIdsAndStreamCombinations_2_6, cb);
+ }
+ }
+
+ if (interface_2_7 != nullptr || interface_2_6 != nullptr) {
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
+ callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+ return res;
+ }
+ }
+ // unsupported operation
+ return INVALID_OPERATION;
+}
+
+status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
+ const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
+ sp<VendorTagDescriptor>& descriptor) {
+
+ int 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);
+ return BAD_VALUE;
+ }
+
+ Vector<uint32_t> tagArray;
+ LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+ "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+
+ sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+ desc->mTagCount = tagCount;
+
+ SortedVector<String8> sections;
+ KeyedVector<uint32_t, String8> tagToSectionMap;
+
+ int idx = 0;
+ for (size_t s = 0; s < vts.size(); s++) {
+ const common::V1_0::VendorTagSection& section = vts[s];
+ const char *sectionName = section.sectionName.c_str();
+ if (sectionName == NULL) {
+ ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
+ return BAD_VALUE;
+ }
+ String8 sectionString(sectionName);
+ sections.add(sectionString);
+
+ for (size_t j = 0; j < section.tags.size(); j++) {
+ uint32_t tag = section.tags[j].tagId;
+ if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+ ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+ return BAD_VALUE;
+ }
+
+ tagArray.editItemAt(idx++) = section.tags[j].tagId;
+
+ const char *tagName = section.tags[j].tagName.c_str();
+ if (tagName == NULL) {
+ 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);
+
+ int tagType = (int) section.tags[j].tagType;
+ if (tagType < 0 || tagType >= NUM_TYPES) {
+ ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+ return BAD_VALUE;
+ }
+ desc->mTagToTypeMap.add(tag, tagType);
+ }
+ }
+
+ desc->mSections = sections;
+
+ for (size_t i = 0; i < tagArray.size(); ++i) {
+ uint32_t tag = tagArray[i];
+ String8 sectionString = tagToSectionMap.valueFor(tag);
+
+ // Set up tag to section index map
+ ssize_t index = sections.indexOf(sectionString);
+ LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+ desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+ // Set up reverse mapping
+ ssize_t reverseIndex = -1;
+ if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+ KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+ reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+ }
+ desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+ }
+
+ descriptor = std::move(desc);
+ return OK;
+}
+
+} //namespace android
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
new file mode 100644
index 0000000..0ba2aff
--- /dev/null
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
@@ -0,0 +1,167 @@
+/*
+ * 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 ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_HIDLPROVIDERINFOH
+#define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_HIDLPROVIDERINFOH
+
+#include "common/CameraProviderManager.h"
+
+namespace android {
+
+/**
+ * The vendor tag descriptor class that takes HIDL vendor tag information as
+ * input. Not part of VendorTagDescriptor class because that class is used
+ * in AIDL generated sources which don't have access to HIDL headers.
+ */
+class HidlVendorTagDescriptor : public VendorTagDescriptor {
+public:
+ /**
+ * Create a VendorTagDescriptor object from the HIDL VendorTagSection
+ * vector.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ static status_t createDescriptorFromHidl(
+ const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
+ /*out*/
+ sp<VendorTagDescriptor>& descriptor);
+};
+
+struct HidlProviderInfo : public CameraProviderManager::ProviderInfo,
+ virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
+ virtual public hardware::hidl_death_recipient {
+ // Current overall Android device physical status
+ hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> mDeviceState;
+
+ // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
+ wp<hardware::camera::provider::V2_4::ICameraProvider> mActiveInterface;
+
+ sp<hardware::camera::provider::V2_4::ICameraProvider> mSavedInterface;
+ HidlProviderInfo(
+ const std::string &providerName,
+ const std::string &providerInstance,
+ CameraProviderManager *manager) :
+ CameraProviderManager::ProviderInfo(providerName, providerInstance, manager) {}
+
+ virtual ~HidlProviderInfo() {}
+
+ static status_t mapToStatusT(const hardware::camera::common::V1_0::Status &status);
+
+ status_t initializeHidlProvider(
+ sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
+ int64_t currentDeviceState);
+
+ IPCTransport getIPCTransport() override {return IPCTransport::HIDL;}
+
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> startProviderInterface();
+
+ virtual bool successfullyStartedProviderInterface() override;
+
+ virtual status_t setUpVendorTags() override;
+ virtual status_t notifyDeviceStateChange(int64_t) override;
+
+ /**
+ * Query the camera provider for concurrent stream configuration support
+ */
+ virtual status_t isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) override;
+
+ // Helper for initializeDeviceInfo to use the right CameraProvider get method.
+ sp<hardware::camera::device::V3_2::ICameraDevice>
+ startDeviceInterface(const std::string &deviceName);
+
+ // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
+ hardware::Return<void> cameraDeviceStatusChange(
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus ) override;
+ hardware::Return<void> torchModeStatusChange(
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::TorchModeStatus ) override;
+ hardware::Return<void> physicalCameraDeviceStatusChange(
+ const hardware::hidl_string& ,
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus ) override;
+
+ // hidl_death_recipient interface - this locks the parent mInterfaceMutex
+ virtual void serviceDied(uint64_t , const wp<hidl::base::V1_0::IBase>& ) override;
+
+ struct HidlDeviceInfo3 : public CameraProviderManager::ProviderInfo::DeviceInfo3 {
+
+ const hardware::hidl_version mVersion = hardware::hidl_version{3, 2};
+ sp<IBase> mSavedInterface = nullptr;
+
+ HidlDeviceInfo3(const std::string& , const metadata_vendor_id_t ,
+ const std::string &, uint16_t ,
+ const CameraResourceCost& ,
+ sp<ProviderInfo> ,
+ const std::vector<std::string>& ,
+ sp<hardware::camera::device::V3_2::ICameraDevice>);
+
+ ~HidlDeviceInfo3() {}
+
+ virtual status_t setTorchMode(bool enabled) override;
+ virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) override;
+ virtual status_t getTorchStrengthLevel(int32_t *torchStrength) override;
+
+ virtual status_t dumpState(int fd) override;
+
+ virtual status_t isSessionConfigurationSupported(
+ const SessionConfiguration &/*configuration*/,
+ bool overrideForPerfClass,
+ bool *status/*status*/);
+ sp<hardware::camera::device::V3_2::ICameraDevice> startDeviceInterface();
+ };
+
+ private:
+
+ status_t cameraDeviceStatusChangeLocked(
+ std::string* , const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus );
+
+ status_t physicalCameraDeviceStatusChangeLocked(
+ std::string* , std::string* ,
+ const hardware::hidl_string& ,
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus );
+
+ status_t addDevice(const std::string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus ,
+ /*out*/ std::string *);
+
+ std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &,
+ const metadata_vendor_id_t , const std::string &,
+ uint16_t );
+ status_t reCacheConcurrentStreamingCameraIdsLocked();
+
+ //Expects to have mLock locked
+ status_t getConcurrentCameraIdsInternalLocked(
+ sp<hardware::camera::provider::V2_6::ICameraProvider> &);
+
+ //expects to have mManager->mInterfaceMutex locked
+ status_t convertToHALStreamCombinationAndCameraIdsLocked(
+ const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>&
+ cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion,
+ hardware::hidl_vec<hardware::camera::provider::V2_7::CameraIdAndStreamCombination>*
+ halCameraIdsAndStreamCombinations,
+ bool *earlyExit);
+}; // HidlProviderInfo
+
+} // namespace android
+#endif
diff --git a/services/camera/libcameraservice/device3/BufferUtils.cpp b/services/camera/libcameraservice/device3/BufferUtils.cpp
index f3adf20..c0d47d5 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.cpp
+++ b/services/camera/libcameraservice/device3/BufferUtils.cpp
@@ -28,16 +28,6 @@
namespace android {
namespace camera3 {
-camera_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
- using hardware::camera::device::V3_2::BufferStatus;
-
- switch (status) {
- case BufferStatus::OK: return CAMERA_BUFFER_STATUS_OK;
- case BufferStatus::ERROR: return CAMERA_BUFFER_STATUS_ERROR;
- }
- return CAMERA_BUFFER_STATUS_ERROR;
-}
-
void BufferRecords::takeInflightBufferMap(BufferRecords& other) {
std::lock_guard<std::mutex> oLock(other.mInflightLock);
std::lock_guard<std::mutex> lock(mInflightLock);
diff --git a/services/camera/libcameraservice/device3/BufferUtils.h b/services/camera/libcameraservice/device3/BufferUtils.h
index 03112ec..96fc111 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.h
+++ b/services/camera/libcameraservice/device3/BufferUtils.h
@@ -154,9 +154,6 @@
}; // class BufferRecords
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
-
- camera_buffer_status_t mapHidlBufferStatus(
- hardware::camera::device::V3_2::BufferStatus status);
} // namespace camera3
} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4c1e7f0..992027a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -65,6 +65,8 @@
#include "utils/TraceHFR.h"
#include "utils/CameraServiceProxyWrapper.h"
+#include "../common/hidl/HidlProviderInfo.h"
+
#include <algorithm>
#include <tuple>
@@ -112,164 +114,6 @@
return mId;
}
-status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
- ATRACE_CALL();
- Mutex::Autolock il(mInterfaceLock);
- Mutex::Autolock l(mLock);
-
- ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
- if (mStatus != STATUS_UNINITIALIZED) {
- CLOGE("Already initialized!");
- return INVALID_OPERATION;
- }
- if (manager == nullptr) return INVALID_OPERATION;
-
- sp<ICameraDeviceSession> session;
- ATRACE_BEGIN("CameraHal::openSession");
- status_t res = manager->openSession(mId.string(), this,
- /*out*/ &session);
- ATRACE_END();
- if (res != OK) {
- SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
- return res;
- }
-
- res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo);
- if (res != OK) {
- SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
- session->close();
- return res;
- }
- mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
-
- std::vector<std::string> physicalCameraIds;
- bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
- if (isLogical) {
- for (auto& physicalId : physicalCameraIds) {
- // Do not override characteristics for physical cameras
- res = manager->getCameraCharacteristics(
- physicalId, /*overrideForPerfClass*/false, &mPhysicalDeviceInfoMap[physicalId]);
- if (res != OK) {
- SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
- physicalId.c_str(), strerror(-res), res);
- session->close();
- return res;
- }
-
- bool usePrecorrectArray =
- DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
- if (usePrecorrectArray) {
- res = mDistortionMappers[physicalId].setupStaticInfo(
- mPhysicalDeviceInfoMap[physicalId]);
- if (res != OK) {
- SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
- "correction", physicalId.c_str());
- session->close();
- return res;
- }
- }
-
- mZoomRatioMappers[physicalId] = ZoomRatioMapper(
- &mPhysicalDeviceInfoMap[physicalId],
- mSupportNativeZoomRatio, usePrecorrectArray);
-
- if (SessionConfigurationUtils::isUltraHighResolutionSensor(
- mPhysicalDeviceInfoMap[physicalId])) {
- mUHRCropAndMeteringRegionMappers[physicalId] =
- UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
- usePrecorrectArray);
- }
- }
- }
-
- std::shared_ptr<RequestMetadataQueue> queue;
- auto requestQueueRet = session->getCaptureRequestMetadataQueue(
- [&queue](const auto& descriptor) {
- queue = std::make_shared<RequestMetadataQueue>(descriptor);
- if (!queue->isValid() || queue->availableToWrite() <= 0) {
- ALOGE("HAL returns empty request metadata fmq, not use it");
- queue = nullptr;
- // don't use the queue onwards.
- }
- });
- if (!requestQueueRet.isOk()) {
- ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
- requestQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
-
- std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
- auto resultQueueRet = session->getCaptureResultMetadataQueue(
- [&resQueue](const auto& descriptor) {
- resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
- ALOGE("HAL returns empty result metadata fmq, not use it");
- resQueue = nullptr;
- // Don't use the resQueue onwards.
- }
- });
- if (!resultQueueRet.isOk()) {
- ALOGE("Transaction error when getting result metadata queue from camera session: %s",
- resultQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
- IF_ALOGV() {
- session->interfaceChain([](
- ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
- ALOGV("Session interface chain:");
- for (const auto& iface : interfaceChain) {
- ALOGV(" %s", iface.c_str());
- }
- });
- }
-
- camera_metadata_entry bufMgrMode =
- mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
- if (bufMgrMode.count > 0) {
- mUseHalBufManager = (bufMgrMode.data.u8[0] ==
- ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
- }
-
- camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
- for (size_t i = 0; i < capabilities.count; i++) {
- uint8_t capability = capabilities.data.u8[i];
- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
- mSupportOfflineProcessing = true;
- }
- }
-
- mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
- std::string providerType;
- mVendorTagId = manager->getProviderTagIdLocked(mId.string());
- mTagMonitor.initialize(mVendorTagId);
- if (!monitorTags.isEmpty()) {
- mTagMonitor.parseTagsToMonitor(String8(monitorTags));
- }
-
- // Metadata tags needs fixup for monochrome camera device version less
- // than 3.5.
- hardware::hidl_version maxVersion{0,0};
- res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
- if (res != OK) {
- ALOGE("%s: Error in getting camera device version id: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return res;
- }
- int deviceVersion = HARDWARE_DEVICE_API_VERSION(
- maxVersion.get_major(), maxVersion.get_minor());
-
- bool isMonochrome = false;
- for (size_t i = 0; i < capabilities.count; i++) {
- uint8_t capability = capabilities.data.u8[i];
- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
- isMonochrome = true;
- }
- }
- mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
-
- return initializeCommonLocked();
-}
-
status_t Camera3Device::initializeCommonLocked() {
/** Start up status tracker thread */
@@ -323,7 +167,7 @@
}
/** Start up request queue thread */
- mRequestThread = new RequestThread(
+ mRequestThread = createNewRequestThread(
this, mStatusTracker, mInterface, sessionParamKeys,
mUseHalBufManager, mSupportCameraMute);
res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
@@ -381,7 +225,8 @@
mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
}
- mInjectionMethods = new Camera3DeviceInjectionMethods(this);
+ // Hidl/AidlCamera3DeviceInjectionMethods
+ mInjectionMethods = createCamera3DeviceInjectionMethods(this);
return OK;
}
@@ -531,83 +376,6 @@
return measured;
}
-CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap
-Camera3Device::mapToHidlDynamicProfile(int dynamicRangeProfile) {
- return static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>(
- dynamicRangeProfile);
-}
-
-hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
- int frameworkFormat) {
- return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
-}
-
-DataspaceFlags Camera3Device::mapToHidlDataspace(
- android_dataspace dataSpace) {
- return dataSpace;
-}
-
-BufferUsageFlags Camera3Device::mapToConsumerUsage(
- uint64_t usage) {
- return usage;
-}
-
-StreamRotation Camera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
- switch (rotation) {
- case CAMERA_STREAM_ROTATION_0:
- return StreamRotation::ROTATION_0;
- case CAMERA_STREAM_ROTATION_90:
- return StreamRotation::ROTATION_90;
- case CAMERA_STREAM_ROTATION_180:
- return StreamRotation::ROTATION_180;
- case CAMERA_STREAM_ROTATION_270:
- return StreamRotation::ROTATION_270;
- }
- ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
- return StreamRotation::ROTATION_0;
-}
-
-status_t Camera3Device::mapToStreamConfigurationMode(
- camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
- if (mode == nullptr) return BAD_VALUE;
- if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
- switch(operationMode) {
- case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
- *mode = StreamConfigurationMode::NORMAL_MODE;
- break;
- case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
- *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
- break;
- default:
- ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
- return BAD_VALUE;
- }
- } else {
- *mode = static_cast<StreamConfigurationMode>(operationMode);
- }
- return OK;
-}
-
-int Camera3Device::mapToFrameworkFormat(
- hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
- return static_cast<uint32_t>(pixelFormat);
-}
-
-android_dataspace Camera3Device::mapToFrameworkDataspace(
- DataspaceFlags dataSpace) {
- return static_cast<android_dataspace>(dataSpace);
-}
-
-uint64_t Camera3Device::mapConsumerToFrameworkUsage(
- BufferUsageFlags usage) {
- return usage;
-}
-
-uint64_t Camera3Device::mapProducerToFrameworkUsage(
- BufferUsageFlags usage) {
- return usage;
-}
-
ssize_t Camera3Device::getJpegBufferSize(const CameraMetadata &info, uint32_t width,
uint32_t height) const {
// Get max jpeg size (area-wise) for default sensor pixel mode
@@ -1050,186 +818,6 @@
return res;
}
-hardware::Return<void> Camera3Device::requestStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) {
- RequestBufferStates states {
- mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
- *this, *mInterface, *this};
- camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3Device::returnStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
- ReturnBufferStates states {
- mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, *mInterface};
- camera3::returnStreamBuffers(states, buffers);
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3Device::processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) {
- // Ideally we should grab mLock, but that can lead to deadlock, and
- // it's not super important to get up to date value of mStatus for this
- // warning print, hence skipping the lock here
- if (mStatus == STATUS_ERROR) {
- // Per API contract, HAL should act as closed after device error
- // But mStatus can be set to error by framework as well, so just log
- // a warning here.
- ALOGW("%s: received capture result in error state.", __FUNCTION__);
- }
-
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> l(mOutputLock);
- listener = mListener.promote();
- }
-
- if (mProcessCaptureResultLock.tryLock() != OK) {
- // This should never happen; it indicates a wrong client implementation
- // that doesn't follow the contract. But, we can be tolerant here.
- ALOGE("%s: callback overlapped! waiting 1s...",
- __FUNCTION__);
- if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
- ALOGE("%s: cannot acquire lock in 1s, dropping results",
- __FUNCTION__);
- // really don't know what to do, so bail out.
- return hardware::Void();
- }
- }
- CaptureOutputStates states {
- mId,
- mInFlightLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient
- };
-
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
- }
- mProcessCaptureResultLock.unlock();
- return hardware::Void();
-}
-
-// Only one processCaptureResult should be called at a time, so
-// the locks won't block. The locks are present here simply to enforce this.
-hardware::Return<void> Camera3Device::processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) {
- hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
-
- // Ideally we should grab mLock, but that can lead to deadlock, and
- // it's not super important to get up to date value of mStatus for this
- // warning print, hence skipping the lock here
- if (mStatus == STATUS_ERROR) {
- // Per API contract, HAL should act as closed after device error
- // But mStatus can be set to error by framework as well, so just log
- // a warning here.
- ALOGW("%s: received capture result in error state.", __FUNCTION__);
- }
-
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> l(mOutputLock);
- listener = mListener.promote();
- }
-
- if (mProcessCaptureResultLock.tryLock() != OK) {
- // This should never happen; it indicates a wrong client implementation
- // that doesn't follow the contract. But, we can be tolerant here.
- ALOGE("%s: callback overlapped! waiting 1s...",
- __FUNCTION__);
- if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
- ALOGE("%s: cannot acquire lock in 1s, dropping results",
- __FUNCTION__);
- // really don't know what to do, so bail out.
- return hardware::Void();
- }
- }
-
- CaptureOutputStates states {
- mId,
- mInFlightLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient
- };
-
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result, noPhysMetadata);
- }
- mProcessCaptureResultLock.unlock();
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3Device::notify(
- const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
- return notifyHelper<hardware::camera::device::V3_2::NotifyMsg>(msgs);
-}
-
-hardware::Return<void> Camera3Device::notify_3_8(
- const hardware::hidl_vec<hardware::camera::device::V3_8::NotifyMsg>& msgs) {
- return notifyHelper<hardware::camera::device::V3_8::NotifyMsg>(msgs);
-}
-
-template<typename NotifyMsgType>
-hardware::Return<void> Camera3Device::notifyHelper(const hardware::hidl_vec<NotifyMsgType>& msgs) {
- // Ideally we should grab mLock, but that can lead to deadlock, and
- // it's not super important to get up to date value of mStatus for this
- // warning print, hence skipping the lock here
- if (mStatus == STATUS_ERROR) {
- // Per API contract, HAL should act as closed after device error
- // But mStatus can be set to error by framework as well, so just log
- // a warning here.
- ALOGW("%s: received notify message in error state.", __FUNCTION__);
- }
-
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> l(mOutputLock);
- listener = mListener.promote();
- }
-
- CaptureOutputStates states {
- mId,
- mInFlightLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient
- };
- for (const auto& msg : msgs) {
- camera3::notify(states, msg);
- }
- return hardware::Void();
-}
-
status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber) {
@@ -3141,733 +2729,6 @@
* HalInterface inner class methods
*/
-Camera3Device::HalInterface::HalInterface(
- sp<ICameraDeviceSession> &session,
- std::shared_ptr<RequestMetadataQueue> queue,
- bool useHalBufManager, bool supportOfflineProcessing) :
- mHidlSession(session),
- mRequestMetadataQueue(queue),
- mUseHalBufManager(useHalBufManager),
- mIsReconfigurationQuerySupported(true),
- mSupportOfflineProcessing(supportOfflineProcessing) {
- // Check with hardware service manager if we can downcast these interfaces
- // Somewhat expensive, so cache the results at startup
- auto castResult_3_8 = device::V3_8::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_8.isOk()) {
- mHidlSession_3_8 = castResult_3_8;
- }
- auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_7.isOk()) {
- mHidlSession_3_7 = castResult_3_7;
- }
- auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_6.isOk()) {
- mHidlSession_3_6 = castResult_3_6;
- }
- auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_5.isOk()) {
- mHidlSession_3_5 = castResult_3_5;
- }
- auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_4.isOk()) {
- mHidlSession_3_4 = castResult_3_4;
- }
- auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_3.isOk()) {
- mHidlSession_3_3 = castResult_3_3;
- }
-}
-
-Camera3Device::HalInterface::HalInterface() :
- mUseHalBufManager(false),
- mSupportOfflineProcessing(false) {}
-
-Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
- mHidlSession(other.mHidlSession),
- mRequestMetadataQueue(other.mRequestMetadataQueue),
- mUseHalBufManager(other.mUseHalBufManager),
- mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
-
-bool Camera3Device::HalInterface::valid() {
- return (mHidlSession != nullptr);
-}
-
-void Camera3Device::HalInterface::clear() {
- mHidlSession_3_8.clear();
- mHidlSession_3_7.clear();
- mHidlSession_3_6.clear();
- mHidlSession_3_5.clear();
- mHidlSession_3_4.clear();
- mHidlSession_3_3.clear();
- mHidlSession.clear();
-}
-
-status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
- camera_request_template_t templateId,
- /*out*/ camera_metadata_t **requestTemplate) {
- ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- common::V1_0::Status status;
-
- auto requestCallback = [&status, &requestTemplate]
- (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
- status = s;
- if (status == common::V1_0::Status::OK) {
- const camera_metadata *r =
- reinterpret_cast<const camera_metadata_t*>(request.data());
- size_t expectedSize = request.size();
- int ret = validate_camera_metadata_structure(r, &expectedSize);
- if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
- *requestTemplate = clone_camera_metadata(r);
- if (*requestTemplate == nullptr) {
- ALOGE("%s: Unable to clone camera metadata received from HAL",
- __FUNCTION__);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
- }
- };
- hardware::Return<void> err;
- RequestTemplate id;
- switch (templateId) {
- case CAMERA_TEMPLATE_PREVIEW:
- id = RequestTemplate::PREVIEW;
- break;
- case CAMERA_TEMPLATE_STILL_CAPTURE:
- id = RequestTemplate::STILL_CAPTURE;
- break;
- case CAMERA_TEMPLATE_VIDEO_RECORD:
- id = RequestTemplate::VIDEO_RECORD;
- break;
- case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
- id = RequestTemplate::VIDEO_SNAPSHOT;
- break;
- case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
- id = RequestTemplate::ZERO_SHUTTER_LAG;
- break;
- case CAMERA_TEMPLATE_MANUAL:
- id = RequestTemplate::MANUAL;
- break;
- default:
- // Unknown template ID, or this HAL is too old to support it
- return BAD_VALUE;
- }
- err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
-
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- res = DEAD_OBJECT;
- } else {
- res = CameraProviderManager::mapToStatusT(status);
- }
-
- return res;
-}
-
-bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
- CameraMetadata& newSessionParams) {
- // We do reconfiguration by default;
- bool ret = true;
- if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
- android::hardware::hidl_vec<uint8_t> oldParams, newParams;
- camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
- oldSessionParams.getAndLock());
- camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
- newSessionParams.getAndLock());
- oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
- get_camera_metadata_size(oldSessioMeta));
- newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
- get_camera_metadata_size(newSessioMeta));
- hardware::camera::common::V1_0::Status callStatus;
- bool required;
- auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
- bool requiredFlag) {
- callStatus = s;
- required = requiredFlag;
- };
- auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
- oldSessionParams.unlock(oldSessioMeta);
- newSessionParams.unlock(newSessioMeta);
- if (err.isOk()) {
- switch (callStatus) {
- case hardware::camera::common::V1_0::Status::OK:
- ret = required;
- break;
- case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
- mIsReconfigurationQuerySupported = false;
- ret = true;
- break;
- default:
- ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
- ret = true;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
- ret = true;
- }
- }
-
- return ret;
-}
-
-status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
- camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
- ATRACE_NAME("CameraHal::configureStreams");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- if (config->input_is_multi_resolution && mHidlSession_3_7 == nullptr) {
- ALOGE("%s: Camera device doesn't support multi-resolution input stream", __FUNCTION__);
- return BAD_VALUE;
- }
-
- // Convert stream config to HIDL
- std::set<int> activeStreams;
- device::V3_2::StreamConfiguration requestedConfiguration3_2;
- device::V3_4::StreamConfiguration requestedConfiguration3_4;
- device::V3_7::StreamConfiguration requestedConfiguration3_7;
- device::V3_8::StreamConfiguration requestedConfiguration3_8;
- requestedConfiguration3_2.streams.resize(config->num_streams);
- requestedConfiguration3_4.streams.resize(config->num_streams);
- requestedConfiguration3_7.streams.resize(config->num_streams);
- requestedConfiguration3_8.streams.resize(config->num_streams);
- for (size_t i = 0; i < config->num_streams; i++) {
- device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
- device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
- device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
- device::V3_8::Stream &dst3_8 = requestedConfiguration3_8.streams[i];
- camera3::camera_stream_t *src = config->streams[i];
-
- Camera3Stream* cam3stream = Camera3Stream::cast(src);
- cam3stream->setBufferFreedListener(this);
- int streamId = cam3stream->getId();
- StreamType streamType;
- switch (src->stream_type) {
- case CAMERA_STREAM_OUTPUT:
- streamType = StreamType::OUTPUT;
- break;
- case CAMERA_STREAM_INPUT:
- streamType = StreamType::INPUT;
- break;
- default:
- ALOGE("%s: Stream %d: Unsupported stream type %d",
- __FUNCTION__, streamId, config->streams[i]->stream_type);
- return BAD_VALUE;
- }
- dst3_2.id = streamId;
- dst3_2.streamType = streamType;
- dst3_2.width = src->width;
- dst3_2.height = src->height;
- dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
- // For HidlSession version 3.5 or newer, the format and dataSpace sent
- // to HAL are original, not the overridden ones.
- if (mHidlSession_3_5 != nullptr) {
- dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
- cam3stream->getOriginalFormat() : src->format);
- dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
- cam3stream->getOriginalDataSpace() : src->data_space);
- } else {
- dst3_2.format = mapToPixelFormat(src->format);
- dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
- }
- dst3_4.v3_2 = dst3_2;
- dst3_4.bufferSize = bufferSizes[i];
- if (src->physical_camera_id != nullptr) {
- dst3_4.physicalCameraId = src->physical_camera_id;
- }
- dst3_7.v3_4 = dst3_4;
- dst3_7.groupId = cam3stream->getHalStreamGroupId();
- dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
- size_t j = 0;
- for (int mode : src->sensor_pixel_modes_used) {
- dst3_7.sensorPixelModesUsed[j++] =
- static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
- }
- if ((src->dynamic_range_profile !=
- ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) &&
- (mHidlSession_3_8 == nullptr)) {
- ALOGE("%s: Camera device doesn't support non-standard dynamic range profiles: %d",
- __FUNCTION__, src->dynamic_range_profile);
- return BAD_VALUE;
- }
- dst3_8.v3_7 = dst3_7;
- dst3_8.dynamicRangeProfile = mapToHidlDynamicProfile(src->dynamic_range_profile);
- activeStreams.insert(streamId);
- // Create Buffer ID map if necessary
- mBufferRecords.tryCreateBufferCache(streamId);
- }
- // remove BufferIdMap for deleted streams
- mBufferRecords.removeInactiveBufferCaches(activeStreams);
-
- StreamConfigurationMode operationMode;
- res = mapToStreamConfigurationMode(
- (camera_stream_configuration_mode_t) config->operation_mode,
- /*out*/ &operationMode);
- if (res != OK) {
- return res;
- }
- requestedConfiguration3_2.operationMode = operationMode;
- requestedConfiguration3_4.operationMode = operationMode;
- requestedConfiguration3_7.operationMode = operationMode;
- size_t sessionParamSize = get_camera_metadata_size(sessionParams);
- requestedConfiguration3_4.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
- requestedConfiguration3_7.operationMode = operationMode;
- requestedConfiguration3_7.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
- requestedConfiguration3_8.operationMode = operationMode;
- requestedConfiguration3_8.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
-
- // Invoke configureStreams
- device::V3_3::HalStreamConfiguration finalConfiguration;
- device::V3_4::HalStreamConfiguration finalConfiguration3_4;
- device::V3_6::HalStreamConfiguration finalConfiguration3_6;
- common::V1_0::Status status;
-
- auto configStream34Cb = [&status, &finalConfiguration3_4]
- (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
- finalConfiguration3_4 = halConfiguration;
- status = s;
- };
-
- auto configStream36Cb = [&status, &finalConfiguration3_6]
- (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
- finalConfiguration3_6 = halConfiguration;
- status = s;
- };
-
- auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
- (hardware::Return<void>& err) -> status_t {
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
- for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
- finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
- }
- return OK;
- };
-
- auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
- (hardware::Return<void>& err) -> status_t {
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
- for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
- finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
- }
- return OK;
- };
-
- // See which version of HAL we have
- if (mHidlSession_3_8 != nullptr) {
- ALOGV("%s: v3.8 device found", __FUNCTION__);
- requestedConfiguration3_8.streamConfigCounter = mNextStreamConfigCounter++;
- requestedConfiguration3_8.multiResolutionInputImage = config->input_is_multi_resolution;
- auto err = mHidlSession_3_8->configureStreams_3_8(requestedConfiguration3_8,
- configStream36Cb);
- res = postprocConfigStream36(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_7 != nullptr) {
- ALOGV("%s: v3.7 device found", __FUNCTION__);
- requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
- requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
- auto err = mHidlSession_3_7->configureStreams_3_7(
- requestedConfiguration3_7, configStream36Cb);
- res = postprocConfigStream36(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_6 != nullptr) {
- ALOGV("%s: v3.6 device found", __FUNCTION__);
- device::V3_5::StreamConfiguration requestedConfiguration3_5;
- requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
- requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
- auto err = mHidlSession_3_6->configureStreams_3_6(
- requestedConfiguration3_5, configStream36Cb);
- res = postprocConfigStream36(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_5 != nullptr) {
- ALOGV("%s: v3.5 device found", __FUNCTION__);
- device::V3_5::StreamConfiguration requestedConfiguration3_5;
- requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
- requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
- auto err = mHidlSession_3_5->configureStreams_3_5(
- requestedConfiguration3_5, configStream34Cb);
- res = postprocConfigStream34(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_4 != nullptr) {
- // We do; use v3.4 for the call
- ALOGV("%s: v3.4 device found", __FUNCTION__);
- auto err = mHidlSession_3_4->configureStreams_3_4(
- requestedConfiguration3_4, configStream34Cb);
- res = postprocConfigStream34(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_3 != nullptr) {
- // We do; use v3.3 for the call
- ALOGV("%s: v3.3 device found", __FUNCTION__);
- auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
- [&status, &finalConfiguration]
- (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
- finalConfiguration = halConfiguration;
- status = s;
- });
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- } else {
- // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
- ALOGV("%s: v3.2 device found", __FUNCTION__);
- HalStreamConfiguration finalConfiguration_3_2;
- auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
- [&status, &finalConfiguration_3_2]
- (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
- finalConfiguration_3_2 = halConfiguration;
- status = s;
- });
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
- for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
- finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
- finalConfiguration.streams[i].overrideDataSpace =
- requestedConfiguration3_2.streams[i].dataSpace;
- }
- }
-
- if (status != common::V1_0::Status::OK ) {
- return CameraProviderManager::mapToStatusT(status);
- }
-
- // And convert output stream configuration from HIDL
-
- for (size_t i = 0; i < config->num_streams; i++) {
- camera3::camera_stream_t *dst = config->streams[i];
- int streamId = Camera3Stream::cast(dst)->getId();
-
- // Start scan at i, with the assumption that the stream order matches
- size_t realIdx = i;
- bool found = false;
- size_t halStreamCount = finalConfiguration.streams.size();
- for (size_t idx = 0; idx < halStreamCount; idx++) {
- if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
- found = true;
- break;
- }
- realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
- }
- if (!found) {
- ALOGE("%s: Stream %d not found in stream configuration response from HAL",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
- device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
-
- Camera3Stream* dstStream = Camera3Stream::cast(dst);
- int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
- android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
-
- if (mHidlSession_3_6 != nullptr) {
- dstStream->setOfflineProcessingSupport(src_36.supportOffline);
- }
-
- if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
- dstStream->setFormatOverride(false);
- dstStream->setDataSpaceOverride(false);
- if (dst->format != overrideFormat) {
- ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
- streamId, dst->format);
- }
- if (dst->data_space != overrideDataSpace) {
- ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
- streamId, dst->format);
- }
- } else {
- bool needFormatOverride =
- requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
- bool needDataspaceOverride =
- requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
- // Override allowed with IMPLEMENTATION_DEFINED
- dstStream->setFormatOverride(needFormatOverride);
- dstStream->setDataSpaceOverride(needDataspaceOverride);
- dst->format = overrideFormat;
- dst->data_space = overrideDataSpace;
- }
-
- if (dst->stream_type == CAMERA_STREAM_INPUT) {
- if (src.v3_2.producerUsage != 0) {
- ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- dstStream->setUsage(
- mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
- } else {
- // OUTPUT
- if (src.v3_2.consumerUsage != 0) {
- ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- dstStream->setUsage(
- mapProducerToFrameworkUsage(src.v3_2.producerUsage));
- }
- dst->max_buffers = src.v3_2.maxBuffers;
- }
-
- return res;
-}
-
-status_t Camera3Device::HalInterface::configureInjectedStreams(
- const camera_metadata_t* sessionParams, camera_stream_configuration* config,
- const std::vector<uint32_t>& bufferSizes,
- const CameraMetadata& cameraCharacteristics) {
- ATRACE_NAME("InjectionCameraHal::configureStreams");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- if (config->input_is_multi_resolution) {
- ALOGE("%s: Injection camera device doesn't support multi-resolution input "
- "stream", __FUNCTION__);
- return BAD_VALUE;
- }
-
- // Convert stream config to HIDL
- std::set<int> activeStreams;
- device::V3_2::StreamConfiguration requestedConfiguration3_2;
- device::V3_4::StreamConfiguration requestedConfiguration3_4;
- device::V3_7::StreamConfiguration requestedConfiguration3_7;
- requestedConfiguration3_2.streams.resize(config->num_streams);
- requestedConfiguration3_4.streams.resize(config->num_streams);
- requestedConfiguration3_7.streams.resize(config->num_streams);
- for (size_t i = 0; i < config->num_streams; i++) {
- device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
- device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
- device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
- camera3::camera_stream_t* src = config->streams[i];
-
- Camera3Stream* cam3stream = Camera3Stream::cast(src);
- cam3stream->setBufferFreedListener(this);
- int streamId = cam3stream->getId();
- StreamType streamType;
- switch (src->stream_type) {
- case CAMERA_STREAM_OUTPUT:
- streamType = StreamType::OUTPUT;
- break;
- case CAMERA_STREAM_INPUT:
- streamType = StreamType::INPUT;
- break;
- default:
- ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
- streamId, config->streams[i]->stream_type);
- return BAD_VALUE;
- }
- dst3_2.id = streamId;
- dst3_2.streamType = streamType;
- dst3_2.width = src->width;
- dst3_2.height = src->height;
- dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst3_2.rotation =
- mapToStreamRotation((camera_stream_rotation_t)src->rotation);
- // For HidlSession version 3.5 or newer, the format and dataSpace sent
- // to HAL are original, not the overridden ones.
- if (mHidlSession_3_5 != nullptr) {
- dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
- ? cam3stream->getOriginalFormat()
- : src->format);
- dst3_2.dataSpace =
- mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
- ? cam3stream->getOriginalDataSpace()
- : src->data_space);
- } else {
- dst3_2.format = mapToPixelFormat(src->format);
- dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
- }
- dst3_4.v3_2 = dst3_2;
- dst3_4.bufferSize = bufferSizes[i];
- if (src->physical_camera_id != nullptr) {
- dst3_4.physicalCameraId = src->physical_camera_id;
- }
- dst3_7.v3_4 = dst3_4;
- dst3_7.groupId = cam3stream->getHalStreamGroupId();
- dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
- size_t j = 0;
- for (int mode : src->sensor_pixel_modes_used) {
- dst3_7.sensorPixelModesUsed[j++] =
- static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
- }
- activeStreams.insert(streamId);
- // Create Buffer ID map if necessary
- mBufferRecords.tryCreateBufferCache(streamId);
- }
- // remove BufferIdMap for deleted streams
- mBufferRecords.removeInactiveBufferCaches(activeStreams);
-
- StreamConfigurationMode operationMode;
- res = mapToStreamConfigurationMode(
- (camera_stream_configuration_mode_t)config->operation_mode,
- /*out*/ &operationMode);
- if (res != OK) {
- return res;
- }
- requestedConfiguration3_7.operationMode = operationMode;
- size_t sessionParamSize = get_camera_metadata_size(sessionParams);
- requestedConfiguration3_7.operationMode = operationMode;
- requestedConfiguration3_7.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
-
- // See which version of HAL we have
- if (mHidlSession_3_7 != nullptr) {
- requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
- requestedConfiguration3_7.multiResolutionInputImage =
- config->input_is_multi_resolution;
-
- const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
- ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
- hidlChars.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
- get_camera_metadata_size(rawMetadata));
- cameraCharacteristics.unlock(rawMetadata);
-
- sp<hardware::camera::device::V3_7::ICameraInjectionSession>
- hidlInjectionSession_3_7;
- auto castInjectionResult_3_7 =
- device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
- if (castInjectionResult_3_7.isOk()) {
- hidlInjectionSession_3_7 = castInjectionResult_3_7;
- } else {
- ALOGE("%s: Transaction error: %s", __FUNCTION__,
- castInjectionResult_3_7.description().c_str());
- return DEAD_OBJECT;
- }
-
- auto err = hidlInjectionSession_3_7->configureInjectionStreams(
- requestedConfiguration3_7, hidlChars);
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__,
- err.description().c_str());
- return DEAD_OBJECT;
- }
- } else {
- ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
- "session is 3.7", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- return res;
-}
-
-status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
- /*out*/device::V3_2::CaptureRequest* captureRequest,
- /*out*/std::vector<native_handle_t*>* handlesCreated,
- /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
- ATRACE_CALL();
- if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
- ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
- "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
- return BAD_VALUE;
- }
-
- captureRequest->frameNumber = request->frame_number;
-
- captureRequest->fmqSettingsSize = 0;
-
- {
- if (request->input_buffer != nullptr) {
- int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
- buffer_handle_t buf = *(request->input_buffer->buffer);
- auto pair = getBufferId(buf, streamId);
- bool isNewBuffer = pair.first;
- uint64_t bufferId = pair.second;
- captureRequest->inputBuffer.streamId = streamId;
- captureRequest->inputBuffer.bufferId = bufferId;
- captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
- captureRequest->inputBuffer.status = BufferStatus::OK;
- native_handle_t *acquireFence = nullptr;
- if (request->input_buffer->acquire_fence != -1) {
- acquireFence = native_handle_create(1,0);
- acquireFence->data[0] = request->input_buffer->acquire_fence;
- handlesCreated->push_back(acquireFence);
- }
- captureRequest->inputBuffer.acquireFence = acquireFence;
- captureRequest->inputBuffer.releaseFence = nullptr;
-
- mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
- request->input_buffer->buffer);
- inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
- } else {
- captureRequest->inputBuffer.streamId = -1;
- captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
- }
-
- captureRequest->outputBuffers.resize(request->num_output_buffers);
- for (size_t i = 0; i < request->num_output_buffers; i++) {
- const camera_stream_buffer_t *src = request->output_buffers + i;
- StreamBuffer &dst = captureRequest->outputBuffers[i];
- int32_t streamId = Camera3Stream::cast(src->stream)->getId();
- if (src->buffer != nullptr) {
- buffer_handle_t buf = *(src->buffer);
- auto pair = getBufferId(buf, streamId);
- bool isNewBuffer = pair.first;
- dst.bufferId = pair.second;
- dst.buffer = isNewBuffer ? buf : nullptr;
- native_handle_t *acquireFence = nullptr;
- if (src->acquire_fence != -1) {
- acquireFence = native_handle_create(1,0);
- acquireFence->data[0] = src->acquire_fence;
- handlesCreated->push_back(acquireFence);
- }
- dst.acquireFence = acquireFence;
- } else if (mUseHalBufManager) {
- // HAL buffer management path
- dst.bufferId = BUFFER_ID_NO_BUFFER;
- dst.buffer = nullptr;
- dst.acquireFence = nullptr;
- } else {
- ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
- return BAD_VALUE;
- }
- dst.streamId = streamId;
- dst.status = BufferStatus::OK;
- dst.releaseFence = nullptr;
-
- // Output buffers are empty when using HAL buffer manager
- if (!mUseHalBufManager) {
- mBufferRecords.pushInflightBuffer(
- captureRequest->frameNumber, streamId, src->buffer);
- inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
- }
- }
- }
- return OK;
-}
-
void Camera3Device::HalInterface::cleanupNativeHandles(
std::vector<native_handle_t*> *handles, bool closeFd) {
if (handles == nullptr) {
@@ -3885,314 +2746,6 @@
return;
}
-status_t Camera3Device::HalInterface::processBatchCaptureRequests(
- std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
- ATRACE_NAME("CameraHal::processBatchCaptureRequests");
- if (!valid()) return INVALID_OPERATION;
-
- sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
- sp<device::V3_7::ICameraDeviceSession> hidlSession_3_7;
- auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_7.isOk()) {
- hidlSession_3_7 = castResult_3_7;
- }
- auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_4.isOk()) {
- hidlSession_3_4 = castResult_3_4;
- }
-
- hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
- hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
- hardware::hidl_vec<device::V3_7::CaptureRequest> captureRequests_3_7;
- size_t batchSize = requests.size();
- if (hidlSession_3_7 != nullptr) {
- captureRequests_3_7.resize(batchSize);
- } else if (hidlSession_3_4 != nullptr) {
- captureRequests_3_4.resize(batchSize);
- } else {
- captureRequests.resize(batchSize);
- }
- std::vector<native_handle_t*> handlesCreated;
- std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
-
- status_t res = OK;
- for (size_t i = 0; i < batchSize; i++) {
- if (hidlSession_3_7 != nullptr) {
- res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_7[i].v3_4.v3_2,
- /*out*/&handlesCreated, /*out*/&inflightBuffers);
- } else if (hidlSession_3_4 != nullptr) {
- res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
- /*out*/&handlesCreated, /*out*/&inflightBuffers);
- } else {
- res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
- /*out*/&handlesCreated, /*out*/&inflightBuffers);
- }
- if (res != OK) {
- mBufferRecords.popInflightBuffers(inflightBuffers);
- cleanupNativeHandles(&handlesCreated);
- return res;
- }
- }
-
- std::vector<device::V3_2::BufferCache> cachesToRemove;
- {
- std::lock_guard<std::mutex> lock(mFreedBuffersLock);
- for (auto& pair : mFreedBuffers) {
- // The stream might have been removed since onBufferFreed
- if (mBufferRecords.isStreamCached(pair.first)) {
- cachesToRemove.push_back({pair.first, pair.second});
- }
- }
- mFreedBuffers.clear();
- }
-
- common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
- *numRequestProcessed = 0;
-
- // Write metadata to FMQ.
- for (size_t i = 0; i < batchSize; i++) {
- camera_capture_request_t* request = requests[i];
- device::V3_2::CaptureRequest* captureRequest;
- if (hidlSession_3_7 != nullptr) {
- captureRequest = &captureRequests_3_7[i].v3_4.v3_2;
- } else if (hidlSession_3_4 != nullptr) {
- captureRequest = &captureRequests_3_4[i].v3_2;
- } else {
- captureRequest = &captureRequests[i];
- }
-
- if (request->settings != nullptr) {
- size_t settingsSize = get_camera_metadata_size(request->settings);
- if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
- reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
- captureRequest->settings.resize(0);
- captureRequest->fmqSettingsSize = settingsSize;
- } else {
- if (mRequestMetadataQueue != nullptr) {
- ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
- }
- captureRequest->settings.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
- get_camera_metadata_size(request->settings));
- captureRequest->fmqSettingsSize = 0u;
- }
- } else {
- // A null request settings maps to a size-0 CameraMetadata
- captureRequest->settings.resize(0);
- captureRequest->fmqSettingsSize = 0u;
- }
-
- // hidl session 3.7 specific handling.
- if (hidlSession_3_7 != nullptr) {
- captureRequests_3_7[i].inputWidth = request->input_width;
- captureRequests_3_7[i].inputHeight = request->input_height;
- }
-
- // hidl session 3.7 and 3.4 specific handling.
- if (hidlSession_3_7 != nullptr || hidlSession_3_4 != nullptr) {
- hardware::hidl_vec<device::V3_4::PhysicalCameraSetting>& physicalCameraSettings =
- (hidlSession_3_7 != nullptr) ?
- captureRequests_3_7[i].v3_4.physicalCameraSettings :
- captureRequests_3_4[i].physicalCameraSettings;
- physicalCameraSettings.resize(request->num_physcam_settings);
- for (size_t j = 0; j < request->num_physcam_settings; j++) {
- if (request->physcam_settings != nullptr) {
- size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
- if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
- reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
- settingsSize)) {
- physicalCameraSettings[j].settings.resize(0);
- physicalCameraSettings[j].fmqSettingsSize = settingsSize;
- } else {
- if (mRequestMetadataQueue != nullptr) {
- ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
- }
- physicalCameraSettings[j].settings.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
- request->physcam_settings[j])),
- get_camera_metadata_size(request->physcam_settings[j]));
- physicalCameraSettings[j].fmqSettingsSize = 0u;
- }
- } else {
- physicalCameraSettings[j].fmqSettingsSize = 0u;
- physicalCameraSettings[j].settings.resize(0);
- }
- physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
- }
- }
- }
-
- hardware::details::return_status err;
- auto resultCallback =
- [&status, &numRequestProcessed] (auto s, uint32_t n) {
- status = s;
- *numRequestProcessed = n;
- };
- if (hidlSession_3_7 != nullptr) {
- err = hidlSession_3_7->processCaptureRequest_3_7(captureRequests_3_7, cachesToRemove,
- resultCallback);
- } else if (hidlSession_3_4 != nullptr) {
- err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
- resultCallback);
- } else {
- err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
- resultCallback);
- }
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- status = common::V1_0::Status::CAMERA_DISCONNECTED;
- }
-
- if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
- ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
- __FUNCTION__, *numRequestProcessed, batchSize);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
-
- res = CameraProviderManager::mapToStatusT(status);
- if (res == OK) {
- if (mHidlSession->isRemote()) {
- // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
- // sent to camera HAL processes)
- cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
- } else {
- // In passthrough mode the FDs are now owned by HAL
- cleanupNativeHandles(&handlesCreated);
- }
- } else {
- mBufferRecords.popInflightBuffers(inflightBuffers);
- cleanupNativeHandles(&handlesCreated);
- }
- return res;
-}
-
-status_t Camera3Device::HalInterface::flush() {
- ATRACE_NAME("CameraHal::flush");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- auto err = mHidlSession->flush();
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- res = DEAD_OBJECT;
- } else {
- res = CameraProviderManager::mapToStatusT(err);
- }
-
- return res;
-}
-
-status_t Camera3Device::HalInterface::dump(int /*fd*/) {
- ATRACE_NAME("CameraHal::dump");
- if (!valid()) return INVALID_OPERATION;
-
- // Handled by CameraProviderManager::dump
-
- return OK;
-}
-
-status_t Camera3Device::HalInterface::repeatingRequestEnd(uint32_t frameNumber,
- hardware::hidl_vec<int32_t> streamIds) {
- ATRACE_NAME("CameraHal::repeatingRequestEnd");
- if (!valid()) return INVALID_OPERATION;
-
- if (mHidlSession_3_8.get() != nullptr) {
- mHidlSession_3_8->repeatingRequestEnd(frameNumber, streamIds);
- }
-
- return OK;
-}
-
-status_t Camera3Device::HalInterface::close() {
- ATRACE_NAME("CameraHal::close()");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- auto err = mHidlSession->close();
- // Interface will be dead shortly anyway, so don't log errors
- if (!err.isOk()) {
- res = DEAD_OBJECT;
- }
-
- return res;
-}
-
-void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
- ATRACE_NAME("CameraHal::signalPipelineDrain");
- if (!valid() || mHidlSession_3_5 == nullptr) {
- ALOGE("%s called on invalid camera!", __FUNCTION__);
- return;
- }
-
- auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return;
- }
-}
-
-status_t Camera3Device::HalInterface::switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords) {
- ATRACE_NAME("CameraHal::switchToOffline");
- if (!valid() || mHidlSession_3_6 == nullptr) {
- ALOGE("%s called on invalid camera!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
- ALOGE("%s: output arguments must not be null!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
- auto resultCallback =
- [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
- status = s;
- *offlineSessionInfo = info;
- *offlineSession = session;
- };
- auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
-
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
-
- status_t ret = CameraProviderManager::mapToStatusT(status);
- if (ret != OK) {
- return ret;
- }
-
- // TODO: assert no ongoing requestBuffer/returnBuffer call here
- // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
- // returns from switchToOffline.
-
-
- // Validate buffer caches
- std::vector<int32_t> streams;
- streams.reserve(offlineSessionInfo->offlineStreams.size());
- for (auto offlineStream : offlineSessionInfo->offlineStreams) {
- int32_t id = offlineStream.id;
- streams.push_back(id);
- // Verify buffer caches
- std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
- offlineStream.circulatingBufferIds.end());
- if (!verifyBufferIds(id, bufIds)) {
- ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
- return UNKNOWN_ERROR;
- }
- }
-
- // Move buffer records
- bufferRecords->takeBufferCaches(mBufferRecords, streams);
- bufferRecords->takeInflightBufferMap(mBufferRecords);
- bufferRecords->takeRequestedBufferMap(mBufferRecords);
- return ret;
-}
-
void Camera3Device::HalInterface::getInflightBufferKeys(
std::vector<std::pair<int32_t, int32_t>>* out) {
mBufferRecords.getInflightBufferKeys(out);
@@ -5415,38 +3968,6 @@
mPrevRequest.clear();
}
-status_t Camera3Device::RequestThread::switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords) {
- Mutex::Autolock l(mRequestLock);
- clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
-
- // Wait until request thread is fully stopped
- // TBD: check if request thread is being paused by other APIs (shouldn't be)
-
- // We could also check for mRepeatingRequests.empty(), but the API interface
- // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
- // new requests during the call; hence skip that check.
- bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
- while (!queueEmpty) {
- status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
- if (res == TIMED_OUT) {
- ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
- return res;
- } else if (res != OK) {
- ALOGE("%s: request thread failed to submit a request: %s (%d)!",
- __FUNCTION__, strerror(-res), res);
- return res;
- }
- queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
- }
-
- return mInterface->switchToOffline(
- streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
-}
-
status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
ATRACE_CALL();
@@ -6477,220 +4998,6 @@
return ret;
}
-status_t Camera3Device::switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/ sp<CameraOfflineSessionBase>* session) {
- ATRACE_CALL();
- if (session == nullptr) {
- ALOGE("%s: session must not be null", __FUNCTION__);
- return BAD_VALUE;
- }
-
- Mutex::Autolock il(mInterfaceLock);
-
- bool hasInputStream = mInputStream != nullptr;
- int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
- bool inputStreamSupportsOffline = hasInputStream ?
- mInputStream->getOfflineProcessingSupport() : false;
- auto outputStreamIds = mOutputStreams.getStreamIds();
- auto streamIds = outputStreamIds;
- if (hasInputStream) {
- streamIds.push_back(mInputStream->getId());
- }
-
- // Check all streams in streamsToKeep supports offline mode
- for (auto id : streamsToKeep) {
- if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
- ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
- return BAD_VALUE;
- } else if (id == inputStreamId) {
- if (!inputStreamSupportsOffline) {
- ALOGE("%s: input stream %d cannot be switched to offline",
- __FUNCTION__, id);
- return BAD_VALUE;
- }
- } else {
- sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
- if (!stream->getOfflineProcessingSupport()) {
- ALOGE("%s: output stream %d cannot be switched to offline",
- __FUNCTION__, id);
- return BAD_VALUE;
- }
- }
- }
-
- // TODO: block surface sharing and surface group streams until we can support them
-
- // Stop repeating request, wait until all remaining requests are submitted, then call into
- // HAL switchToOffline
- hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
- camera3::BufferRecords bufferRecords;
- status_t ret = mRequestThread->switchToOffline(
- streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
-
- if (ret != OK) {
- SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
- return ret;
- }
-
- bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
- if (!succ) {
- SET_ERR("HAL must not be calling requestStreamBuffers call");
- // TODO: block ALL callbacks from HAL till app configured new streams?
- return UNKNOWN_ERROR;
- }
-
- // Verify offlineSessionInfo
- std::vector<int32_t> offlineStreamIds;
- offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
- for (auto offlineStream : offlineSessionInfo.offlineStreams) {
- // verify stream IDs
- int32_t id = offlineStream.id;
- if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
- SET_ERR("stream ID %d not found!", id);
- return UNKNOWN_ERROR;
- }
-
- // When not using HAL buf manager, only allow streams requested by app to be preserved
- if (!mUseHalBufManager) {
- if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
- SET_ERR("stream ID %d must not be switched to offline!", id);
- return UNKNOWN_ERROR;
- }
- }
-
- offlineStreamIds.push_back(id);
- sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
- static_cast<sp<Camera3StreamInterface>>(mInputStream) :
- static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
- // Verify number of outstanding buffers
- if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
- SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
- id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
- return UNKNOWN_ERROR;
- }
- }
-
- // Verify all streams to be deleted don't have any outstanding buffers
- if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
- inputStreamId) == offlineStreamIds.end()) {
- if (mInputStream->hasOutstandingBuffers()) {
- SET_ERR("Input stream %d still has %zu outstanding buffer!",
- inputStreamId, mInputStream->getOutstandingBuffersCount());
- return UNKNOWN_ERROR;
- }
- }
-
- for (const auto& outStreamId : outputStreamIds) {
- if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
- outStreamId) == offlineStreamIds.end()) {
- auto outStream = mOutputStreams.get(outStreamId);
- if (outStream->hasOutstandingBuffers()) {
- SET_ERR("Output stream %d still has %zu outstanding buffer!",
- outStreamId, outStream->getOutstandingBuffersCount());
- return UNKNOWN_ERROR;
- }
- }
- }
-
- InFlightRequestMap offlineReqs;
- // Verify inflight requests and their pending buffers
- {
- std::lock_guard<std::mutex> l(mInFlightLock);
- for (auto offlineReq : offlineSessionInfo.offlineRequests) {
- int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
- if (idx == NAME_NOT_FOUND) {
- SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
- return UNKNOWN_ERROR;
- }
-
- const auto& inflightReq = mInFlightMap.valueAt(idx);
- // TODO: check specific stream IDs
- size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
- if (numBuffersLeft != offlineReq.pendingStreams.size()) {
- SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
- inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
- return UNKNOWN_ERROR;
- }
- offlineReqs.add(offlineReq.frameNumber, inflightReq);
- }
- }
-
- // Create Camera3OfflineSession and transfer object ownership
- // (streams, inflight requests, buffer caches)
- camera3::StreamSet offlineStreamSet;
- sp<camera3::Camera3Stream> inputStream;
- for (auto offlineStream : offlineSessionInfo.offlineStreams) {
- int32_t id = offlineStream.id;
- if (mInputStream != nullptr && id == mInputStream->getId()) {
- inputStream = mInputStream;
- } else {
- offlineStreamSet.add(id, mOutputStreams.get(id));
- }
- }
-
- // TODO: check if we need to lock before copying states
- // though technically no other thread should be talking to Camera3Device at this point
- Camera3OfflineStates offlineStates(
- mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
- mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mNextResultFrameNumber, mNextReprocessResultFrameNumber,
- mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
- mZoomRatioMappers, mRotateAndCropMappers);
-
- *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
- std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
-
- // Delete all streams that has been transferred to offline session
- Mutex::Autolock l(mLock);
- for (auto offlineStream : offlineSessionInfo.offlineStreams) {
- int32_t id = offlineStream.id;
- if (mInputStream != nullptr && id == mInputStream->getId()) {
- mInputStream.clear();
- } else {
- mOutputStreams.remove(id);
- }
- }
-
- // disconnect all other streams and switch to UNCONFIGURED state
- if (mInputStream != nullptr) {
- ret = mInputStream->disconnect();
- if (ret != OK) {
- SET_ERR_L("disconnect input stream failed!");
- return UNKNOWN_ERROR;
- }
- }
-
- for (auto streamId : mOutputStreams.getStreamIds()) {
- sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
- ret = stream->disconnect();
- if (ret != OK) {
- SET_ERR_L("disconnect output stream %d failed!", streamId);
- return UNKNOWN_ERROR;
- }
- }
-
- mInputStream.clear();
- mOutputStreams.clear();
- mNeedConfig = true;
- internalUpdateStatusLocked(STATUS_UNCONFIGURED);
- mOperatingMode = NO_MODE;
- mIsConstrainedHighSpeedConfiguration = false;
- mRequestThread->clearPreviousRequest();
-
- return OK;
- // TO be done by CameraDeviceClient/Camera3OfflineSession
- // register the offline client to camera service
- // Setup result passthing threads etc
- // Initialize offline session so HAL can start sending callback to it (result Fmq)
- // TODO: check how many onIdle callback will be sent
- // Java side to make sure the CameraCaptureSession is properly closed
-}
-
void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
ATRACE_CALL();
@@ -6777,7 +5084,7 @@
}
}
- res = mInjectionMethods->injectionInitialize(injectedCamId, manager, this);
+ res = injectionCameraInitialize(injectedCamId, manager);
if (res != OK) {
ALOGE("%s: Failed to initialize the injection camera! ret != NO_ERROR: %d",
__FUNCTION__, res);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3ce17f9..6c4ba49 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -29,20 +29,6 @@
#include <utils/KeyedVector.h>
#include <utils/Timers.h>
-#include <android/hardware/camera/device/3.2/ICameraDevice.h>
-#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
-#include <fmq/MessageQueue.h>
-
#include <camera/CaptureResult.h>
#include "android/hardware/camera/metadata/3.8/types.h"
@@ -59,6 +45,7 @@
#include "device3/Camera3OfflineSession.h"
#include "device3/Camera3StreamInterface.h"
#include "utils/TagMonitor.h"
+#include "utils/IPCTransport.h"
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
@@ -70,7 +57,6 @@
using android::camera3::camera_stream_configuration_mode_t;
using android::camera3::CAMERA_TEMPLATE_COUNT;
using android::camera3::OutputStreamInfo;
-using android::hardware::camera::metadata::V3_8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
namespace android {
@@ -87,11 +73,11 @@
*/
class Camera3Device :
public CameraDeviceBase,
- virtual public hardware::camera::device::V3_8::ICameraDeviceCallback,
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
public camera3::FlushBufferInterface {
+ friend class HidlCamera3Device;
public:
explicit Camera3Device(const String8& id, bool overrideForPerfClass, bool legacyClient = false);
@@ -107,7 +93,9 @@
metadata_vendor_id_t getVendorTagId() const override { return mVendorTagId; }
// Transitions to idle state on success.
- status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+ virtual status_t initialize(sp<CameraProviderManager> /*manager*/,
+ const String8& /*monitorTags*/) = 0;
+
status_t disconnect() override;
status_t dump(int fd, const Vector<String16> &args) override;
status_t startWatchingTags(const String8 &tags) override;
@@ -236,8 +224,10 @@
nsecs_t getExpectedInFlightDuration() override;
- status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
- /*out*/ sp<CameraOfflineSessionBase>* session) override;
+ virtual status_t switchToOffline(const std::vector<int32_t>& ,
+ /*out*/ sp<CameraOfflineSessionBase>* ) override {
+ return INVALID_OPERATION;
+ };
// RequestBufferInterface
bool startRequestBuffer() override;
@@ -288,35 +278,10 @@
*/
status_t stopInjection();
- /**
- * Helper functions to map between framework and HIDL values
- */
- static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
- static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
- android_dataspace dataSpace);
- static CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap mapToHidlDynamicProfile(
- int dynamicRangeProfile);
- static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
- static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
- camera_stream_rotation_t rotation);
- // Returns a negative error code if the passed-in operation mode is not valid.
- static status_t mapToStreamConfigurationMode(camera_stream_configuration_mode_t operationMode,
- /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
- static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
- static android_dataspace mapToFrameworkDataspace(
- hardware::camera::device::V3_2::DataspaceFlags);
- static uint64_t mapConsumerToFrameworkUsage(
- hardware::camera::device::V3_2::BufferUsageFlags usage);
- static uint64_t mapProducerToFrameworkUsage(
- hardware::camera::device::V3_2::BufferUsageFlags usage);
-
- private:
+ protected:
status_t disconnectImpl();
static status_t removeFwkOnlyRegionKeys(CameraMetadata *request);
- // internal typedefs
- using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-
static const size_t kDumpLockAttempts = 10;
static const size_t kDumpSleepDuration = 100000; // 0.10 sec
static const nsecs_t kActiveTimeout = 500000000; // 500 ms
@@ -362,70 +327,65 @@
// Flag indicating is the current active stream configuration is constrained high speed.
bool mIsConstrainedHighSpeedConfiguration;
- // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
- std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
-
/**** Scope for mLock ****/
- /**
- * Adapter for legacy HAL / HIDL HAL interface calls; calls either into legacy HALv3 or the
- * HIDL HALv3 interfaces.
- */
class HalInterface : public camera3::Camera3StreamBufferFreedListener,
public camera3::BufferRecordsInterface {
public:
- HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
- std::shared_ptr<RequestMetadataQueue> queue,
- bool useHalBufManager, bool supportOfflineProcessing);
+ HalInterface(bool useHalBufManager, bool supportOfflineProcessing) :
+ mUseHalBufManager(useHalBufManager),
+ mIsReconfigurationQuerySupported(true),
+ mSupportOfflineProcessing(supportOfflineProcessing)
+ {};
HalInterface(const HalInterface &other);
HalInterface();
+ virtual IPCTransport getTransportType() = 0;
+
// Returns true if constructed with a valid device or session, and not yet cleared
- bool valid();
+ virtual bool valid() = 0;
// Reset this HalInterface object (does not call close())
- void clear();
+ virtual void clear() = 0;
// Calls into the HAL interface
// Caller takes ownership of requestTemplate
- status_t constructDefaultRequestSettings(camera_request_template templateId,
- /*out*/ camera_metadata_t **requestTemplate);
- status_t configureStreams(const camera_metadata_t *sessionParams,
- /*inout*/ camera_stream_configuration_t *config,
- const std::vector<uint32_t>& bufferSizes);
+ virtual status_t constructDefaultRequestSettings(camera_request_template templateId,
+ /*out*/ camera_metadata_t **requestTemplate) = 0;
+
+ virtual status_t configureStreams(const camera_metadata_t * sessionParams,
+ /*inout*/ camera_stream_configuration_t * config,
+ const std::vector<uint32_t>& bufferSizes) = 0;
// The injection camera configures the streams to hal.
- status_t configureInjectedStreams(
+ virtual status_t configureInjectedStreams(
const camera_metadata_t* sessionParams,
/*inout*/ camera_stream_configuration_t* config,
const std::vector<uint32_t>& bufferSizes,
- const CameraMetadata& cameraCharacteristics);
+ const CameraMetadata& cameraCharacteristics) = 0;
// When the call succeeds, the ownership of acquire fences in requests is transferred to
// HalInterface. More specifically, the current implementation will send the fence to
// HAL process and close the FD in cameraserver process. When the call fails, the ownership
// of the acquire fence still belongs to the caller.
- status_t processBatchCaptureRequests(
+ virtual status_t processBatchCaptureRequests(
std::vector<camera_capture_request_t*>& requests,
- /*out*/uint32_t* numRequestProcessed);
- status_t flush();
- status_t dump(int fd);
- status_t close();
+ /*out*/uint32_t* numRequestProcessed) = 0;
- void signalPipelineDrain(const std::vector<int>& streamIds);
- bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
- CameraMetadata& newSessionParams);
+ virtual status_t flush() = 0;
- // Upon successful return, HalInterface will return buffer maps needed for offline
- // processing, and clear all its internal buffer maps.
- status_t switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords);
+ virtual status_t dump(int fd) = 0;
- status_t repeatingRequestEnd(uint32_t frameNumber, hardware::hidl_vec<int32_t> streamIds);
+ virtual status_t close() = 0;
+
+ virtual void signalPipelineDrain(const std::vector<int>& streamIds) = 0;
+
+ virtual bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
+ CameraMetadata& newSessionParams) = 0;
+
+ virtual status_t repeatingRequestEnd(uint32_t frameNumber,
+ const std::vector<int32_t> &streamIds) = 0;
/////////////////////////////////////////////////////////////////////
// Implements BufferRecordsInterface
@@ -456,40 +416,36 @@
void onStreamReConfigured(int streamId);
- private:
- // Always valid
- sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
- // Valid if ICameraDeviceSession is @3.3 or newer
- sp<hardware::camera::device::V3_3::ICameraDeviceSession> mHidlSession_3_3;
- // Valid if ICameraDeviceSession is @3.4 or newer
- sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
- // Valid if ICameraDeviceSession is @3.5 or newer
- sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
- // Valid if ICameraDeviceSession is @3.6 or newer
- sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
- // Valid if ICameraDeviceSession is @3.7 or newer
- sp<hardware::camera::device::V3_7::ICameraDeviceSession> mHidlSession_3_7;
- // Valid if ICameraDeviceSession is @3.8 or newer
- sp<hardware::camera::device::V3_8::ICameraDeviceSession> mHidlSession_3_8;
-
- std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
-
- // The output HIDL request still depends on input camera_capture_request_t
- // Do not free input camera_capture_request_t before output HIDL request
- status_t wrapAsHidlRequest(camera_capture_request_t* in,
- /*out*/hardware::camera::device::V3_2::CaptureRequest* out,
- /*out*/std::vector<native_handle_t*>* handlesCreated,
- /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
-
- status_t pushInflightBufferLocked(int32_t frameNumber, int32_t streamId,
- buffer_handle_t *buffer);
-
- // Pop inflight buffers based on pairs of (frameNumber,streamId)
- void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
+ protected:
// Return true if the input caches match what we have; otherwise false
bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
+ template <typename OfflineSessionInfoT>
+ status_t verifyBufferCaches(
+ const OfflineSessionInfoT *offlineSessionInfo, camera3::BufferRecords *bufferRecords) {
+ // Validate buffer caches
+ std::vector<int32_t> streams;
+ streams.reserve(offlineSessionInfo->offlineStreams.size());
+ for (auto offlineStream : offlineSessionInfo->offlineStreams) {
+ int32_t id = offlineStream.id;
+ streams.push_back(id);
+ // Verify buffer caches
+ std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
+ offlineStream.circulatingBufferIds.end());
+ if (!verifyBufferIds(id, bufIds)) {
+ ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ // Move buffer records
+ bufferRecords->takeBufferCaches(mBufferRecords, streams);
+ bufferRecords->takeInflightBufferMap(mBufferRecords);
+ bufferRecords->takeRequestedBufferMap(mBufferRecords);
+ return OK;
+ }
+
// Delete and optionally close native handles and clear the input vector afterward
static void cleanupNativeHandles(
std::vector<native_handle_t*> *handles, bool closeFd = false);
@@ -508,7 +464,7 @@
bool mIsReconfigurationQuerySupported;
const bool mSupportOfflineProcessing;
- };
+ }; // class HalInterface
sp<HalInterface> mInterface;
@@ -634,41 +590,6 @@
bool repeating,
int64_t *lastFrameNumber = NULL);
-
- /**
- * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
- */
-
- hardware::Return<void> processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) override;
- hardware::Return<void> processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) override;
- hardware::Return<void> notify(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
-
- hardware::Return<void> requestStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) override;
-
- hardware::Return<void> returnStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
-
- hardware::Return<void> notify_3_8(
- const hardware::hidl_vec<
- hardware::camera::device::V3_8::NotifyMsg>& msgs) override;
-
- template<typename NotifyMsgType>
- hardware::Return<void> notifyHelper(
- const hardware::hidl_vec<NotifyMsgType>& msgs);
-
- // Handle one notify message
- void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
-
// lock to ensure only one processCaptureResult is called at a time.
Mutex mProcessCaptureResultLock;
@@ -686,6 +607,9 @@
*/
virtual CameraMetadata getLatestRequestLocked();
+ virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+ sp<CameraProviderManager> manager) = 0;
+
/**
* Update the current device status and wake all waiting threads.
*
@@ -934,12 +858,6 @@
void signalPipelineDrain(const std::vector<int>& streamIds);
void resetPipelineDrain();
- status_t switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords);
-
void clearPreviousRequest();
status_t setRotateAndCropAutoBehavior(
@@ -954,7 +872,6 @@
virtual bool threadLoop();
- private:
static const String8& getId(const wp<Camera3Device> &device);
status_t queueTriggerLocked(RequestTrigger trigger);
@@ -1119,6 +1036,14 @@
const bool mUseHalBufManager;
const bool mSupportCameraMute;
};
+
+ virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> /*parent*/,
+ sp<camera3::StatusTracker> /*statusTracker*/,
+ sp<HalInterface> /*interface*/,
+ const Vector<int32_t>& /*sessionParamKeys*/,
+ bool /*useHalBufManager*/,
+ bool /*supportCameraMute*/) = 0;
+
sp<RequestThread> mRequestThread;
/**
@@ -1394,13 +1319,6 @@
~Camera3DeviceInjectionMethods();
- // Initialize the injection camera and generate an hal interface.
- status_t injectionInitialize(
- const String8& injectedCamId, sp<CameraProviderManager> manager,
- const sp<
- android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
- callback);
-
// Injection camera will replace the internal camera and configure streams
// when device is IDLE and request thread is paused.
status_t injectCamera(
@@ -1426,7 +1344,7 @@
const camera3::camera_stream_configuration& injectionConfig,
const std::vector<uint32_t>& injectionBufferSizes);
- private:
+ protected:
// Configure the streams of injection camera, it need wait until the
// output streams are created and configured to the original camera before
// proceeding.
@@ -1439,8 +1357,8 @@
// Use injection camera hal interface to replace and backup original
// camera hal interface.
- status_t replaceHalInterface(sp<HalInterface> newHalInterface,
- bool keepBackup);
+ virtual status_t replaceHalInterface(sp<HalInterface> /*newHalInterface*/,
+ bool /*keepBackup*/) = 0;
wp<Camera3Device> mParent;
@@ -1450,13 +1368,6 @@
// Generated injection camera hal interface.
sp<HalInterface> mInjectedCamHalInterface;
- // Backup of the original camera hal result FMQ.
- std::unique_ptr<ResultMetadataQueue> mBackupResultMetadataQueue;
-
- // FMQ writes the result for the injection camera. Must be guarded by
- // mProcessCaptureResultLock.
- std::unique_ptr<ResultMetadataQueue> mInjectionResultMetadataQueue;
-
// The flag indicates that the stream configuration is complete, the camera device is
// active, but the injection camera has not yet been injected.
bool mIsStreamConfigCompleteButNotInjected = false;
@@ -1477,6 +1388,10 @@
// The injection camera ID.
String8 mInjectedCamId;
};
+
+ virtual sp<Camera3DeviceInjectionMethods>
+ createCamera3DeviceInjectionMethods(wp<Camera3Device>) = 0;
+
sp<Camera3DeviceInjectionMethods> mInjectionMethods;
}; // class Camera3Device
diff --git a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
index 4744a6d..6818acf 100644
--- a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
@@ -39,92 +39,6 @@
injectionDisconnectImpl();
}
-status_t Camera3Device::Camera3DeviceInjectionMethods::injectionInitialize(
- const String8& injectedCamId, sp<CameraProviderManager> manager,
- const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
- callback) {
- ATRACE_CALL();
- Mutex::Autolock lock(mInjectionLock);
-
- if (manager == nullptr) {
- ALOGE("%s: manager does not exist!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- sp<Camera3Device> parent = mParent.promote();
- if (parent == nullptr) {
- ALOGE("%s: parent does not exist!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- mInjectedCamId = injectedCamId;
- sp<ICameraDeviceSession> session;
- ATRACE_BEGIN("Injection CameraHal::openSession");
- status_t res = manager->openSession(injectedCamId.string(), callback,
- /*out*/ &session);
- ATRACE_END();
- if (res != OK) {
- ALOGE("Injection camera could not open camera session: %s (%d)",
- strerror(-res), res);
- return res;
- }
-
- std::shared_ptr<RequestMetadataQueue> queue;
- auto requestQueueRet =
- session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
- queue = std::make_shared<RequestMetadataQueue>(descriptor);
- if (!queue->isValid() || queue->availableToWrite() <= 0) {
- ALOGE("Injection camera HAL returns empty request metadata fmq, not "
- "use it");
- queue = nullptr;
- // don't use the queue onwards.
- }
- });
- if (!requestQueueRet.isOk()) {
- ALOGE("Injection camera transaction error when getting request metadata fmq: "
- "%s, not use it", requestQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
-
- std::unique_ptr<ResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
- auto resultQueueRet = session->getCaptureResultMetadataQueue(
- [&resQueue](const auto& descriptor) {
- resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
- ALOGE("Injection camera HAL returns empty result metadata fmq, not use "
- "it");
- resQueue = nullptr;
- // Don't use the resQueue onwards.
- }
- });
- if (!resultQueueRet.isOk()) {
- ALOGE("Injection camera transaction error when getting result metadata queue "
- "from camera session: %s", resultQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
- IF_ALOGV() {
- session->interfaceChain(
- [](::android::hardware::hidl_vec<::android::hardware::hidl_string>
- interfaceChain) {
- ALOGV("Injection camera session interface chain:");
- for (const auto& iface : interfaceChain) {
- ALOGV(" %s", iface.c_str());
- }
- });
- }
-
- ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
- mInjectedCamHalInterface =
- new HalInterface(session, queue, parent->mUseHalBufManager,
- parent->mSupportOfflineProcessing);
- if (mInjectedCamHalInterface == nullptr) {
- ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- return OK;
-}
-
status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
camera3::camera_stream_configuration& injectionConfig,
const std::vector<uint32_t>& injectionBufferSizes) {
@@ -379,37 +293,4 @@
}
}
-status_t Camera3Device::Camera3DeviceInjectionMethods::replaceHalInterface(
- sp<HalInterface> newHalInterface, bool keepBackup) {
- Mutex::Autolock lock(mInjectionLock);
- if (newHalInterface.get() == nullptr) {
- ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
- __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- sp<Camera3Device> parent = mParent.promote();
- if (parent == nullptr) {
- ALOGE("%s: parent does not exist!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- if (keepBackup) {
- if (mBackupHalInterface == nullptr) {
- mBackupHalInterface = parent->mInterface;
- }
- if (mBackupResultMetadataQueue == nullptr) {
- mBackupResultMetadataQueue = std::move(parent->mResultMetadataQueue);
- parent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
- }
- } else {
- mBackupHalInterface = nullptr;
- parent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
- mBackupResultMetadataQueue = nullptr;
- }
- parent->mInterface = newHalInterface;
-
- return OK;
-}
-
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index b702e20..7cfa255 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -47,14 +47,12 @@
const camera3::StreamSet& offlineStreamSet,
camera3::BufferRecords&& bufferRecords,
const camera3::InFlightRequestMap& offlineReqs,
- const Camera3OfflineStates& offlineStates,
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
+ const Camera3OfflineStates& offlineStates) :
mId(id),
mInputStream(inputStream),
mOutputStreams(offlineStreamSet),
mBufferRecords(std::move(bufferRecords)),
mOfflineReqs(offlineReqs),
- mSession(offlineSession),
mTagMonitor(offlineStates.mTagMonitor),
mVendorTagId(offlineStates.mVendorTagId),
mUseHalBufManager(offlineStates.mUseHalBufManager),
@@ -90,43 +88,6 @@
return mId;
}
-status_t Camera3OfflineSession::initialize(wp<NotificationListener> listener) {
- ATRACE_CALL();
-
- if (mSession == nullptr) {
- ALOGE("%s: HIDL session is null!", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
-
- mListener = listener;
-
- // setup result FMQ
- std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
- auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
- [&resQueue](const auto& descriptor) {
- resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
- ALOGE("HAL returns empty result metadata fmq, not use it");
- resQueue = nullptr;
- // Don't use resQueue onwards.
- }
- });
- if (!resultQueueRet.isOk()) {
- ALOGE("Transaction error when getting result metadata queue from camera session: %s",
- resultQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
- mStatus = STATUS_ACTIVE;
- }
-
- mSession->setCallback(this);
-
- return OK;
-}
-
status_t Camera3OfflineSession::dump(int /*fd*/) {
ATRACE_CALL();
std::lock_guard<std::mutex> il(mInterfaceLock);
@@ -135,6 +96,7 @@
status_t Camera3OfflineSession::disconnect() {
ATRACE_CALL();
+ disconnectSession();
return disconnectImpl();
}
@@ -170,10 +132,6 @@
streams.push_back(mInputStream);
}
- if (mSession != nullptr) {
- mSession->close();
- }
-
FlushInflightReqStates states {
mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
listener, *this, mBufferRecords, *this, mSessionStatsBuilder};
@@ -182,7 +140,6 @@
{
std::lock_guard<std::mutex> lock(mLock);
- mSession.clear();
mOutputStreams.clear();
mInputStream.clear();
mStatus = STATUS_CLOSED;
@@ -235,149 +192,6 @@
return OK;
}
-hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) {
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- listener = mListener.promote();
- }
-
- CaptureOutputStates states {
- mId,
- mOfflineReqsLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false
- };
-
- std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
- }
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) {
- // TODO: changed impl to call into processCaptureResult_3_4 instead?
- // might need to figure how to reduce copy though.
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- listener = mListener.promote();
- }
-
- hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
-
- CaptureOutputStates states {
- mId,
- mOfflineReqsLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false
- };
-
- std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result, noPhysMetadata);
- }
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::notify(
- const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- listener = mListener.promote();
- }
-
- CaptureOutputStates states {
- mId,
- mOfflineReqsLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false
- };
- for (const auto& msg : msgs) {
- camera3::notify(states, msg);
- }
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) {
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- }
-
- RequestBufferStates states {
- mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
- *this, mBufferRecords, *this};
- camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- }
-
- ReturnBufferStates states {
- mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, mBufferRecords};
- camera3::returnStreamBuffers(states, buffers);
- return hardware::Void();
-}
-
void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 5581964..0f7d145 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -131,7 +131,6 @@
*/
class Camera3OfflineSession :
public CameraOfflineSessionBase,
- virtual public hardware::camera::device::V3_5::ICameraDeviceCallback,
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
@@ -144,12 +143,11 @@
const camera3::StreamSet& offlineStreamSet,
camera3::BufferRecords&& bufferRecords,
const camera3::InFlightRequestMap& offlineReqs,
- const Camera3OfflineStates& offlineStates,
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession);
+ const Camera3OfflineStates& offlineStates);
virtual ~Camera3OfflineSession();
- virtual status_t initialize(wp<NotificationListener> listener) override;
+ virtual status_t initialize(wp<NotificationListener> /*listener*/) = 0;
/**
* CameraOfflineSessionBase interface
@@ -171,38 +169,7 @@
* End of CameraOfflineSessionBase interface
*/
- /**
- * HIDL ICameraDeviceCallback interface
- */
-
- /**
- * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
- */
-
- hardware::Return<void> processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) override;
- hardware::Return<void> processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) override;
- hardware::Return<void> notify(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
-
- hardware::Return<void> requestStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) override;
-
- hardware::Return<void> returnStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
-
- /**
- * End of CameraOfflineSessionBase interface
- */
-
- private:
+ protected:
// Camera device ID
const String8 mId;
sp<camera3::Camera3Stream> mInputStream;
@@ -213,8 +180,6 @@
std::mutex mOfflineReqsLock;
camera3::InFlightRequestMap mOfflineReqs;
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> mSession;
-
TagMonitor mTagMonitor;
const metadata_vendor_id_t mVendorTagId;
@@ -269,8 +234,6 @@
// End of mLock protect scope
std::mutex mProcessCaptureResultLock;
- // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
- std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
// Tracking cause of fatal errors when in STATUS_ERROR
String8 mErrorCause;
@@ -305,6 +268,8 @@
void setErrorStateLockedV(const char *fmt, va_list args);
status_t disconnectImpl();
+ virtual void disconnectSession() = 0;
+
}; // class Camera3OfflineSession
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 24f81f3..d8cc685 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -376,43 +376,6 @@
insertResultLocked(states, &captureResult, frameNumber);
}
-// Reading one camera metadata from result argument via fmq or from the result
-// Assuming the fmq is protected by a lock already
-status_t readOneCameraMetadataLocked(
- std::unique_ptr<ResultMetadataQueue>& fmq,
- uint64_t fmqResultSize,
- hardware::camera::device::V3_2::CameraMetadata& resultMetadata,
- const hardware::camera::device::V3_2::CameraMetadata& result) {
- if (fmqResultSize > 0) {
- resultMetadata.resize(fmqResultSize);
- if (fmq == nullptr) {
- return NO_MEMORY; // logged in initialize()
- }
- if (!fmq->read(resultMetadata.data(), fmqResultSize)) {
- ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
- __FUNCTION__, fmqResultSize);
- return INVALID_OPERATION;
- }
- } else {
- resultMetadata.setToExternal(const_cast<uint8_t *>(result.data()),
- result.size());
- }
-
- if (resultMetadata.size() != 0) {
- status_t res;
- const camera_metadata_t* metadata =
- reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
- size_t expected_metadata_size = resultMetadata.size();
- if ((res = validate_camera_metadata_structure(metadata, &expected_metadata_size)) != OK) {
- ALOGE("%s: Invalid camera metadata received by camera service from HAL: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return INVALID_OPERATION;
- }
- }
-
- return OK;
-}
-
void removeInFlightMapEntryLocked(CaptureOutputStates& states, int idx) {
ATRACE_CALL();
InFlightRequestMap& inflightMap = states.inflightMap;
@@ -719,153 +682,6 @@
}
}
-void processOneCaptureResultLocked(
- CaptureOutputStates& states,
- const hardware::camera::device::V3_2::CaptureResult& result,
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata) {
- using hardware::camera::device::V3_2::StreamBuffer;
- using hardware::camera::device::V3_2::BufferStatus;
- std::unique_ptr<ResultMetadataQueue>& fmq = states.fmq;
- BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
- camera_capture_result r;
- status_t res;
- r.frame_number = result.frameNumber;
-
- // Read and validate the result metadata.
- hardware::camera::device::V3_2::CameraMetadata resultMetadata;
- res = readOneCameraMetadataLocked(
- fmq, result.fmqResultSize,
- resultMetadata, result.result);
- if (res != OK) {
- ALOGE("%s: Frame %d: Failed to read capture result metadata",
- __FUNCTION__, result.frameNumber);
- return;
- }
- r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
-
- // Read and validate physical camera metadata
- size_t physResultCount = physicalCameraMetadata.size();
- std::vector<const char*> physCamIds(physResultCount);
- std::vector<const camera_metadata_t *> phyCamMetadatas(physResultCount);
- std::vector<hardware::camera::device::V3_2::CameraMetadata> physResultMetadata;
- physResultMetadata.resize(physResultCount);
- for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
- res = readOneCameraMetadataLocked(fmq, physicalCameraMetadata[i].fmqMetadataSize,
- physResultMetadata[i], physicalCameraMetadata[i].metadata);
- if (res != OK) {
- ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
- __FUNCTION__, result.frameNumber,
- physicalCameraMetadata[i].physicalCameraId.c_str());
- return;
- }
- physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
- phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
- physResultMetadata[i].data());
- }
- r.num_physcam_metadata = physResultCount;
- r.physcam_ids = physCamIds.data();
- r.physcam_metadata = phyCamMetadatas.data();
-
- std::vector<camera_stream_buffer_t> outputBuffers(result.outputBuffers.size());
- std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
- for (size_t i = 0; i < result.outputBuffers.size(); i++) {
- auto& bDst = outputBuffers[i];
- const StreamBuffer &bSrc = result.outputBuffers[i];
-
- sp<Camera3StreamInterface> stream = states.outputStreams.get(bSrc.streamId);
- if (stream == nullptr) {
- ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
- __FUNCTION__, result.frameNumber, i, bSrc.streamId);
- return;
- }
- bDst.stream = stream->asHalStream();
-
- bool noBufferReturned = false;
- buffer_handle_t *buffer = nullptr;
- if (states.useHalBufManager) {
- // This is suspicious most of the time but can be correct during flush where HAL
- // has to return capture result before a buffer is requested
- if (bSrc.bufferId == BUFFER_ID_NO_BUFFER) {
- if (bSrc.status == BufferStatus::OK) {
- ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d",
- __FUNCTION__, result.frameNumber, i, bSrc.streamId);
- // Still proceeds so other buffers can be returned
- }
- noBufferReturned = true;
- }
- if (noBufferReturned) {
- res = OK;
- } else {
- res = bufferRecords.popInflightRequestBuffer(bSrc.bufferId, &buffer);
- }
- } else {
- res = bufferRecords.popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
- }
-
- if (res != OK) {
- ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
- __FUNCTION__, result.frameNumber, i, bSrc.streamId);
- return;
- }
-
- bDst.buffer = buffer;
- bDst.status = mapHidlBufferStatus(bSrc.status);
- bDst.acquire_fence = -1;
- if (bSrc.releaseFence == nullptr) {
- bDst.release_fence = -1;
- } else if (bSrc.releaseFence->numFds == 1) {
- if (noBufferReturned) {
- ALOGE("%s: got releaseFence without output buffer!", __FUNCTION__);
- }
- bDst.release_fence = dup(bSrc.releaseFence->data[0]);
- } else {
- ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
- __FUNCTION__, result.frameNumber, i, bSrc.releaseFence->numFds);
- return;
- }
- }
- r.num_output_buffers = outputBuffers.size();
- r.output_buffers = outputBuffers.data();
-
- camera_stream_buffer_t inputBuffer;
- if (result.inputBuffer.streamId == -1) {
- r.input_buffer = nullptr;
- } else {
- if (states.inputStream->getId() != result.inputBuffer.streamId) {
- ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
- result.frameNumber, result.inputBuffer.streamId);
- return;
- }
- inputBuffer.stream = states.inputStream->asHalStream();
- buffer_handle_t *buffer;
- res = bufferRecords.popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
- &buffer);
- if (res != OK) {
- ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
- __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
- return;
- }
- inputBuffer.buffer = buffer;
- inputBuffer.status = mapHidlBufferStatus(result.inputBuffer.status);
- inputBuffer.acquire_fence = -1;
- if (result.inputBuffer.releaseFence == nullptr) {
- inputBuffer.release_fence = -1;
- } else if (result.inputBuffer.releaseFence->numFds == 1) {
- inputBuffer.release_fence = dup(result.inputBuffer.releaseFence->data[0]);
- } else {
- ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
- __FUNCTION__, result.frameNumber, result.inputBuffer.releaseFence->numFds);
- return;
- }
- r.input_buffer = &inputBuffer;
- }
-
- r.partial_result = result.partialResult;
-
- processCaptureResult(states, &r);
-}
-
void returnOutputBuffers(
bool useHalBufManager,
sp<NotificationListener> listener,
@@ -1194,330 +1010,6 @@
}
}
-void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_8::NotifyMsg& msg) {
- using android::hardware::camera::device::V3_2::MsgType;
-
- hardware::camera::device::V3_2::NotifyMsg msg_3_2;
- msg_3_2.type = msg.type;
- bool hasReadoutTime = false;
- uint64_t readoutTime = 0;
- switch (msg.type) {
- case MsgType::ERROR:
- msg_3_2.msg.error = msg.msg.error;
- break;
- case MsgType::SHUTTER:
- msg_3_2.msg.shutter = msg.msg.shutter.v3_2;
- hasReadoutTime = true;
- readoutTime = msg.msg.shutter.readoutTimestamp;
- break;
- }
- notify(states, msg_3_2, hasReadoutTime, readoutTime);
-}
-
-void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_2::NotifyMsg& msg,
- bool hasReadoutTime, uint64_t readoutTime) {
-
- using android::hardware::camera::device::V3_2::MsgType;
- using android::hardware::camera::device::V3_2::ErrorCode;
-
- ATRACE_CALL();
- camera_notify_msg m;
- switch (msg.type) {
- case MsgType::ERROR:
- m.type = CAMERA_MSG_ERROR;
- m.message.error.frame_number = msg.msg.error.frameNumber;
- if (msg.msg.error.errorStreamId >= 0) {
- sp<Camera3StreamInterface> stream =
- states.outputStreams.get(msg.msg.error.errorStreamId);
- if (stream == nullptr) {
- ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
- m.message.error.frame_number, msg.msg.error.errorStreamId);
- return;
- }
- m.message.error.error_stream = stream->asHalStream();
- } else {
- m.message.error.error_stream = nullptr;
- }
- switch (msg.msg.error.errorCode) {
- case ErrorCode::ERROR_DEVICE:
- m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
- break;
- case ErrorCode::ERROR_REQUEST:
- m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
- break;
- case ErrorCode::ERROR_RESULT:
- m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
- break;
- case ErrorCode::ERROR_BUFFER:
- m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
- break;
- }
- break;
- case MsgType::SHUTTER:
- m.type = CAMERA_MSG_SHUTTER;
- m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
- m.message.shutter.timestamp = msg.msg.shutter.timestamp;
- m.message.shutter.readout_timestamp = hasReadoutTime ?
- readoutTime : m.message.shutter.timestamp;
- break;
- }
- notify(states, &m);
-}
-
-// The buffers requested through this call are not tied to any CaptureRequest in
-// particular. They may used by the hal for a particular frame's output buffer
-// or for its internal use as well. In the case that the hal does use any buffer
-// from the requested list here, for a particular frame's output buffer, the
-// buffer will be returned with the processCaptureResult call corresponding to
-// the frame. The other buffers will be returned through returnStreamBuffers.
-// The buffers returned via returnStreamBuffers will not have a valid
-// timestamp(0) and will be dropped by the bufferqueue.
-void requestStreamBuffers(RequestBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb) {
- using android::hardware::camera::device::V3_2::BufferStatus;
- using android::hardware::camera::device::V3_2::StreamBuffer;
- using android::hardware::camera::device::V3_5::BufferRequestStatus;
- using android::hardware::camera::device::V3_5::StreamBufferRet;
- using android::hardware::camera::device::V3_5::StreamBufferRequestError;
-
- std::lock_guard<std::mutex> lock(states.reqBufferLock);
-
- hardware::hidl_vec<StreamBufferRet> bufRets;
- if (!states.useHalBufManager) {
- ALOGE("%s: Camera %s does not support HAL buffer management",
- __FUNCTION__, states.cameraId.string());
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
-
- SortedVector<int32_t> streamIds;
- ssize_t sz = streamIds.setCapacity(bufReqs.size());
- if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
- ALOGE("%s: failed to allocate memory for %zu buffer requests",
- __FUNCTION__, bufReqs.size());
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
-
- if (bufReqs.size() > states.outputStreams.size()) {
- ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
- __FUNCTION__, bufReqs.size(), states.outputStreams.size());
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
-
- // Check for repeated streamId
- for (const auto& bufReq : bufReqs) {
- if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d appear multiple times in buffer requests",
- __FUNCTION__, bufReq.streamId);
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
- streamIds.add(bufReq.streamId);
- }
-
- if (!states.reqBufferIntf.startRequestBuffer()) {
- ALOGE("%s: request buffer disallowed while camera service is configuring",
- __FUNCTION__);
- _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
- return;
- }
-
- bufRets.resize(bufReqs.size());
-
- bool allReqsSucceeds = true;
- bool oneReqSucceeds = false;
- for (size_t i = 0; i < bufReqs.size(); i++) {
- const auto& bufReq = bufReqs[i];
- auto& bufRet = bufRets[i];
- int32_t streamId = bufReq.streamId;
- sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
- if (outputStream == nullptr) {
- ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
- hardware::hidl_vec<StreamBufferRet> emptyBufRets;
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
- states.reqBufferIntf.endRequestBuffer();
- return;
- }
-
- bufRet.streamId = streamId;
- if (outputStream->isAbandoned()) {
- bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
- allReqsSucceeds = false;
- continue;
- }
-
- size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
- uint32_t numBuffersRequested = bufReq.numBuffersRequested;
- size_t totalHandout = handOutBufferCount + numBuffersRequested;
- uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
- if (totalHandout > maxBuffers) {
- // Not able to allocate enough buffer. Exit early for this stream
- ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
- " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
- numBuffersRequested, maxBuffers);
- bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
- allReqsSucceeds = false;
- continue;
- }
-
- hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
- bool currentReqSucceeds = true;
- std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
- std::vector<buffer_handle_t> newBuffers;
- size_t numAllocatedBuffers = 0;
- size_t numPushedInflightBuffers = 0;
- for (size_t b = 0; b < numBuffersRequested; b++) {
- camera_stream_buffer_t& sb = streamBuffers[b];
- // Since this method can run concurrently with request thread
- // We need to update the wait duration everytime we call getbuffer
- nsecs_t waitDuration = states.reqBufferIntf.getWaitDuration();
- status_t res = outputStream->getBuffer(&sb, waitDuration);
- if (res != OK) {
- if (res == NO_INIT || res == DEAD_OBJECT) {
- ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
- states.sessionStatsBuilder.stopCounter(streamId);
- } else {
- ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- if (res == TIMED_OUT || res == NO_MEMORY) {
- bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
- } else {
- bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
- }
- }
- currentReqSucceeds = false;
- break;
- }
- numAllocatedBuffers++;
-
- buffer_handle_t *buffer = sb.buffer;
- auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
- bool isNewBuffer = pair.first;
- uint64_t bufferId = pair.second;
- StreamBuffer& hBuf = tmpRetBuffers[b];
-
- hBuf.streamId = streamId;
- hBuf.bufferId = bufferId;
- hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
- hBuf.status = BufferStatus::OK;
- hBuf.releaseFence = nullptr;
- if (isNewBuffer) {
- newBuffers.push_back(*buffer);
- }
-
- native_handle_t *acquireFence = nullptr;
- if (sb.acquire_fence != -1) {
- acquireFence = native_handle_create(1,0);
- acquireFence->data[0] = sb.acquire_fence;
- }
- hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
- hBuf.releaseFence = nullptr;
-
- res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
- if (res != OK) {
- ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
- currentReqSucceeds = false;
- break;
- }
- numPushedInflightBuffers++;
- }
- if (currentReqSucceeds) {
- bufRet.val.buffers(std::move(tmpRetBuffers));
- oneReqSucceeds = true;
- } else {
- allReqsSucceeds = false;
- for (size_t b = 0; b < numPushedInflightBuffers; b++) {
- StreamBuffer& hBuf = tmpRetBuffers[b];
- buffer_handle_t* buffer;
- status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
- hBuf.bufferId, &buffer);
- if (res != OK) {
- SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- }
- }
- for (size_t b = 0; b < numAllocatedBuffers; b++) {
- camera_stream_buffer_t& sb = streamBuffers[b];
- sb.acquire_fence = -1;
- sb.status = CAMERA_BUFFER_STATUS_ERROR;
- }
- returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
- streamBuffers.data(), numAllocatedBuffers, /*timestamp*/0,
- /*readoutTimestamp*/0, /*requested*/false,
- /*requestTimeNs*/0, states.sessionStatsBuilder);
- for (auto buf : newBuffers) {
- states.bufferRecordsIntf.removeOneBufferCache(streamId, buf);
- }
- }
- }
-
- _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
- oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
- BufferRequestStatus::FAILED_UNKNOWN,
- bufRets);
- states.reqBufferIntf.endRequestBuffer();
-}
-
-void returnStreamBuffers(ReturnBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
- if (!states.useHalBufManager) {
- ALOGE("%s: Camera %s does not support HAL buffer managerment",
- __FUNCTION__, states.cameraId.string());
- return;
- }
-
- for (const auto& buf : buffers) {
- if (buf.bufferId == BUFFER_ID_NO_BUFFER) {
- ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__);
- continue;
- }
-
- buffer_handle_t* buffer;
- status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(buf.bufferId, &buffer);
-
- if (res != OK) {
- ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d",
- __FUNCTION__, buf.bufferId, buf.streamId);
- continue;
- }
-
- camera_stream_buffer_t streamBuffer;
- streamBuffer.buffer = buffer;
- streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
- streamBuffer.acquire_fence = -1;
- streamBuffer.release_fence = -1;
-
- if (buf.releaseFence == nullptr) {
- streamBuffer.release_fence = -1;
- } else if (buf.releaseFence->numFds == 1) {
- streamBuffer.release_fence = dup(buf.releaseFence->data[0]);
- } else {
- ALOGE("%s: Invalid release fence, fd count is %d, not 1",
- __FUNCTION__, buf.releaseFence->numFds);
- continue;
- }
-
- sp<Camera3StreamInterface> stream = states.outputStreams.get(buf.streamId);
- if (stream == nullptr) {
- ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId);
- continue;
- }
- streamBuffer.stream = stream->asHalStream();
- returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
- &streamBuffer, /*size*/1, /*timestamp*/ 0, /*readoutTimestamp*/0,
- /*requested*/false, /*requestTimeNs*/0, states.sessionStatsBuilder);
- }
-}
-
void flushInflightRequests(FlushInflightReqStates& states) {
ATRACE_CALL();
{ // First return buffers cached in inFlightMap
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 51899ee..4d1eb75 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -40,8 +40,6 @@
namespace android {
-using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-
namespace camera3 {
/**
@@ -97,7 +95,6 @@
const metadata_vendor_id_t vendorTagId;
const CameraMetadata& deviceInfo;
const std::unordered_map<std::string, CameraMetadata>& physicalDeviceInfoMap;
- std::unique_ptr<ResultMetadataQueue>& fmq;
std::unordered_map<std::string, camera3::DistortionMapper>& distortionMappers;
std::unordered_map<std::string, camera3::ZoomRatioMapper>& zoomRatioMappers;
std::unordered_map<std::string, camera3::RotateAndCropMapper>& rotateAndCropMappers;
@@ -112,20 +109,8 @@
bool legacyClient;
};
- // Handle one capture result. Assume callers hold the lock to serialize all
- // processCaptureResult calls
- void processOneCaptureResultLocked(
- CaptureOutputStates& states,
- const hardware::camera::device::V3_2::CaptureResult& result,
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata);
-
- // Handle one notify message
- void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_2::NotifyMsg& msg,
- bool hasReadoutTime = false, uint64_t readoutTime = 0LL);
- void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_8::NotifyMsg& msg);
+ void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result);
+ void notify(CaptureOutputStates& states, const camera_notify_msg *msg);
struct RequestBufferStates {
const String8& cameraId;
@@ -138,10 +123,6 @@
RequestBufferInterface& reqBufferIntf;
};
- void requestStreamBuffers(RequestBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb);
-
struct ReturnBufferStates {
const String8& cameraId;
const bool useHalBufManager;
@@ -150,9 +131,6 @@
BufferRecordsInterface& bufferRecordsIntf;
};
- void returnStreamBuffers(ReturnBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers);
-
struct FlushInflightReqStates {
const String8& cameraId;
std::mutex& inflightLock;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
new file mode 100644
index 0000000..7dc8e10
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
@@ -0,0 +1,335 @@
+/*
+ * 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 ANDROID_SERVERS_CAMERA3_OUTPUT_TEMPLUTILS_H
+#define ANDROID_SERVERS_CAMERA3_OUTPUT_TEMPLUTILS_H
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+
+#include <aidl/android/hardware/common/NativeHandle.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+
+#include <camera/CameraUtils.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/Camera3OutputUtils.h"
+
+#include "system/camera_metadata.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+namespace camera3 {
+
+template <class BufferStatusType>
+camera_buffer_status_t mapBufferStatus(BufferStatusType status) {
+ switch (status) {
+ case BufferStatusType::OK: return CAMERA_BUFFER_STATUS_OK;
+ case BufferStatusType::ERROR: return CAMERA_BUFFER_STATUS_ERROR;
+ }
+ return CAMERA_BUFFER_STATUS_ERROR;
+}
+
+inline void readBufferFromVec(hardware::hidl_vec<uint8_t> &dst,
+ const hardware::hidl_vec<uint8_t> &src) {
+ // Not cloning here since that will be done in processCaptureResult whil
+ // assigning to CameraMetadata.
+ dst.setToExternal(const_cast<uint8_t *>(src.data()), src.size());
+}
+
+inline void readBufferFromVec(std::vector<uint8_t> &dst, const std::vector<uint8_t> &src) {
+ // TODO: Check if we're really supposed to copy
+ dst = src;
+}
+// Reading one camera metadata from result argument via fmq or from the result
+// Assuming the fmq is protected by a lock already
+template <class FmqType, class MetadataType>
+status_t readOneCameraMetadataLockedT(
+ std::unique_ptr<FmqType>& fmq,
+ uint64_t fmqResultSize,
+ MetadataType& resultMetadata,
+ const MetadataType& result) {
+ if (fmqResultSize > 0) {
+ resultMetadata.resize(fmqResultSize);
+ if (fmq == nullptr) {
+ return NO_MEMORY; // logged in initialize()
+ }
+ if (!fmq->read(resultMetadata.data(), fmqResultSize)) {
+ ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
+ __FUNCTION__, fmqResultSize);
+ return INVALID_OPERATION;
+ }
+ } else {
+ readBufferFromVec(resultMetadata, result);
+ }
+
+ if (resultMetadata.size() != 0) {
+ status_t res;
+ const camera_metadata_t* metadata =
+ reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+ size_t expected_metadata_size = resultMetadata.size();
+ if ((res = validate_camera_metadata_structure(metadata, &expected_metadata_size)) != OK) {
+ ALOGE("%s: Invalid camera metadata received by camera service from HAL: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return INVALID_OPERATION;
+ }
+ }
+
+ return OK;
+}
+
+inline bool isHandleNull(const hardware::hidl_handle &handle) {
+ return handle == nullptr;
+}
+
+inline bool isHandleNull(const aidl::android::hardware::common::NativeHandle &handle) {
+ return (handle.fds.size() == 0) && (handle.ints.size() == 0);
+}
+
+inline size_t numFdsInHandle(const hardware::hidl_handle &handle) {
+ return handle->numFds;
+}
+
+inline size_t numFdsInHandle(const aidl::android::hardware::common::NativeHandle &handle) {
+ return handle.fds.size();
+}
+
+inline int32_t getHandleFirstFd(const hardware::hidl_handle &handle) {
+ if (handle->numFds != 1) {
+ return -1;
+ }
+ return handle->data[0];
+}
+
+inline int32_t getHandleFirstFd(const aidl::android::hardware::common::NativeHandle &handle) {
+ if (handle.fds.size() != 1) {
+ return -1;
+ }
+ return handle.fds[0].get();
+}
+
+template <class StatesType, class CaptureResultType, class PhysMetadataType, class MetadataType,
+ class FmqType, class BufferStatusType>
+void processOneCaptureResultLockedT(
+ StatesType& states,
+ const CaptureResultType& result,
+ const PhysMetadataType &physicalCameraMetadata) {
+ std::unique_ptr<FmqType>& fmq = states.fmq;
+ BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
+ camera_capture_result r;
+ status_t res;
+ r.frame_number = result.frameNumber;
+
+ // Read and validate the result metadata.
+ MetadataType resultMetadata;
+ res = readOneCameraMetadataLockedT(
+ fmq, result.fmqResultSize,
+ resultMetadata, result.result);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Failed to read capture result metadata",
+ __FUNCTION__, result.frameNumber);
+ return;
+ }
+ r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+
+ // Read and validate physical camera metadata
+ size_t physResultCount = physicalCameraMetadata.size();
+ std::vector<const char*> physCamIds(physResultCount);
+ std::vector<const camera_metadata_t *> phyCamMetadatas(physResultCount);
+ std::vector<MetadataType> physResultMetadata;
+ physResultMetadata.resize(physResultCount);
+ for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
+ res = readOneCameraMetadataLockedT(fmq, physicalCameraMetadata[i].fmqMetadataSize,
+ physResultMetadata[i], physicalCameraMetadata[i].metadata);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
+ __FUNCTION__, result.frameNumber,
+ physicalCameraMetadata[i].physicalCameraId.c_str());
+ return;
+ }
+ physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
+ phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
+ physResultMetadata[i].data());
+ }
+ r.num_physcam_metadata = physResultCount;
+ r.physcam_ids = physCamIds.data();
+ r.physcam_metadata = phyCamMetadatas.data();
+
+ std::vector<camera_stream_buffer_t> outputBuffers(result.outputBuffers.size());
+ std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
+ for (size_t i = 0; i < result.outputBuffers.size(); i++) {
+ auto& bDst = outputBuffers[i];
+ const auto &bSrc = result.outputBuffers[i];
+
+ sp<Camera3StreamInterface> stream = states.outputStreams.get(bSrc.streamId);
+ if (stream == nullptr) {
+ ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
+ __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+ return;
+ }
+ bDst.stream = stream->asHalStream();
+
+ bool noBufferReturned = false;
+ buffer_handle_t *buffer = nullptr;
+ if (states.useHalBufManager) {
+ // This is suspicious most of the time but can be correct during flush where HAL
+ // has to return capture result before a buffer is requested
+ if (bSrc.bufferId == BUFFER_ID_NO_BUFFER) {
+ if (bSrc.status == BufferStatusType::OK) {
+ ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d",
+ __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+ // Still proceeds so other buffers can be returned
+ }
+ noBufferReturned = true;
+ }
+ if (noBufferReturned) {
+ res = OK;
+ } else {
+ res = bufferRecords.popInflightRequestBuffer(bSrc.bufferId, &buffer);
+ }
+ } else {
+ res = bufferRecords.popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
+ }
+
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
+ __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+ return;
+ }
+
+ bDst.buffer = buffer;
+ bDst.status = mapBufferStatus<BufferStatusType>(bSrc.status);
+ bDst.acquire_fence = -1;
+ if (isHandleNull(bSrc.releaseFence)) {
+ bDst.release_fence = -1;
+ } else if (numFdsInHandle(bSrc.releaseFence) == 1) {
+ if (noBufferReturned) {
+ ALOGE("%s: got releaseFence without output buffer!", __FUNCTION__);
+ }
+ bDst.release_fence = dup(getHandleFirstFd(bSrc.releaseFence));
+ } else {
+ ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
+ __FUNCTION__, result.frameNumber, i, (int)numFdsInHandle(bSrc.releaseFence));
+ return;
+ }
+ }
+ r.num_output_buffers = outputBuffers.size();
+ r.output_buffers = outputBuffers.data();
+
+ camera_stream_buffer_t inputBuffer;
+ if (result.inputBuffer.streamId == -1) {
+ r.input_buffer = nullptr;
+ } else {
+ if (states.inputStream->getId() != result.inputBuffer.streamId) {
+ ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
+ result.frameNumber, result.inputBuffer.streamId);
+ return;
+ }
+ inputBuffer.stream = states.inputStream->asHalStream();
+ buffer_handle_t *buffer;
+ res = bufferRecords.popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
+ &buffer);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
+ __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
+ return;
+ }
+ inputBuffer.buffer = buffer;
+ inputBuffer.status = mapBufferStatus<BufferStatusType>(result.inputBuffer.status);
+ inputBuffer.acquire_fence = -1;
+ if (isHandleNull(result.inputBuffer.releaseFence)) {
+ inputBuffer.release_fence = -1;
+ } else if (numFdsInHandle(result.inputBuffer.releaseFence) == 1) {
+ inputBuffer.release_fence = dup(getHandleFirstFd(result.inputBuffer.releaseFence));
+ } else {
+ ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
+ __FUNCTION__, result.frameNumber,
+ (int)numFdsInHandle(result.inputBuffer.releaseFence));
+ return;
+ }
+ r.input_buffer = &inputBuffer;
+ }
+
+ r.partial_result = result.partialResult;
+
+ processCaptureResult(states, &r);
+}
+
+template <class VecStreamBufferType>
+void returnStreamBuffersT(ReturnBufferStates& states,
+ const VecStreamBufferType& buffers) {
+ if (!states.useHalBufManager) {
+ ALOGE("%s: Camera %s does not support HAL buffer managerment",
+ __FUNCTION__, states.cameraId.string());
+ return;
+ }
+
+ for (const auto& buf : buffers) {
+ if (buf.bufferId == BUFFER_ID_NO_BUFFER) {
+ ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__);
+ continue;
+ }
+
+ buffer_handle_t* buffer;
+ status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(buf.bufferId, &buffer);
+
+ if (res != OK) {
+ ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d",
+ __FUNCTION__, buf.bufferId, buf.streamId);
+ continue;
+ }
+
+ camera_stream_buffer_t streamBuffer;
+ streamBuffer.buffer = buffer;
+ streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
+ streamBuffer.acquire_fence = -1;
+ streamBuffer.release_fence = -1;
+
+ if (isHandleNull(buf.releaseFence)) {
+ streamBuffer.release_fence = -1;
+ } else if (numFdsInHandle(buf.releaseFence) == 1) {
+ streamBuffer.release_fence = dup(getHandleFirstFd(buf.releaseFence));
+ } else {
+ ALOGE("%s: Invalid release fence, fd count is %d, not 1",
+ __FUNCTION__, (int)numFdsInHandle(buf.releaseFence));
+ continue;
+ }
+
+ sp<Camera3StreamInterface> stream = states.outputStreams.get(buf.streamId);
+ if (stream == nullptr) {
+ ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId);
+ continue;
+ }
+ streamBuffer.stream = stream->asHalStream();
+ returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
+ &streamBuffer, /*size*/1, /*timestamp*/ 0, /*readoutTimestamp*/0,
+ /*requested*/false, /*requestTimeNs*/0, states.sessionStatsBuilder);
+ }
+}
+
+} // camera3
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
new file mode 100644
index 0000000..7b7a2a2
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -0,0 +1,1893 @@
+/*
+ * 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 "HidlCamera3-Device"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0 // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+ ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+
+#include <inttypes.h>
+
+#include <utility>
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <utils/Timers.h>
+#include <cutils/properties.h>
+
+#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+
+#include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/hidl/HidlCamera3OfflineSession.h"
+#include "utils/SessionConfigurationUtils.h"
+#include "utils/TraceHFR.h"
+
+#include "../../common/hidl/HidlProviderInfo.h"
+#include "HidlCamera3Device.h"
+
+#include <algorithm>
+#include <tuple>
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+using namespace android::hardware::camera::device::V3_2;
+using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
+
+namespace android {
+
+CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap
+HidlCamera3Device::mapToHidlDynamicProfile(int dynamicRangeProfile) {
+ return static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>(
+ dynamicRangeProfile);
+}
+
+hardware::graphics::common::V1_0::PixelFormat HidlCamera3Device::mapToPixelFormat(
+ int frameworkFormat) {
+ return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
+}
+
+DataspaceFlags HidlCamera3Device::mapToHidlDataspace(
+ android_dataspace dataSpace) {
+ return dataSpace;
+}
+
+BufferUsageFlags HidlCamera3Device::mapToConsumerUsage(
+ uint64_t usage) {
+ return usage;
+}
+
+StreamRotation HidlCamera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
+ switch (rotation) {
+ case CAMERA_STREAM_ROTATION_0:
+ return StreamRotation::ROTATION_0;
+ case CAMERA_STREAM_ROTATION_90:
+ return StreamRotation::ROTATION_90;
+ case CAMERA_STREAM_ROTATION_180:
+ return StreamRotation::ROTATION_180;
+ case CAMERA_STREAM_ROTATION_270:
+ return StreamRotation::ROTATION_270;
+ }
+ ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
+ return StreamRotation::ROTATION_0;
+}
+
+status_t HidlCamera3Device::mapToStreamConfigurationMode(
+ camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
+ if (mode == nullptr) return BAD_VALUE;
+ if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+ switch(operationMode) {
+ case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
+ *mode = StreamConfigurationMode::NORMAL_MODE;
+ break;
+ case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+ *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
+ break;
+ default:
+ ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
+ return BAD_VALUE;
+ }
+ } else {
+ *mode = static_cast<StreamConfigurationMode>(operationMode);
+ }
+ return OK;
+}
+
+int HidlCamera3Device::mapToFrameworkFormat(
+ hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
+ return static_cast<uint32_t>(pixelFormat);
+}
+
+android_dataspace HidlCamera3Device::mapToFrameworkDataspace(
+ DataspaceFlags dataSpace) {
+ return static_cast<android_dataspace>(dataSpace);
+}
+
+uint64_t HidlCamera3Device::mapConsumerToFrameworkUsage(
+ BufferUsageFlags usage) {
+ return usage;
+}
+
+uint64_t HidlCamera3Device::mapProducerToFrameworkUsage(
+ BufferUsageFlags usage) {
+ return usage;
+}
+
+status_t HidlCamera3Device::initialize(sp<CameraProviderManager> manager,
+ const String8& monitorTags) {
+ ATRACE_CALL();
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
+ if (mStatus != STATUS_UNINITIALIZED) {
+ CLOGE("Already initialized!");
+ return INVALID_OPERATION;
+ }
+ if (manager == nullptr) return INVALID_OPERATION;
+
+ sp<ICameraDeviceSession> session;
+ ATRACE_BEGIN("CameraHal::openSession");
+ status_t res = manager->openHidlSession(mId.string(), this,
+ /*out*/ &session);
+ ATRACE_END();
+ if (res != OK) {
+ SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
+ return res;
+ }
+
+ res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo);
+ if (res != OK) {
+ SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
+ session->close();
+ return res;
+ }
+ mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
+
+ std::vector<std::string> physicalCameraIds;
+ bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
+ if (isLogical) {
+ for (auto& physicalId : physicalCameraIds) {
+ // Do not override characteristics for physical cameras
+ res = manager->getCameraCharacteristics(
+ physicalId, /*overrideForPerfClass*/false, &mPhysicalDeviceInfoMap[physicalId]);
+ if (res != OK) {
+ SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
+ physicalId.c_str(), strerror(-res), res);
+ session->close();
+ return res;
+ }
+
+ bool usePrecorrectArray =
+ DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
+ if (usePrecorrectArray) {
+ res = mDistortionMappers[physicalId].setupStaticInfo(
+ mPhysicalDeviceInfoMap[physicalId]);
+ if (res != OK) {
+ SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
+ "correction", physicalId.c_str());
+ session->close();
+ return res;
+ }
+ }
+
+ mZoomRatioMappers[physicalId] = ZoomRatioMapper(
+ &mPhysicalDeviceInfoMap[physicalId],
+ mSupportNativeZoomRatio, usePrecorrectArray);
+
+ if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+ mPhysicalDeviceInfoMap[physicalId])) {
+ mUHRCropAndMeteringRegionMappers[physicalId] =
+ UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
+ usePrecorrectArray);
+ }
+ }
+ }
+
+ std::shared_ptr<RequestMetadataQueue> queue;
+ auto requestQueueRet = session->getCaptureRequestMetadataQueue(
+ [&queue](const auto& descriptor) {
+ queue = std::make_shared<RequestMetadataQueue>(descriptor);
+ if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty request metadata fmq, not use it");
+ queue = nullptr;
+ // don't use the queue onwards.
+ }
+ });
+ if (!requestQueueRet.isOk()) {
+ ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
+ requestQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
+ auto resultQueueRet = session->getCaptureResultMetadataQueue(
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty result metadata fmq, not use it");
+ resQueue = nullptr;
+ // Don't use the resQueue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+ resultQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+ IF_ALOGV() {
+ session->interfaceChain([](
+ ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Session interface chain:");
+ for (const auto& iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+
+ camera_metadata_entry bufMgrMode =
+ mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+ if (bufMgrMode.count > 0) {
+ mUseHalBufManager = (bufMgrMode.data.u8[0] ==
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+ }
+
+ camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ for (size_t i = 0; i < capabilities.count; i++) {
+ uint8_t capability = capabilities.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
+ mSupportOfflineProcessing = true;
+ }
+ }
+
+ mInterface = new HidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
+
+ std::string providerType;
+ mVendorTagId = manager->getProviderTagIdLocked(mId.string());
+ mTagMonitor.initialize(mVendorTagId);
+ if (!monitorTags.isEmpty()) {
+ mTagMonitor.parseTagsToMonitor(String8(monitorTags));
+ }
+
+ // Metadata tags needs fixup for monochrome camera device version less
+ // than 3.5.
+ hardware::hidl_version maxVersion{0,0};
+ res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
+ if (res != OK) {
+ ALOGE("%s: Error in getting camera device version id: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ int deviceVersion = HARDWARE_DEVICE_API_VERSION(
+ maxVersion.get_major(), maxVersion.get_minor());
+
+ bool isMonochrome = false;
+ for (size_t i = 0; i < capabilities.count; i++) {
+ uint8_t capability = capabilities.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
+ isMonochrome = true;
+ }
+ }
+ mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
+
+ return initializeCommonLocked();
+}
+
+hardware::Return<void> HidlCamera3Device::requestStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) {
+ RequestBufferStates states {
+ mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
+ *this, *mInterface, *this};
+ camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3Device::returnStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+ ReturnBufferStates states {
+ mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, *mInterface};
+ camera3::returnStreamBuffers(states, buffers);
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3Device::processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) {
+ // Ideally we should grab mLock, but that can lead to deadlock, and
+ // it's not super important to get up to date value of mStatus for this
+ // warning print, hence skipping the lock here
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ // But mStatus can be set to error by framework as well, so just log
+ // a warning here.
+ ALOGW("%s: received capture result in error state.", __FUNCTION__);
+ }
+
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> l(mOutputLock);
+ listener = mListener.promote();
+ }
+
+ if (mProcessCaptureResultLock.tryLock() != OK) {
+ // This should never happen; it indicates a wrong client implementation
+ // that doesn't follow the contract. But, we can be tolerant here.
+ ALOGE("%s: callback overlapped! waiting 1s...",
+ __FUNCTION__);
+ if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+ ALOGE("%s: cannot acquire lock in 1s, dropping results",
+ __FUNCTION__);
+ // really don't know what to do, so bail out.
+ return hardware::Void();
+ }
+ }
+ HidlCaptureOutputStates states {
+ {
+ mId,
+ mInFlightLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ *mInterface, mLegacyClient}, mResultMetadataQueue
+ };
+
+ //HidlCaptureOutputStates hidlStates {
+ //}
+
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
+ }
+ mProcessCaptureResultLock.unlock();
+ return hardware::Void();
+}
+
+// Only one processCaptureResult should be called at a time, so
+// the locks won't block. The locks are present here simply to enforce this.
+hardware::Return<void> HidlCamera3Device::processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) {
+ hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
+
+ // Ideally we should grab mLock, but that can lead to deadlock, and
+ // it's not super important to get up to date value of mStatus for this
+ // warning print, hence skipping the lock here
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ // But mStatus can be set to error by framework as well, so just log
+ // a warning here.
+ ALOGW("%s: received capture result in error state.", __FUNCTION__);
+ }
+
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> l(mOutputLock);
+ listener = mListener.promote();
+ }
+
+ if (mProcessCaptureResultLock.tryLock() != OK) {
+ // This should never happen; it indicates a wrong client implementation
+ // that doesn't follow the contract. But, we can be tolerant here.
+ ALOGE("%s: callback overlapped! waiting 1s...",
+ __FUNCTION__);
+ if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+ ALOGE("%s: cannot acquire lock in 1s, dropping results",
+ __FUNCTION__);
+ // really don't know what to do, so bail out.
+ return hardware::Void();
+ }
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mInFlightLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ *mInterface, mLegacyClient}, mResultMetadataQueue
+ };
+
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result, noPhysMetadata);
+ }
+ mProcessCaptureResultLock.unlock();
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3Device::notify(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
+ return notifyHelper<hardware::camera::device::V3_2::NotifyMsg>(msgs);
+}
+
+hardware::Return<void> HidlCamera3Device::notify_3_8(
+ const hardware::hidl_vec<hardware::camera::device::V3_8::NotifyMsg>& msgs) {
+ return notifyHelper<hardware::camera::device::V3_8::NotifyMsg>(msgs);
+}
+
+template<typename NotifyMsgType>
+hardware::Return<void> HidlCamera3Device::notifyHelper(
+ const hardware::hidl_vec<NotifyMsgType>& msgs) {
+ // Ideally we should grab mLock, but that can lead to deadlock, and
+ // it's not super important to get up to date value of mStatus for this
+ // warning print, hence skipping the lock here
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ // But mStatus can be set to error by framework as well, so just log
+ // a warning here.
+ ALOGW("%s: received notify message in error state.", __FUNCTION__);
+ }
+
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> l(mOutputLock);
+ listener = mListener.promote();
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mInFlightLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ *mInterface, mLegacyClient}, mResultMetadataQueue
+ };
+ for (const auto& msg : msgs) {
+ camera3::notify(states, msg);
+ }
+ return hardware::Void();
+}
+
+status_t HidlCamera3Device::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) {
+ ATRACE_CALL();
+ if (session == nullptr) {
+ ALOGE("%s: session must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock il(mInterfaceLock);
+
+ bool hasInputStream = mInputStream != nullptr;
+ int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
+ bool inputStreamSupportsOffline = hasInputStream ?
+ mInputStream->getOfflineProcessingSupport() : false;
+ auto outputStreamIds = mOutputStreams.getStreamIds();
+ auto streamIds = outputStreamIds;
+ if (hasInputStream) {
+ streamIds.push_back(mInputStream->getId());
+ }
+
+ // Check all streams in streamsToKeep supports offline mode
+ for (auto id : streamsToKeep) {
+ if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+ ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
+ return BAD_VALUE;
+ } else if (id == inputStreamId) {
+ if (!inputStreamSupportsOffline) {
+ ALOGE("%s: input stream %d cannot be switched to offline",
+ __FUNCTION__, id);
+ return BAD_VALUE;
+ }
+ } else {
+ sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
+ if (!stream->getOfflineProcessingSupport()) {
+ ALOGE("%s: output stream %d cannot be switched to offline",
+ __FUNCTION__, id);
+ return BAD_VALUE;
+ }
+ }
+ }
+ // TODO: block surface sharing and surface group streams until we can support them
+
+ // Stop repeating request, wait until all remaining requests are submitted, then call into
+ // HAL switchToOffline
+ hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
+ camera3::BufferRecords bufferRecords;
+ status_t ret = static_cast<HidlRequestThread *>(mRequestThread.get())->switchToOffline(
+ streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
+
+ if (ret != OK) {
+ SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
+ return ret;
+ }
+
+ bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
+ if (!succ) {
+ SET_ERR("HAL must not be calling requestStreamBuffers call");
+ // TODO: block ALL callbacks from HAL till app configured new streams?
+ return UNKNOWN_ERROR;
+ }
+
+ // Verify offlineSessionInfo
+ std::vector<int32_t> offlineStreamIds;
+ offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
+ for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+ // verify stream IDs
+ int32_t id = offlineStream.id;
+ if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+ SET_ERR("stream ID %d not found!", id);
+ return UNKNOWN_ERROR;
+ }
+
+ // When not using HAL buf manager, only allow streams requested by app to be preserved
+ if (!mUseHalBufManager) {
+ if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
+ SET_ERR("stream ID %d must not be switched to offline!", id);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ offlineStreamIds.push_back(id);
+ sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
+ static_cast<sp<Camera3StreamInterface>>(mInputStream) :
+ static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
+ // Verify number of outstanding buffers
+ if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
+ SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
+ id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ // Verify all streams to be deleted don't have any outstanding buffers
+ if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+ inputStreamId) == offlineStreamIds.end()) {
+ if (mInputStream->hasOutstandingBuffers()) {
+ SET_ERR("Input stream %d still has %zu outstanding buffer!",
+ inputStreamId, mInputStream->getOutstandingBuffersCount());
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ for (const auto& outStreamId : outputStreamIds) {
+ if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+ outStreamId) == offlineStreamIds.end()) {
+ auto outStream = mOutputStreams.get(outStreamId);
+ if (outStream->hasOutstandingBuffers()) {
+ SET_ERR("Output stream %d still has %zu outstanding buffer!",
+ outStreamId, outStream->getOutstandingBuffersCount());
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ InFlightRequestMap offlineReqs;
+ // Verify inflight requests and their pending buffers
+ {
+ std::lock_guard<std::mutex> l(mInFlightLock);
+ for (auto offlineReq : offlineSessionInfo.offlineRequests) {
+ int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
+ if (idx == NAME_NOT_FOUND) {
+ SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
+ return UNKNOWN_ERROR;
+ }
+
+ const auto& inflightReq = mInFlightMap.valueAt(idx);
+ // TODO: check specific stream IDs
+ size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
+ if (numBuffersLeft != offlineReq.pendingStreams.size()) {
+ SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
+ inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
+ return UNKNOWN_ERROR;
+ }
+ offlineReqs.add(offlineReq.frameNumber, inflightReq);
+ }
+ }
+
+ // Create Camera3OfflineSession and transfer object ownership
+ // (streams, inflight requests, buffer caches)
+ camera3::StreamSet offlineStreamSet;
+ sp<camera3::Camera3Stream> inputStream;
+ for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+ int32_t id = offlineStream.id;
+ if (mInputStream != nullptr && id == mInputStream->getId()) {
+ inputStream = mInputStream;
+ } else {
+ offlineStreamSet.add(id, mOutputStreams.get(id));
+ }
+ }
+
+ // TODO: check if we need to lock before copying states
+ // though technically no other thread should be talking to Camera3Device at this point
+ Camera3OfflineStates offlineStates(
+ mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
+ mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mNextResultFrameNumber, mNextReprocessResultFrameNumber,
+ mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
+ mZoomRatioMappers, mRotateAndCropMappers);
+
+ *session = new HidlCamera3OfflineSession(mId, inputStream, offlineStreamSet,
+ std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
+
+ // Delete all streams that has been transferred to offline session
+ Mutex::Autolock l(mLock);
+ for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+ int32_t id = offlineStream.id;
+ if (mInputStream != nullptr && id == mInputStream->getId()) {
+ mInputStream.clear();
+ } else {
+ mOutputStreams.remove(id);
+ }
+ }
+
+ // disconnect all other streams and switch to UNCONFIGURED state
+ if (mInputStream != nullptr) {
+ ret = mInputStream->disconnect();
+ if (ret != OK) {
+ SET_ERR_L("disconnect input stream failed!");
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ for (auto streamId : mOutputStreams.getStreamIds()) {
+ sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
+ ret = stream->disconnect();
+ if (ret != OK) {
+ SET_ERR_L("disconnect output stream %d failed!", streamId);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ mInputStream.clear();
+ mOutputStreams.clear();
+ mNeedConfig = true;
+ internalUpdateStatusLocked(STATUS_UNCONFIGURED);
+ mOperatingMode = NO_MODE;
+ mIsConstrainedHighSpeedConfiguration = false;
+ mRequestThread->clearPreviousRequest();
+
+ return OK;
+ // TO be done by CameraDeviceClient/Camera3OfflineSession
+ // register the offline client to camera service
+ // Setup result passthing threads etc
+ // Initialize offline session so HAL can start sending callback to it (result Fmq)
+ // TODO: check how many onIdle callback will be sent
+ // Java side to make sure the CameraCaptureSession is properly closed
+}
+
+sp<Camera3Device::RequestThread> HidlCamera3Device::createNewRequestThread(
+ wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
+ sp<Camera3Device::HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute) {
+ return new HidlRequestThread(parent, statusTracker, interface, sessionParamKeys,
+ useHalBufManager, supportCameraMute);
+};
+
+sp<Camera3Device::Camera3DeviceInjectionMethods>
+HidlCamera3Device::createCamera3DeviceInjectionMethods(wp<Camera3Device> parent) {
+ return new HidlCamera3DeviceInjectionMethods(parent);
+}
+
+status_t HidlCamera3Device::injectionCameraInitialize(const String8 &injectedCamId,
+ sp<CameraProviderManager> manager) {
+ return (static_cast<HidlCamera3DeviceInjectionMethods *>(
+ mInjectionMethods.get()))->injectionInitialize(injectedCamId, manager, this);
+};
+
+
+HidlCamera3Device::HidlHalInterface::HidlHalInterface(
+ sp<device::V3_2::ICameraDeviceSession> &session,
+ std::shared_ptr<RequestMetadataQueue> queue,
+ bool useHalBufManager, bool supportOfflineProcessing) :
+ HalInterface(useHalBufManager, supportOfflineProcessing),
+ mHidlSession(session),
+ mRequestMetadataQueue(queue) {
+ // Check with hardware service manager if we can downcast these interfaces
+ // Somewhat expensive, so cache the results at startup
+ auto castResult_3_8 = device::V3_8::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_8.isOk()) {
+ mHidlSession_3_8 = castResult_3_8;
+ }
+ auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_7.isOk()) {
+ mHidlSession_3_7 = castResult_3_7;
+ }
+ auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_6.isOk()) {
+ mHidlSession_3_6 = castResult_3_6;
+ }
+ auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_5.isOk()) {
+ mHidlSession_3_5 = castResult_3_5;
+ }
+ auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_4.isOk()) {
+ mHidlSession_3_4 = castResult_3_4;
+ }
+ auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_3.isOk()) {
+ mHidlSession_3_3 = castResult_3_3;
+ }
+}
+
+bool HidlCamera3Device::HidlHalInterface::valid() {
+ return (mHidlSession != nullptr);
+}
+
+void HidlCamera3Device::HidlHalInterface::clear() {
+ mHidlSession_3_8.clear();
+ mHidlSession_3_7.clear();
+ mHidlSession_3_6.clear();
+ mHidlSession_3_5.clear();
+ mHidlSession_3_4.clear();
+ mHidlSession_3_3.clear();
+ mHidlSession.clear();
+}
+
+status_t HidlCamera3Device::HidlHalInterface::constructDefaultRequestSettings(
+ camera_request_template_t templateId,
+ /*out*/ camera_metadata_t **requestTemplate) {
+ ATRACE_NAME("CameraHidlHal::constructDefaultRequestSettings");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ common::V1_0::Status status;
+
+ auto requestCallback = [&status, &requestTemplate]
+ (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
+ status = s;
+ if (status == common::V1_0::Status::OK) {
+ const camera_metadata *r =
+ reinterpret_cast<const camera_metadata_t*>(request.data());
+ size_t expectedSize = request.size();
+ int ret = validate_camera_metadata_structure(r, &expectedSize);
+ if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ *requestTemplate = clone_camera_metadata(r);
+ if (*requestTemplate == nullptr) {
+ ALOGE("%s: Unable to clone camera metadata received from HAL",
+ __FUNCTION__);
+ status = common::V1_0::Status::INTERNAL_ERROR;
+ }
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = common::V1_0::Status::INTERNAL_ERROR;
+ }
+ }
+ };
+ hardware::Return<void> err;
+ RequestTemplate id;
+ switch (templateId) {
+ case CAMERA_TEMPLATE_PREVIEW:
+ id = RequestTemplate::PREVIEW;
+ break;
+ case CAMERA_TEMPLATE_STILL_CAPTURE:
+ id = RequestTemplate::STILL_CAPTURE;
+ break;
+ case CAMERA_TEMPLATE_VIDEO_RECORD:
+ id = RequestTemplate::VIDEO_RECORD;
+ break;
+ case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
+ id = RequestTemplate::VIDEO_SNAPSHOT;
+ break;
+ case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
+ id = RequestTemplate::ZERO_SHUTTER_LAG;
+ break;
+ case CAMERA_TEMPLATE_MANUAL:
+ id = RequestTemplate::MANUAL;
+ break;
+ default:
+ // Unknown template ID, or this HAL is too old to support it
+ return BAD_VALUE;
+ }
+ err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
+
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ res = DEAD_OBJECT;
+ } else {
+ res = HidlProviderInfo::mapToStatusT(status);
+ }
+
+ return res;
+}
+
+bool HidlCamera3Device::HidlHalInterface::isReconfigurationRequired(
+ CameraMetadata& oldSessionParams, CameraMetadata& newSessionParams) {
+ // We do reconfiguration by default;
+ bool ret = true;
+ if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
+ android::hardware::hidl_vec<uint8_t> oldParams, newParams;
+ camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
+ oldSessionParams.getAndLock());
+ camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
+ newSessionParams.getAndLock());
+ oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
+ get_camera_metadata_size(oldSessioMeta));
+ newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
+ get_camera_metadata_size(newSessioMeta));
+ hardware::camera::common::V1_0::Status callStatus;
+ bool required;
+ auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
+ bool requiredFlag) {
+ callStatus = s;
+ required = requiredFlag;
+ };
+ auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
+ oldSessionParams.unlock(oldSessioMeta);
+ newSessionParams.unlock(newSessioMeta);
+ if (err.isOk()) {
+ switch (callStatus) {
+ case hardware::camera::common::V1_0::Status::OK:
+ ret = required;
+ break;
+ case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
+ mIsReconfigurationQuerySupported = false;
+ ret = true;
+ break;
+ default:
+ ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
+ ret = true;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::configureStreams(
+ const camera_metadata_t *sessionParams,
+ camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
+ ATRACE_NAME("CameraHal::configureStreams");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ if (config->input_is_multi_resolution && mHidlSession_3_7 == nullptr) {
+ ALOGE("%s: Camera device doesn't support multi-resolution input stream", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ // Convert stream config to HIDL
+ std::set<int> activeStreams;
+ device::V3_2::StreamConfiguration requestedConfiguration3_2;
+ device::V3_4::StreamConfiguration requestedConfiguration3_4;
+ device::V3_7::StreamConfiguration requestedConfiguration3_7;
+ device::V3_8::StreamConfiguration requestedConfiguration3_8;
+ requestedConfiguration3_2.streams.resize(config->num_streams);
+ requestedConfiguration3_4.streams.resize(config->num_streams);
+ requestedConfiguration3_7.streams.resize(config->num_streams);
+ requestedConfiguration3_8.streams.resize(config->num_streams);
+ for (size_t i = 0; i < config->num_streams; i++) {
+ device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
+ device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
+ device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
+ device::V3_8::Stream &dst3_8 = requestedConfiguration3_8.streams[i];
+ camera3::camera_stream_t *src = config->streams[i];
+
+ Camera3Stream* cam3stream = Camera3Stream::cast(src);
+ cam3stream->setBufferFreedListener(this);
+ int streamId = cam3stream->getId();
+ StreamType streamType;
+ switch (src->stream_type) {
+ case CAMERA_STREAM_OUTPUT:
+ streamType = StreamType::OUTPUT;
+ break;
+ case CAMERA_STREAM_INPUT:
+ streamType = StreamType::INPUT;
+ break;
+ default:
+ ALOGE("%s: Stream %d: Unsupported stream type %d",
+ __FUNCTION__, streamId, config->streams[i]->stream_type);
+ return BAD_VALUE;
+ }
+ dst3_2.id = streamId;
+ dst3_2.streamType = streamType;
+ dst3_2.width = src->width;
+ dst3_2.height = src->height;
+ dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+ dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
+ // For HidlSession version 3.5 or newer, the format and dataSpace sent
+ // to HAL are original, not the overridden ones.
+ if (mHidlSession_3_5 != nullptr) {
+ dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
+ cam3stream->getOriginalFormat() : src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
+ cam3stream->getOriginalDataSpace() : src->data_space);
+ } else {
+ dst3_2.format = mapToPixelFormat(src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+ }
+ dst3_4.v3_2 = dst3_2;
+ dst3_4.bufferSize = bufferSizes[i];
+ if (src->physical_camera_id != nullptr) {
+ dst3_4.physicalCameraId = src->physical_camera_id;
+ }
+ dst3_7.v3_4 = dst3_4;
+ dst3_7.groupId = cam3stream->getHalStreamGroupId();
+ dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+ size_t j = 0;
+ for (int mode : src->sensor_pixel_modes_used) {
+ dst3_7.sensorPixelModesUsed[j++] =
+ static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+ }
+ if ((src->dynamic_range_profile !=
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) &&
+ (mHidlSession_3_8 == nullptr)) {
+ ALOGE("%s: Camera device doesn't support non-standard dynamic range profiles: %d",
+ __FUNCTION__, src->dynamic_range_profile);
+ return BAD_VALUE;
+ }
+ dst3_8.v3_7 = dst3_7;
+ dst3_8.dynamicRangeProfile = mapToHidlDynamicProfile(src->dynamic_range_profile);
+ activeStreams.insert(streamId);
+ // Create Buffer ID map if necessary
+ mBufferRecords.tryCreateBufferCache(streamId);
+ }
+ // remove BufferIdMap for deleted streams
+ mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+ StreamConfigurationMode operationMode;
+ res = mapToStreamConfigurationMode(
+ (camera_stream_configuration_mode_t) config->operation_mode,
+ /*out*/ &operationMode);
+ if (res != OK) {
+ return res;
+ }
+ requestedConfiguration3_2.operationMode = operationMode;
+ requestedConfiguration3_4.operationMode = operationMode;
+ requestedConfiguration3_7.operationMode = operationMode;
+ size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+ requestedConfiguration3_4.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+ requestedConfiguration3_7.operationMode = operationMode;
+ requestedConfiguration3_7.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+ requestedConfiguration3_8.operationMode = operationMode;
+ requestedConfiguration3_8.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+
+ // Invoke configureStreams
+ device::V3_3::HalStreamConfiguration finalConfiguration;
+ device::V3_4::HalStreamConfiguration finalConfiguration3_4;
+ device::V3_6::HalStreamConfiguration finalConfiguration3_6;
+ common::V1_0::Status status;
+
+ auto configStream34Cb = [&status, &finalConfiguration3_4]
+ (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration3_4 = halConfiguration;
+ status = s;
+ };
+
+ auto configStream36Cb = [&status, &finalConfiguration3_6]
+ (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration3_6 = halConfiguration;
+ status = s;
+ };
+
+ auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
+ (hardware::Return<void>& err) -> status_t {
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
+ for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
+ finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
+ }
+ return OK;
+ };
+
+ auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
+ (hardware::Return<void>& err) -> status_t {
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
+ for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
+ finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
+ }
+ return OK;
+ };
+
+ // See which version of HAL we have
+ if (mHidlSession_3_8 != nullptr) {
+ ALOGV("%s: v3.8 device found", __FUNCTION__);
+ requestedConfiguration3_8.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_8.multiResolutionInputImage = config->input_is_multi_resolution;
+ auto err = mHidlSession_3_8->configureStreams_3_8(requestedConfiguration3_8,
+ configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_7 != nullptr) {
+ ALOGV("%s: v3.7 device found", __FUNCTION__);
+ requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
+ auto err = mHidlSession_3_7->configureStreams_3_7(
+ requestedConfiguration3_7, configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_6 != nullptr) {
+ ALOGV("%s: v3.6 device found", __FUNCTION__);
+ device::V3_5::StreamConfiguration requestedConfiguration3_5;
+ requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
+ requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
+ auto err = mHidlSession_3_6->configureStreams_3_6(
+ requestedConfiguration3_5, configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_5 != nullptr) {
+ ALOGV("%s: v3.5 device found", __FUNCTION__);
+ device::V3_5::StreamConfiguration requestedConfiguration3_5;
+ requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
+ requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
+ auto err = mHidlSession_3_5->configureStreams_3_5(
+ requestedConfiguration3_5, configStream34Cb);
+ res = postprocConfigStream34(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_4 != nullptr) {
+ // We do; use v3.4 for the call
+ ALOGV("%s: v3.4 device found", __FUNCTION__);
+ auto err = mHidlSession_3_4->configureStreams_3_4(
+ requestedConfiguration3_4, configStream34Cb);
+ res = postprocConfigStream34(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_3 != nullptr) {
+ // We do; use v3.3 for the call
+ ALOGV("%s: v3.3 device found", __FUNCTION__);
+ auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
+ [&status, &finalConfiguration]
+ (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration = halConfiguration;
+ status = s;
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ } else {
+ // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
+ ALOGV("%s: v3.2 device found", __FUNCTION__);
+ HalStreamConfiguration finalConfiguration_3_2;
+ auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
+ [&status, &finalConfiguration_3_2]
+ (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
+ finalConfiguration_3_2 = halConfiguration;
+ status = s;
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
+ for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
+ finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
+ finalConfiguration.streams[i].overrideDataSpace =
+ requestedConfiguration3_2.streams[i].dataSpace;
+ }
+ }
+
+ if (status != common::V1_0::Status::OK ) {
+ return HidlProviderInfo::mapToStatusT(status);
+ }
+
+ // And convert output stream configuration from HIDL
+
+ for (size_t i = 0; i < config->num_streams; i++) {
+ camera3::camera_stream_t *dst = config->streams[i];
+ int streamId = Camera3Stream::cast(dst)->getId();
+
+ // Start scan at i, with the assumption that the stream order matches
+ size_t realIdx = i;
+ bool found = false;
+ size_t halStreamCount = finalConfiguration.streams.size();
+ for (size_t idx = 0; idx < halStreamCount; idx++) {
+ if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
+ found = true;
+ break;
+ }
+ realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
+ }
+ if (!found) {
+ ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
+ device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
+
+ Camera3Stream* dstStream = Camera3Stream::cast(dst);
+ int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
+ android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
+
+ if (mHidlSession_3_6 != nullptr) {
+ dstStream->setOfflineProcessingSupport(src_36.supportOffline);
+ }
+
+ if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ dstStream->setFormatOverride(false);
+ dstStream->setDataSpaceOverride(false);
+ if (dst->format != overrideFormat) {
+ ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
+ streamId, dst->format);
+ }
+ if (dst->data_space != overrideDataSpace) {
+ ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
+ streamId, dst->format);
+ }
+ } else {
+ bool needFormatOverride =
+ requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
+ bool needDataspaceOverride =
+ requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
+ // Override allowed with IMPLEMENTATION_DEFINED
+ dstStream->setFormatOverride(needFormatOverride);
+ dstStream->setDataSpaceOverride(needDataspaceOverride);
+ dst->format = overrideFormat;
+ dst->data_space = overrideDataSpace;
+ }
+
+ if (dst->stream_type == CAMERA_STREAM_INPUT) {
+ if (src.v3_2.producerUsage != 0) {
+ ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ dstStream->setUsage(
+ mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
+ } else {
+ // OUTPUT
+ if (src.v3_2.consumerUsage != 0) {
+ ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ dstStream->setUsage(
+ mapProducerToFrameworkUsage(src.v3_2.producerUsage));
+ }
+ dst->max_buffers = src.v3_2.maxBuffers;
+ }
+
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::configureInjectedStreams(
+ const camera_metadata_t* sessionParams, camera_stream_configuration* config,
+ const std::vector<uint32_t>& bufferSizes,
+ const CameraMetadata& cameraCharacteristics) {
+ ATRACE_NAME("InjectionCameraHal::configureStreams");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ if (config->input_is_multi_resolution) {
+ ALOGE("%s: Injection camera device doesn't support multi-resolution input "
+ "stream", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ // Convert stream config to HIDL
+ std::set<int> activeStreams;
+ device::V3_2::StreamConfiguration requestedConfiguration3_2;
+ device::V3_4::StreamConfiguration requestedConfiguration3_4;
+ device::V3_7::StreamConfiguration requestedConfiguration3_7;
+ requestedConfiguration3_2.streams.resize(config->num_streams);
+ requestedConfiguration3_4.streams.resize(config->num_streams);
+ requestedConfiguration3_7.streams.resize(config->num_streams);
+ for (size_t i = 0; i < config->num_streams; i++) {
+ device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
+ device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
+ device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
+ camera3::camera_stream_t* src = config->streams[i];
+
+ Camera3Stream* cam3stream = Camera3Stream::cast(src);
+ cam3stream->setBufferFreedListener(this);
+ int streamId = cam3stream->getId();
+ StreamType streamType;
+ switch (src->stream_type) {
+ case CAMERA_STREAM_OUTPUT:
+ streamType = StreamType::OUTPUT;
+ break;
+ case CAMERA_STREAM_INPUT:
+ streamType = StreamType::INPUT;
+ break;
+ default:
+ ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
+ streamId, config->streams[i]->stream_type);
+ return BAD_VALUE;
+ }
+ dst3_2.id = streamId;
+ dst3_2.streamType = streamType;
+ dst3_2.width = src->width;
+ dst3_2.height = src->height;
+ dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+ dst3_2.rotation =
+ mapToStreamRotation((camera_stream_rotation_t)src->rotation);
+ // For HidlSession version 3.5 or newer, the format and dataSpace sent
+ // to HAL are original, not the overridden ones.
+ if (mHidlSession_3_5 != nullptr) {
+ dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
+ ? cam3stream->getOriginalFormat()
+ : src->format);
+ dst3_2.dataSpace =
+ mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
+ ? cam3stream->getOriginalDataSpace()
+ : src->data_space);
+ } else {
+ dst3_2.format = mapToPixelFormat(src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+ }
+ dst3_4.v3_2 = dst3_2;
+ dst3_4.bufferSize = bufferSizes[i];
+ if (src->physical_camera_id != nullptr) {
+ dst3_4.physicalCameraId = src->physical_camera_id;
+ }
+ dst3_7.v3_4 = dst3_4;
+ dst3_7.groupId = cam3stream->getHalStreamGroupId();
+ dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+ size_t j = 0;
+ for (int mode : src->sensor_pixel_modes_used) {
+ dst3_7.sensorPixelModesUsed[j++] =
+ static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+ }
+ activeStreams.insert(streamId);
+ // Create Buffer ID map if necessary
+ mBufferRecords.tryCreateBufferCache(streamId);
+ }
+ // remove BufferIdMap for deleted streams
+ mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+ StreamConfigurationMode operationMode;
+ res = mapToStreamConfigurationMode(
+ (camera_stream_configuration_mode_t)config->operation_mode,
+ /*out*/ &operationMode);
+ if (res != OK) {
+ return res;
+ }
+ requestedConfiguration3_7.operationMode = operationMode;
+ size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+ requestedConfiguration3_7.operationMode = operationMode;
+ requestedConfiguration3_7.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+
+ // See which version of HAL we have
+ if (mHidlSession_3_7 != nullptr) {
+ requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_7.multiResolutionInputImage =
+ config->input_is_multi_resolution;
+
+ const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
+ ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
+ hidlChars.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
+ get_camera_metadata_size(rawMetadata));
+ cameraCharacteristics.unlock(rawMetadata);
+
+ sp<hardware::camera::device::V3_7::ICameraInjectionSession>
+ hidlInjectionSession_3_7;
+ auto castInjectionResult_3_7 =
+ device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
+ if (castInjectionResult_3_7.isOk()) {
+ hidlInjectionSession_3_7 = castInjectionResult_3_7;
+ } else {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__,
+ castInjectionResult_3_7.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ auto err = hidlInjectionSession_3_7->configureInjectionStreams(
+ requestedConfiguration3_7, hidlChars);
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__,
+ err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ } else {
+ ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
+ "session is 3.7", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
+ /*out*/device::V3_2::CaptureRequest* captureRequest,
+ /*out*/std::vector<native_handle_t*>* handlesCreated,
+ /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
+ ATRACE_CALL();
+ if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
+ ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
+ "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
+ return BAD_VALUE;
+ }
+
+ captureRequest->frameNumber = request->frame_number;
+
+ captureRequest->fmqSettingsSize = 0;
+
+ {
+ if (request->input_buffer != nullptr) {
+ int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
+ buffer_handle_t buf = *(request->input_buffer->buffer);
+ auto pair = getBufferId(buf, streamId);
+ bool isNewBuffer = pair.first;
+ uint64_t bufferId = pair.second;
+ captureRequest->inputBuffer.streamId = streamId;
+ captureRequest->inputBuffer.bufferId = bufferId;
+ captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
+ captureRequest->inputBuffer.status = BufferStatus::OK;
+ native_handle_t *acquireFence = nullptr;
+ if (request->input_buffer->acquire_fence != -1) {
+ acquireFence = native_handle_create(1,0);
+ acquireFence->data[0] = request->input_buffer->acquire_fence;
+ handlesCreated->push_back(acquireFence);
+ }
+ captureRequest->inputBuffer.acquireFence = acquireFence;
+ captureRequest->inputBuffer.releaseFence = nullptr;
+
+ mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
+ request->input_buffer->buffer);
+ inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
+ } else {
+ captureRequest->inputBuffer.streamId = -1;
+ captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
+ }
+
+ captureRequest->outputBuffers.resize(request->num_output_buffers);
+ for (size_t i = 0; i < request->num_output_buffers; i++) {
+ const camera_stream_buffer_t *src = request->output_buffers + i;
+ StreamBuffer &dst = captureRequest->outputBuffers[i];
+ int32_t streamId = Camera3Stream::cast(src->stream)->getId();
+ if (src->buffer != nullptr) {
+ buffer_handle_t buf = *(src->buffer);
+ auto pair = getBufferId(buf, streamId);
+ bool isNewBuffer = pair.first;
+ dst.bufferId = pair.second;
+ dst.buffer = isNewBuffer ? buf : nullptr;
+ native_handle_t *acquireFence = nullptr;
+ if (src->acquire_fence != -1) {
+ acquireFence = native_handle_create(1,0);
+ acquireFence->data[0] = src->acquire_fence;
+ handlesCreated->push_back(acquireFence);
+ }
+ dst.acquireFence = acquireFence;
+ } else if (mUseHalBufManager) {
+ // HAL buffer management path
+ dst.bufferId = BUFFER_ID_NO_BUFFER;
+ dst.buffer = nullptr;
+ dst.acquireFence = nullptr;
+ } else {
+ ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ dst.streamId = streamId;
+ dst.status = BufferStatus::OK;
+ dst.releaseFence = nullptr;
+
+ // Output buffers are empty when using HAL buffer manager
+ if (!mUseHalBufManager) {
+ mBufferRecords.pushInflightBuffer(
+ captureRequest->frameNumber, streamId, src->buffer);
+ inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
+ }
+ }
+ }
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::flush() {
+ ATRACE_NAME("CameraHal::flush");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ auto err = mHidlSession->flush();
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ res = DEAD_OBJECT;
+ } else {
+ res = HidlProviderInfo::mapToStatusT(err);
+ }
+
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::dump(int /*fd*/) {
+ ATRACE_NAME("CameraHal::dump");
+ if (!valid()) return INVALID_OPERATION;
+
+ // Handled by CameraProviderManager::dump
+
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::repeatingRequestEnd(uint32_t frameNumber,
+ const std::vector<int32_t> &streamIds) {
+ ATRACE_NAME("CameraHal::repeatingRequestEnd");
+ if (!valid()) return INVALID_OPERATION;
+
+ if (mHidlSession_3_8.get() != nullptr) {
+ mHidlSession_3_8->repeatingRequestEnd(frameNumber, streamIds);
+ }
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::close() {
+ ATRACE_NAME("CameraHal::close()");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ auto err = mHidlSession->close();
+ // Interface will be dead shortly anyway, so don't log errors
+ if (!err.isOk()) {
+ res = DEAD_OBJECT;
+ }
+
+ return res;
+}
+
+void HidlCamera3Device::HidlHalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
+ ATRACE_NAME("CameraHal::signalPipelineDrain");
+ if (!valid() || mHidlSession_3_5 == nullptr) {
+ ALOGE("%s called on invalid camera!", __FUNCTION__);
+ return;
+ }
+
+ auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return;
+ }
+}
+
+status_t HidlCamera3Device::HidlHalInterface::processBatchCaptureRequests(
+ std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
+ ATRACE_NAME("CameraHal::processBatchCaptureRequests");
+ if (!valid()) return INVALID_OPERATION;
+
+ sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
+ sp<device::V3_7::ICameraDeviceSession> hidlSession_3_7;
+ auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_7.isOk()) {
+ hidlSession_3_7 = castResult_3_7;
+ }
+ auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_4.isOk()) {
+ hidlSession_3_4 = castResult_3_4;
+ }
+
+ hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
+ hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
+ hardware::hidl_vec<device::V3_7::CaptureRequest> captureRequests_3_7;
+ size_t batchSize = requests.size();
+ if (hidlSession_3_7 != nullptr) {
+ captureRequests_3_7.resize(batchSize);
+ } else if (hidlSession_3_4 != nullptr) {
+ captureRequests_3_4.resize(batchSize);
+ } else {
+ captureRequests.resize(batchSize);
+ }
+ std::vector<native_handle_t*> handlesCreated;
+ std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
+
+ status_t res = OK;
+ for (size_t i = 0; i < batchSize; i++) {
+ if (hidlSession_3_7 != nullptr) {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_7[i].v3_4.v3_2,
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ } else if (hidlSession_3_4 != nullptr) {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ } else {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ }
+ if (res != OK) {
+ mBufferRecords.popInflightBuffers(inflightBuffers);
+ cleanupNativeHandles(&handlesCreated);
+ return res;
+ }
+ }
+
+ std::vector<device::V3_2::BufferCache> cachesToRemove;
+ {
+ std::lock_guard<std::mutex> lock(mFreedBuffersLock);
+ for (auto& pair : mFreedBuffers) {
+ // The stream might have been removed since onBufferFreed
+ if (mBufferRecords.isStreamCached(pair.first)) {
+ cachesToRemove.push_back({pair.first, pair.second});
+ }
+ }
+ mFreedBuffers.clear();
+ }
+
+ common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
+ *numRequestProcessed = 0;
+
+ // Write metadata to FMQ.
+ for (size_t i = 0; i < batchSize; i++) {
+ camera_capture_request_t* request = requests[i];
+ device::V3_2::CaptureRequest* captureRequest;
+ if (hidlSession_3_7 != nullptr) {
+ captureRequest = &captureRequests_3_7[i].v3_4.v3_2;
+ } else if (hidlSession_3_4 != nullptr) {
+ captureRequest = &captureRequests_3_4[i].v3_2;
+ } else {
+ captureRequest = &captureRequests[i];
+ }
+
+ if (request->settings != nullptr) {
+ size_t settingsSize = get_camera_metadata_size(request->settings);
+ if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+ reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
+ captureRequest->settings.resize(0);
+ captureRequest->fmqSettingsSize = settingsSize;
+ } else {
+ if (mRequestMetadataQueue != nullptr) {
+ ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+ }
+ captureRequest->settings.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+ request->settings)),
+ get_camera_metadata_size(request->settings));
+ captureRequest->fmqSettingsSize = 0u;
+ }
+ } else {
+ // A null request settings maps to a size-0 CameraMetadata
+ captureRequest->settings.resize(0);
+ captureRequest->fmqSettingsSize = 0u;
+ }
+
+ // hidl session 3.7 specific handling.
+ if (hidlSession_3_7 != nullptr) {
+ captureRequests_3_7[i].inputWidth = request->input_width;
+ captureRequests_3_7[i].inputHeight = request->input_height;
+ }
+
+ // hidl session 3.7 and 3.4 specific handling.
+ if (hidlSession_3_7 != nullptr || hidlSession_3_4 != nullptr) {
+ hardware::hidl_vec<device::V3_4::PhysicalCameraSetting>& physicalCameraSettings =
+ (hidlSession_3_7 != nullptr) ?
+ captureRequests_3_7[i].v3_4.physicalCameraSettings :
+ captureRequests_3_4[i].physicalCameraSettings;
+ physicalCameraSettings.resize(request->num_physcam_settings);
+ for (size_t j = 0; j < request->num_physcam_settings; j++) {
+ if (request->physcam_settings != nullptr) {
+ size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
+ if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+ reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
+ settingsSize)) {
+ physicalCameraSettings[j].settings.resize(0);
+ physicalCameraSettings[j].fmqSettingsSize = settingsSize;
+ } else {
+ if (mRequestMetadataQueue != nullptr) {
+ ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+ }
+ physicalCameraSettings[j].settings.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+ request->physcam_settings[j])),
+ get_camera_metadata_size(request->physcam_settings[j]));
+ physicalCameraSettings[j].fmqSettingsSize = 0u;
+ }
+ } else {
+ physicalCameraSettings[j].fmqSettingsSize = 0u;
+ physicalCameraSettings[j].settings.resize(0);
+ }
+ physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
+ }
+ }
+ }
+
+ hardware::details::return_status err;
+ auto resultCallback =
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ *numRequestProcessed = n;
+ };
+ if (hidlSession_3_7 != nullptr) {
+ err = hidlSession_3_7->processCaptureRequest_3_7(captureRequests_3_7, cachesToRemove,
+ resultCallback);
+ } else if (hidlSession_3_4 != nullptr) {
+ err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
+ resultCallback);
+ } else {
+ err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+ resultCallback);
+ }
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ status = common::V1_0::Status::CAMERA_DISCONNECTED;
+ }
+
+ if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
+ ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
+ __FUNCTION__, *numRequestProcessed, batchSize);
+ status = common::V1_0::Status::INTERNAL_ERROR;
+ }
+
+ res = HidlProviderInfo::mapToStatusT(status);
+ if (res == OK) {
+ if (mHidlSession->isRemote()) {
+ // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
+ // sent to camera HAL processes)
+ cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
+ } else {
+ // In passthrough mode the FDs are now owned by HAL
+ cleanupNativeHandles(&handlesCreated);
+ }
+ } else {
+ mBufferRecords.popInflightBuffers(inflightBuffers);
+ cleanupNativeHandles(&handlesCreated);
+ }
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords) {
+ ATRACE_NAME("CameraHal::switchToOffline");
+ if (!valid() || mHidlSession_3_6 == nullptr) {
+ ALOGE("%s called on invalid camera!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
+ ALOGE("%s: output arguments must not be null!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
+ auto resultCallback =
+ [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
+ status = s;
+ *offlineSessionInfo = info;
+ *offlineSession = session;
+ };
+ auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
+
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ status_t ret = HidlProviderInfo::mapToStatusT(status);
+ if (ret != OK) {
+ return ret;
+ }
+
+ return verifyBufferCaches(offlineSessionInfo, bufferRecords);
+}
+
+HidlCamera3Device::HidlRequestThread::HidlRequestThread(wp<Camera3Device> parent,
+ sp<camera3::StatusTracker> statusTracker,
+ sp<HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute) :
+ RequestThread(parent, statusTracker, interface, sessionParamKeys, useHalBufManager,
+ supportCameraMute) {}
+
+status_t HidlCamera3Device::HidlRequestThread::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords) {
+ Mutex::Autolock l(mRequestLock);
+ clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
+
+ // Wait until request thread is fully stopped
+ // TBD: check if request thread is being paused by other APIs (shouldn't be)
+
+ // We could also check for mRepeatingRequests.empty(), but the API interface
+ // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
+ // new requests during the call; hence skip that check.
+ bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+ while (!queueEmpty) {
+ status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
+ return res;
+ } else if (res != OK) {
+ ALOGE("%s: request thread failed to submit a request: %s (%d)!",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+ }
+ return (static_cast<HidlHalInterface *>(mInterface.get()))->switchToOffline(
+ streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
+}
+
+status_t HidlCamera3Device::HidlCamera3DeviceInjectionMethods::injectionInitialize(
+ const String8& injectedCamId, sp<CameraProviderManager> manager,
+ const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
+ callback) {
+ ATRACE_CALL();
+ Mutex::Autolock lock(mInjectionLock);
+
+ if (manager == nullptr) {
+ ALOGE("%s: manager does not exist!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent == nullptr) {
+ ALOGE("%s: parent does not exist!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ mInjectedCamId = injectedCamId;
+ sp<ICameraDeviceSession> session;
+ ATRACE_BEGIN("Injection CameraHal::openSession");
+ status_t res = manager->openHidlSession(injectedCamId.string(), callback,
+ /*out*/ &session);
+ ATRACE_END();
+ if (res != OK) {
+ ALOGE("Injection camera could not open camera session: %s (%d)",
+ strerror(-res), res);
+ return res;
+ }
+
+ std::shared_ptr<RequestMetadataQueue> queue;
+ auto requestQueueRet =
+ session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
+ queue = std::make_shared<RequestMetadataQueue>(descriptor);
+ if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ ALOGE("Injection camera HAL returns empty request metadata fmq, not "
+ "use it");
+ queue = nullptr;
+ // don't use the queue onwards.
+ }
+ });
+ if (!requestQueueRet.isOk()) {
+ ALOGE("Injection camera transaction error when getting request metadata fmq: "
+ "%s, not use it", requestQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
+ auto resultQueueRet = session->getCaptureResultMetadataQueue(
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("Injection camera HAL returns empty result metadata fmq, not use "
+ "it");
+ resQueue = nullptr;
+ // Don't use the resQueue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Injection camera transaction error when getting result metadata queue "
+ "from camera session: %s", resultQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+ IF_ALOGV() {
+ session->interfaceChain(
+ [](::android::hardware::hidl_vec<::android::hardware::hidl_string>
+ interfaceChain) {
+ ALOGV("Injection camera session interface chain:");
+ for (const auto& iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+
+ ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
+
+ mInjectedCamHalInterface =
+ new HidlHalInterface(session, queue, parent->mUseHalBufManager,
+ parent->mSupportOfflineProcessing);
+ if (mInjectedCamHalInterface == nullptr) {
+ ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlCamera3DeviceInjectionMethods::replaceHalInterface(
+ sp<HalInterface> newHalInterface, bool keepBackup) {
+ Mutex::Autolock lock(mInjectionLock);
+ if (newHalInterface.get() == nullptr) {
+ ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
+ __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent == nullptr) {
+ ALOGE("%s: parent does not exist!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (newHalInterface->getTransportType() != IPCTransport::HIDL) {
+ ALOGE("%s Replacing HIDL HalInterface with another transport unsupported", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ HidlCamera3Device *hidlParent = static_cast<HidlCamera3Device *>(parent.get());
+ if (keepBackup) {
+ if (mBackupHalInterface == nullptr) {
+ mBackupHalInterface = parent->mInterface;
+ }
+ if (mBackupResultMetadataQueue == nullptr) {
+ mBackupResultMetadataQueue = std::move(hidlParent->mResultMetadataQueue);
+ hidlParent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
+ }
+ } else {
+ mBackupHalInterface = nullptr;
+ hidlParent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
+ mBackupResultMetadataQueue = nullptr;
+ }
+ parent->mInterface = newHalInterface;
+
+ return OK;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
new file mode 100644
index 0000000..a83080b
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -0,0 +1,246 @@
+/*
+ * 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 ANDROID_SERVERS_HIDLCAMERA3DEVICE_H
+#define ANDROID_SERVERS_HIDLCAMERA3DEVICE_H
+
+#include "../Camera3Device.h"
+#include "HidlCamera3OutputUtils.h"
+
+namespace android {
+
+using android::hardware::camera::metadata::V3_8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
+
+/**
+ * CameraDevice for HIDL HAL devices with version CAMERA_DEVICE_API_VERSION_3_0 or higher.
+ */
+class HidlCamera3Device :
+ virtual public hardware::camera::device::V3_8::ICameraDeviceCallback,
+ public Camera3Device {
+ public:
+
+ explicit HidlCamera3Device(const String8& id, bool overrideForPerfClass,
+ bool legacyClient = false) : Camera3Device(id, overrideForPerfClass, legacyClient) { }
+
+ virtual ~HidlCamera3Device() {}
+
+ /**
+ * Helper functions to map between framework and HIDL values
+ */
+ static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
+ static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
+ android_dataspace dataSpace);
+ static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
+ static CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap mapToHidlDynamicProfile(
+ int dynamicRangeProfile);
+ static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
+ camera_stream_rotation_t rotation);
+ // Returns a negative error code if the passed-in operation mode is not valid.
+ static status_t mapToStreamConfigurationMode(camera_stream_configuration_mode_t operationMode,
+ /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
+ static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
+ static android_dataspace mapToFrameworkDataspace(
+ hardware::camera::device::V3_2::DataspaceFlags);
+ static uint64_t mapConsumerToFrameworkUsage(
+ hardware::camera::device::V3_2::BufferUsageFlags usage);
+ static uint64_t mapProducerToFrameworkUsage(
+ hardware::camera::device::V3_2::BufferUsageFlags usage);
+
+ status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+
+ /**
+ * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
+ */
+
+ hardware::Return<void> processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) override;
+ hardware::Return<void> processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) override;
+ hardware::Return<void> notify(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
+
+ hardware::Return<void> requestStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) override;
+
+ hardware::Return<void> returnStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
+
+ hardware::Return<void> notify_3_8(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_8::NotifyMsg>& msgs) override;
+
+ // Handle one notify message
+ void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
+
+ status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) override;
+
+ using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
+
+ class HidlHalInterface : public Camera3Device::HalInterface {
+ public:
+ HidlHalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
+ std::shared_ptr<RequestMetadataQueue> queue,
+ bool useHalBufManager, bool supportOfflineProcessing);
+
+ virtual IPCTransport getTransportType() override { return IPCTransport::HIDL; }
+ // Returns true if constructed with a valid device or session, and not yet cleared
+ virtual bool valid() override;
+
+ // Reset this HalInterface object (does not call close())
+ virtual void clear() override;
+
+ // Calls into the HAL interface
+
+ // Caller takes ownership of requestTemplate
+ virtual status_t constructDefaultRequestSettings(camera_request_template templateId,
+ /*out*/ camera_metadata_t **requestTemplate) override;
+
+ virtual status_t configureStreams(const camera_metadata_t *sessionParams,
+ /*inout*/ camera_stream_configuration_t *config,
+ const std::vector<uint32_t>& bufferSizes) override;
+
+ // The injection camera configures the streams to hal.
+ virtual status_t configureInjectedStreams(
+ const camera_metadata_t* sessionParams,
+ /*inout*/ camera_stream_configuration_t* config,
+ const std::vector<uint32_t>& bufferSizes,
+ const CameraMetadata& cameraCharacteristics) override;
+
+ // When the call succeeds, the ownership of acquire fences in requests is transferred to
+ // HalInterface. More specifically, the current implementation will send the fence to
+ // HAL process and close the FD in cameraserver process. When the call fails, the ownership
+ // of the acquire fence still belongs to the caller.
+ virtual status_t processBatchCaptureRequests(
+ std::vector<camera_capture_request_t*>& requests,
+ /*out*/uint32_t* numRequestProcessed) override;
+ virtual status_t flush() override;
+ virtual status_t dump(int fd) override;
+ virtual status_t close() override;
+
+ virtual void signalPipelineDrain(const std::vector<int>& streamIds) override;
+ virtual bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
+ CameraMetadata& newSessionParams) override;
+
+ virtual status_t repeatingRequestEnd(uint32_t frameNumber,
+ const std::vector<int32_t> &streamIds) override;
+
+ status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords);
+
+ private:
+
+ // Always valid
+ sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
+ // Valid if ICameraDeviceSession is @3.3 or newer
+ sp<hardware::camera::device::V3_3::ICameraDeviceSession> mHidlSession_3_3;
+ // Valid if ICameraDeviceSession is @3.4 or newer
+ sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
+ // Valid if ICameraDeviceSession is @3.5 or newer
+ sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
+ // Valid if ICameraDeviceSession is @3.6 or newer
+ sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
+ // Valid if ICameraDeviceSession is @3.7 or newer
+ sp<hardware::camera::device::V3_7::ICameraDeviceSession> mHidlSession_3_7;
+ // Valid if ICameraDeviceSession is @3.7 or newer
+ sp<hardware::camera::device::V3_8::ICameraDeviceSession> mHidlSession_3_8;
+
+ std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
+
+ // The output HIDL request still depends on input camera_capture_request_t
+ // Do not free input camera_capture_request_t before output HIDL request
+ status_t wrapAsHidlRequest(camera_capture_request_t* in,
+ /*out*/hardware::camera::device::V3_2::CaptureRequest* out,
+ /*out*/std::vector<native_handle_t*>* handlesCreated,
+ /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
+ }; // class HidlHalInterface
+
+ class HidlRequestThread : public Camera3Device::RequestThread {
+ public:
+ HidlRequestThread(wp<Camera3Device> parent,
+ sp<camera3::StatusTracker> statusTracker,
+ sp<HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute);
+
+ status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords);
+ }; // class HidlRequestThread
+
+ class HidlCamera3DeviceInjectionMethods : public Camera3DeviceInjectionMethods {
+ public:
+ // Initialize the injection camera and generate an hal interface.
+ status_t injectionInitialize(
+ const String8& injectedCamId, sp<CameraProviderManager> manager,
+ const sp<
+ android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
+ callback);
+ HidlCamera3DeviceInjectionMethods(wp<Camera3Device> parent) :
+ Camera3DeviceInjectionMethods(parent) { };
+ ~HidlCamera3DeviceInjectionMethods() {}
+ private:
+ // Backup of the original camera hal result FMQ.
+ std::unique_ptr<ResultMetadataQueue> mBackupResultMetadataQueue;
+
+ // FMQ writes the result for the injection camera. Must be guarded by
+ // mProcessCaptureResultLock.
+ std::unique_ptr<ResultMetadataQueue> mInjectionResultMetadataQueue;
+
+ // Use injection camera hal interface to replace and backup original
+ // camera hal interface.
+ virtual status_t replaceHalInterface(sp<HalInterface> newHalInterface,
+ bool keepBackup) override;
+ };
+
+ private:
+ template<typename NotifyMsgType>
+ hardware::Return<void> notifyHelper(
+ const hardware::hidl_vec<NotifyMsgType>& msgs);
+
+ virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+ sp<CameraProviderManager> manager) override;
+
+ virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> parent,
+ sp<camera3::StatusTracker> statusTracker,
+ sp<HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute) override;
+
+ virtual sp<Camera3DeviceInjectionMethods>
+ createCamera3DeviceInjectionMethods(wp<Camera3Device>) override;
+
+ // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+ std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+}; // class HidlCamera3Device
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
new file mode 100644
index 0000000..d517c8d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -0,0 +1,235 @@
+/*
+ * 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 "Hidl-Camera3-OffLnSsn"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <inttypes.h>
+
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include "device3/hidl/HidlCamera3OfflineSession.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+#include "utils/CameraTraces.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+
+HidlCamera3OfflineSession::~HidlCamera3OfflineSession() {
+ ATRACE_CALL();
+ ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string());
+ HidlCamera3OfflineSession::disconnectSession();
+}
+
+status_t HidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
+ ATRACE_CALL();
+
+ if (mSession == nullptr) {
+ ALOGE("%s: HIDL session is null!", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ mListener = listener;
+
+ // setup result FMQ
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
+ auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty result metadata fmq, not use it");
+ resQueue = nullptr;
+ // Don't use resQueue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+ resultQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+ mStatus = STATUS_ACTIVE;
+ }
+
+ mSession->setCallback(this);
+
+ return OK;
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) {
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ listener = mListener.promote();
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+ };
+
+ std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) {
+ // TODO: changed impl to call into processCaptureResult_3_4 instead?
+ // might need to figure how to reduce copy though.
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ listener = mListener.promote();
+ }
+
+ hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+ };
+
+ std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result, noPhysMetadata);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::notify(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ listener = mListener.promote();
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+ };
+ for (const auto& msg : msgs) {
+ camera3::notify(states, msg);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::requestStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) {
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ }
+
+ RequestBufferStates states {
+ mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
+ *this, mBufferRecords, *this};
+ camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::returnStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ }
+
+ ReturnBufferStates states {
+ mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, mBufferRecords};
+
+ camera3::returnStreamBuffers(states, buffers);
+ return hardware::Void();
+}
+
+void HidlCamera3OfflineSession::disconnectSession() {
+ // TODO: Make sure this locking is correct.
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mSession != nullptr) {
+ mSession->close();
+ }
+ mSession.clear();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
new file mode 100644
index 0000000..597cc5d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
@@ -0,0 +1,109 @@
+/*
+ * 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 ANDROID_SERVERS_HIDL_CAMERA3OFFLINESESSION_H
+#define ANDROID_SERVERS_HIDL_CAMERA3OFFLINESESSION_H
+
+#include <memory>
+#include <mutex>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include <android/hardware/camera/device/3.6/ICameraOfflineSession.h>
+
+#include <fmq/MessageQueue.h>
+
+#include "HidlCamera3OutputUtils.h"
+#include "common/CameraOfflineSessionBase.h"
+
+#include "device3/Camera3BufferManager.h"
+#include "device3/Camera3OfflineSession.h"
+#include "device3/InFlightRequest.h"
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3Stream;
+class Camera3OutputStreamInterface;
+class Camera3StreamInterface;
+
+} // namespace camera3
+
+/**
+ * HidlCamera3OfflineSession for offline session defined in HIDL ICameraOfflineSession@3.6 or higher
+ */
+class HidlCamera3OfflineSession :
+ public Camera3OfflineSession,
+ virtual public hardware::camera::device::V3_5::ICameraDeviceCallback {
+ public:
+
+ // initialize by Camera3Device.
+ explicit HidlCamera3OfflineSession(const String8& id,
+ const sp<camera3::Camera3Stream>& inputStream,
+ const camera3::StreamSet& offlineStreamSet,
+ camera3::BufferRecords&& bufferRecords,
+ const camera3::InFlightRequestMap& offlineReqs,
+ const Camera3OfflineStates& offlineStates,
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
+ Camera3OfflineSession(id, inputStream, offlineStreamSet, std::move(bufferRecords),
+ offlineReqs, offlineStates),
+ mSession(offlineSession) {};
+
+ virtual ~HidlCamera3OfflineSession();
+
+ virtual status_t initialize(wp<NotificationListener> listener) override;
+
+ /**
+ * HIDL ICameraDeviceCallback interface
+ * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
+ */
+
+ hardware::Return<void> processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) override;
+ hardware::Return<void> processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) override;
+ hardware::Return<void> notify(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
+
+ hardware::Return<void> requestStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) override;
+
+ hardware::Return<void> returnStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
+
+ /**
+ * End of CameraOfflineSessionBase interface
+ */
+
+ private:
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> mSession;
+ // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+ std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+ virtual void disconnectSession() override;
+}; // class Camera3OfflineSession
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
new file mode 100644
index 0000000..afe9d56
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
@@ -0,0 +1,344 @@
+/*
+ * 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 "HidlCamera3-OutputUtils"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) states.setErrIntf.setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+
+#include <camera/CameraUtils.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/Camera3OutputUtilsTemplated.h"
+
+#include "system/camera_metadata.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+namespace camera3 {
+
+void processOneCaptureResultLocked(
+ HidlCaptureOutputStates& states,
+ const hardware::camera::device::V3_2::CaptureResult& result,
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::PhysicalCameraMetadata> &physicalCameraMetadata) {
+ processOneCaptureResultLockedT<HidlCaptureOutputStates,
+ hardware::camera::device::V3_2::CaptureResult,
+ hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata>,
+ hardware::hidl_vec<uint8_t>, ResultMetadataQueue,
+ hardware::camera::device::V3_2::BufferStatus>(states, result, physicalCameraMetadata);
+}
+
+void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_8::NotifyMsg& msg) {
+ using android::hardware::camera::device::V3_2::MsgType;
+
+ hardware::camera::device::V3_2::NotifyMsg msg_3_2;
+ msg_3_2.type = msg.type;
+ bool hasReadoutTime = false;
+ uint64_t readoutTime = 0;
+ switch (msg.type) {
+ case MsgType::ERROR:
+ msg_3_2.msg.error = msg.msg.error;
+ break;
+ case MsgType::SHUTTER:
+ msg_3_2.msg.shutter = msg.msg.shutter.v3_2;
+ hasReadoutTime = true;
+ readoutTime = msg.msg.shutter.readoutTimestamp;
+ break;
+ }
+ notify(states, msg_3_2, hasReadoutTime, readoutTime);
+}
+
+void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_2::NotifyMsg& msg,
+ bool hasReadoutTime, uint64_t readoutTime) {
+
+ using android::hardware::camera::device::V3_2::MsgType;
+ using android::hardware::camera::device::V3_2::ErrorCode;
+
+ ATRACE_CALL();
+ camera_notify_msg m;
+ switch (msg.type) {
+ case MsgType::ERROR:
+ m.type = CAMERA_MSG_ERROR;
+ m.message.error.frame_number = msg.msg.error.frameNumber;
+ if (msg.msg.error.errorStreamId >= 0) {
+ sp<Camera3StreamInterface> stream =
+ states.outputStreams.get(msg.msg.error.errorStreamId);
+ if (stream == nullptr) {
+ ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
+ m.message.error.frame_number, msg.msg.error.errorStreamId);
+ return;
+ }
+ m.message.error.error_stream = stream->asHalStream();
+ } else {
+ m.message.error.error_stream = nullptr;
+ }
+ switch (msg.msg.error.errorCode) {
+ case ErrorCode::ERROR_DEVICE:
+ m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
+ break;
+ case ErrorCode::ERROR_REQUEST:
+ m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
+ break;
+ case ErrorCode::ERROR_RESULT:
+ m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
+ break;
+ case ErrorCode::ERROR_BUFFER:
+ m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
+ break;
+ }
+ break;
+ case MsgType::SHUTTER:
+ m.type = CAMERA_MSG_SHUTTER;
+ m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
+ m.message.shutter.timestamp = msg.msg.shutter.timestamp;
+ m.message.shutter.readout_timestamp = hasReadoutTime ?
+ readoutTime : m.message.shutter.timestamp;
+ break;
+ }
+ notify(states, &m);
+}
+
+
+
+// The buffers requested through this call are not tied to any CaptureRequest in
+// particular. They may used by the hal for a particular frame's output buffer
+// or for its internal use as well. In the case that the hal does use any buffer
+// from the requested list here, for a particular frame's output buffer, the
+// buffer will be returned with the processCaptureResult call corresponding to
+// the frame. The other buffers will be returned through returnStreamBuffers.
+// The buffers returned via returnStreamBuffers will not have a valid
+// timestamp(0) and will be dropped by the bufferqueue.
+void requestStreamBuffers(RequestBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb) {
+ using android::hardware::camera::device::V3_2::BufferStatus;
+ using android::hardware::camera::device::V3_2::StreamBuffer;
+ using android::hardware::camera::device::V3_5::BufferRequestStatus;
+ using android::hardware::camera::device::V3_5::StreamBufferRet;
+ using android::hardware::camera::device::V3_5::StreamBufferRequestError;
+
+ std::lock_guard<std::mutex> lock(states.reqBufferLock);
+
+ hardware::hidl_vec<StreamBufferRet> bufRets;
+ if (!states.useHalBufManager) {
+ ALOGE("%s: Camera %s does not support HAL buffer management",
+ __FUNCTION__, states.cameraId.string());
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+
+ SortedVector<int32_t> streamIds;
+ ssize_t sz = streamIds.setCapacity(bufReqs.size());
+ if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
+ ALOGE("%s: failed to allocate memory for %zu buffer requests",
+ __FUNCTION__, bufReqs.size());
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+
+ if (bufReqs.size() > states.outputStreams.size()) {
+ ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
+ __FUNCTION__, bufReqs.size(), states.outputStreams.size());
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+
+ // Check for repeated streamId
+ for (const auto& bufReq : bufReqs) {
+ if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
+ ALOGE("%s: Stream %d appear multiple times in buffer requests",
+ __FUNCTION__, bufReq.streamId);
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+ streamIds.add(bufReq.streamId);
+ }
+
+ if (!states.reqBufferIntf.startRequestBuffer()) {
+ ALOGE("%s: request buffer disallowed while camera service is configuring",
+ __FUNCTION__);
+ _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
+ return;
+ }
+
+ bufRets.resize(bufReqs.size());
+
+ bool allReqsSucceeds = true;
+ bool oneReqSucceeds = false;
+ for (size_t i = 0; i < bufReqs.size(); i++) {
+ const auto& bufReq = bufReqs[i];
+ auto& bufRet = bufRets[i];
+ int32_t streamId = bufReq.streamId;
+ sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
+ if (outputStream == nullptr) {
+ ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
+ hardware::hidl_vec<StreamBufferRet> emptyBufRets;
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
+ states.reqBufferIntf.endRequestBuffer();
+ return;
+ }
+
+ bufRet.streamId = streamId;
+ if (outputStream->isAbandoned()) {
+ bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
+ allReqsSucceeds = false;
+ continue;
+ }
+
+ size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
+ uint32_t numBuffersRequested = bufReq.numBuffersRequested;
+ size_t totalHandout = handOutBufferCount + numBuffersRequested;
+ uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
+ if (totalHandout > maxBuffers) {
+ // Not able to allocate enough buffer. Exit early for this stream
+ ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
+ " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
+ numBuffersRequested, maxBuffers);
+ bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
+ allReqsSucceeds = false;
+ continue;
+ }
+
+ hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
+ bool currentReqSucceeds = true;
+ std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
+ std::vector<buffer_handle_t> newBuffers;
+ size_t numAllocatedBuffers = 0;
+ size_t numPushedInflightBuffers = 0;
+ for (size_t b = 0; b < numBuffersRequested; b++) {
+ camera_stream_buffer_t& sb = streamBuffers[b];
+ // Since this method can run concurrently with request thread
+ // We need to update the wait duration everytime we call getbuffer
+ nsecs_t waitDuration = states.reqBufferIntf.getWaitDuration();
+ status_t res = outputStream->getBuffer(&sb, waitDuration);
+ if (res != OK) {
+ if (res == NO_INIT || res == DEAD_OBJECT) {
+ ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
+ states.sessionStatsBuilder.stopCounter(streamId);
+ } else {
+ ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ if (res == TIMED_OUT || res == NO_MEMORY) {
+ bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
+ } else {
+ bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+ }
+ }
+ currentReqSucceeds = false;
+ break;
+ }
+ numAllocatedBuffers++;
+
+ buffer_handle_t *buffer = sb.buffer;
+ auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
+ bool isNewBuffer = pair.first;
+ uint64_t bufferId = pair.second;
+ StreamBuffer& hBuf = tmpRetBuffers[b];
+
+ hBuf.streamId = streamId;
+ hBuf.bufferId = bufferId;
+ hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
+ hBuf.status = BufferStatus::OK;
+ hBuf.releaseFence = nullptr;
+ if (isNewBuffer) {
+ newBuffers.push_back(*buffer);
+ }
+
+ native_handle_t *acquireFence = nullptr;
+ if (sb.acquire_fence != -1) {
+ acquireFence = native_handle_create(1,0);
+ acquireFence->data[0] = sb.acquire_fence;
+ }
+ hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
+ hBuf.releaseFence = nullptr;
+
+ res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
+ if (res != OK) {
+ ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+ currentReqSucceeds = false;
+ break;
+ }
+ numPushedInflightBuffers++;
+ }
+ if (currentReqSucceeds) {
+ bufRet.val.buffers(std::move(tmpRetBuffers));
+ oneReqSucceeds = true;
+ } else {
+ allReqsSucceeds = false;
+ for (size_t b = 0; b < numPushedInflightBuffers; b++) {
+ StreamBuffer& hBuf = tmpRetBuffers[b];
+ buffer_handle_t* buffer;
+ status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
+ hBuf.bufferId, &buffer);
+ if (res != OK) {
+ SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ }
+ }
+ for (size_t b = 0; b < numAllocatedBuffers; b++) {
+ camera_stream_buffer_t& sb = streamBuffers[b];
+ sb.acquire_fence = -1;
+ sb.status = CAMERA_BUFFER_STATUS_ERROR;
+ }
+ returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
+ streamBuffers.data(), numAllocatedBuffers, /*timestamp*/0,
+ /*readoutTimestamp*/0, /*requested*/false,
+ /*requestTimeNs*/0, states.sessionStatsBuilder);
+ for (auto buf : newBuffers) {
+ states.bufferRecordsIntf.removeOneBufferCache(streamId, buf);
+ }
+ }
+ }
+
+ _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
+ oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
+ BufferRequestStatus::FAILED_UNKNOWN,
+ bufRets);
+ states.reqBufferIntf.endRequestBuffer();
+}
+
+void returnStreamBuffers(ReturnBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+ returnStreamBuffersT(states, buffers);
+}
+
+} // camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.h
new file mode 100644
index 0000000..583d738
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.h
@@ -0,0 +1,84 @@
+/*
+ * 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 ANDROID_SERVERS_HIDL_CAMERA3_OUTPUT_UTILS_H
+#define ANDROID_SERVERS_HIDL_CAMERA3_OUTPUT_UTILS_H
+
+#include <memory>
+#include <mutex>
+
+#include <cutils/native_handle.h>
+
+#include <fmq/MessageQueue.h>
+
+#include <common/CameraDeviceBase.h>
+
+#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
+
+#include "device3/BufferUtils.h"
+//#include "device3/DistortionMapper.h"
+//#include "device3/ZoomRatioMapper.h"
+//#include "device3/RotateAndCropMapper.h"
+#include "device3/InFlightRequest.h"
+#include "device3/Camera3Stream.h"
+//#include "device3/Camera3OutputStreamInterface.h"
+#include "device3/Camera3OutputUtils.h"
+//#include "utils/SessionStatsBuilder.h"
+//#include "utils/TagMonitor.h"
+
+namespace android {
+
+using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
+
+namespace camera3 {
+
+ /**
+ * Helper methods shared between HidlCamera3Device/HidlCamera3OfflineSession for HAL callbacks
+ */
+ // Camera3Device/Camera3OfflineSession internal states used in notify/processCaptureResult
+ // callbacks
+ struct HidlCaptureOutputStates : public CaptureOutputStates {
+ std::unique_ptr<ResultMetadataQueue>& fmq;
+ };
+
+ // Handle one capture result. Assume callers hold the lock to serialize all
+ // processCaptureResult calls
+ void processOneCaptureResultLocked(
+ HidlCaptureOutputStates& states,
+ const hardware::camera::device::V3_2::CaptureResult& result,
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::PhysicalCameraMetadata>
+ &physicalCameraMetadata);
+
+ // Handle one notify message
+ void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_2::NotifyMsg& msg,
+ bool hasReadoutTime = false, uint64_t readoutTime = 0LL);
+ void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_8::NotifyMsg& msg);
+
+ void requestStreamBuffers(RequestBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb
+ _hidl_cb);
+ void returnStreamBuffers(ReturnBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers);
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index c8a6b32..e9f6979 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -212,7 +212,7 @@
* Simple test version of the interaction proxy, to use to inject onRegistered calls to the
* CameraProviderManager
*/
-struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionProxy {
+struct TestInteractionProxy : public CameraProviderManager::HidlServiceInteractionProxy {
sp<hidl::manager::V1_0::IServiceNotification> mManagerNotificationInterface;
sp<TestICameraProvider> mTestCameraProvider;
@@ -269,13 +269,13 @@
~TestStatusListener() {}
void onDeviceStatusChanged(const String8 &,
- hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+ CameraDeviceStatus) override {}
void onDeviceStatusChanged(const String8 &, const String8 &,
- hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+ CameraDeviceStatus) override {}
void onTorchStatusChanged(const String8 &,
- hardware::camera::common::V1_0::TorchModeStatus) override {}
+ TorchModeStatus) override {}
void onTorchStatusChanged(const String8 &,
- hardware::camera::common::V1_0::TorchModeStatus, SystemCameraKind) override {}
+ TorchModeStatus, SystemCameraKind) override {}
void onNewProviderRegistered() override {}
};
diff --git a/services/camera/libcameraservice/utils/IPCTransport.h b/services/camera/libcameraservice/utils/IPCTransport.h
new file mode 100644
index 0000000..b8e80ac
--- /dev/null
+++ b/services/camera/libcameraservice/utils/IPCTransport.h
@@ -0,0 +1,26 @@
+/*
+ * 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 ANDROID_SERVERS_IPC_H_
+#define ANDROID_SERVERS_IPC_H_
+
+enum class IPCTransport : uint32_t {
+ HIDL = 0,
+ AIDL = 1,
+ INVALID = 2
+};
+
+#endif
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index a35e6f3..f826d83 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -22,7 +22,7 @@
#include "android/hardware/camera/metadata/3.8/types.h"
#include "common/CameraDeviceBase.h"
#include "../CameraService.h"
-#include "device3/Camera3Device.h"
+#include "device3/hidl/HidlCamera3Device.h"
#include "device3/Camera3OutputStream.h"
#include "system/graphics-base-v1.1.h"
@@ -486,17 +486,18 @@
stream->v3_7.v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
stream->v3_7.v3_4.v3_2.width = streamInfo.width;
stream->v3_7.v3_4.v3_2.height = streamInfo.height;
- stream->v3_7.v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
+ stream->v3_7.v3_4.v3_2.format = HidlCamera3Device::mapToPixelFormat(streamInfo.format);
auto u = streamInfo.consumerUsage;
camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
- stream->v3_7.v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
- stream->v3_7.v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
- stream->v3_7.v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
+ stream->v3_7.v3_4.v3_2.usage = HidlCamera3Device::mapToConsumerUsage(u);
+ stream->v3_7.v3_4.v3_2.dataSpace = HidlCamera3Device::mapToHidlDataspace(streamInfo.dataSpace);
+ stream->v3_7.v3_4.v3_2.rotation = HidlCamera3Device::mapToStreamRotation(rotation);
stream->v3_7.v3_4.v3_2.id = -1; // Invalid stream id
stream->v3_7.v3_4.physicalCameraId = std::string(physicalId.string());
stream->v3_7.v3_4.bufferSize = 0;
stream->v3_7.groupId = groupId;
stream->v3_7.sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
+
size_t idx = 0;
for (auto mode : streamInfo.sensorPixelModesUsed) {
stream->v3_7.sensorPixelModesUsed[idx++] =
@@ -599,7 +600,7 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
*earlyExit = false;
- auto ret = Camera3Device::mapToStreamConfigurationMode(
+ auto ret = HidlCamera3Device::mapToStreamConfigurationMode(
static_cast<camera_stream_configuration_mode_t> (operatingMode),
/*out*/ &streamConfiguration.operationMode);
if (ret != OK) {
@@ -629,7 +630,7 @@
hardware::camera::device::V3_2::StreamType::INPUT,
static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
- Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
+ HidlCamera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
/*usage*/ 0, HAL_DATASPACE_UNKNOWN,
hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
/*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 0fa24cd..11534bb 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -181,8 +181,14 @@
"libstatssocket",
],
+ // within the library, we use "xxx.h"
+ local_include_dirs: [
+ "include/mediametricsservice",
+ ],
+
+ // external parties use <mediametricsservice/xxx.h>
export_include_dirs: [
- ".",
+ "include",
],
static_libs: [
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index ab74c8e..5787e9e 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -45,6 +45,10 @@
#define AUDIO_POWER_USAGE_PROP_DURATION_NS "durationNs" // int64
#define AUDIO_POWER_USAGE_PROP_TYPE "type" // int32
#define AUDIO_POWER_USAGE_PROP_VOLUME "volume" // double
+#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS "minVolumeDurationNs" // int64
+#define AUDIO_POWER_USAGE_PROP_MIN_VOLUME "minVolume" // double
+#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS "maxVolumeDurationNs" // int64
+#define AUDIO_POWER_USAGE_PROP_MAX_VOLUME "maxVolume" // double
namespace android::mediametrics {
@@ -141,13 +145,34 @@
double volume;
if (!item->getDouble(AUDIO_POWER_USAGE_PROP_VOLUME, &volume)) return;
+ int64_t min_volume_duration_ns;
+ if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, &min_volume_duration_ns)) {
+ return;
+ }
+
+ double min_volume;
+ if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &min_volume)) return;
+
+ int64_t max_volume_duration_ns;
+ if (!item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, &max_volume_duration_ns)) {
+ return;
+ }
+
+ double max_volume;
+ if (!item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &max_volume)) return;
+
const int32_t duration_secs = (int32_t)(duration_ns / NANOS_PER_SECOND);
- const float average_volume = (float)volume;
+ const int32_t min_volume_duration_secs = (int32_t)(min_volume_duration_ns / NANOS_PER_SECOND);
+ const int32_t max_volume_duration_secs = (int32_t)(max_volume_duration_ns / NANOS_PER_SECOND);
const int result = android::util::stats_write(android::util::AUDIO_POWER_USAGE_DATA_REPORTED,
audio_device,
duration_secs,
- average_volume,
- type);
+ (float)volume,
+ type,
+ min_volume_duration_secs,
+ (float)min_volume,
+ max_volume_duration_secs,
+ (float)max_volume);
std::stringstream log;
log << "result:" << result << " {"
@@ -155,17 +180,43 @@
<< android::util::AUDIO_POWER_USAGE_DATA_REPORTED
<< " audio_device:" << audio_device
<< " duration_secs:" << duration_secs
- << " average_volume:" << average_volume
+ << " average_volume:" << (float)volume
<< " type:" << type
+ << " min_volume_duration_secs:" << min_volume_duration_secs
+ << " min_volume:" << (float)min_volume
+ << " max_volume_duration_secs:" << max_volume_duration_secs
+ << " max_volume:" << (float)max_volume
<< " }";
mStatsdLog->log(android::util::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
}
+void AudioPowerUsage::updateMinMaxVolumeAndDuration(
+ const int64_t cur_max_volume_duration_ns, const double cur_max_volume,
+ const int64_t cur_min_volume_duration_ns, const double cur_min_volume,
+ int64_t& f_max_volume_duration_ns, double& f_max_volume,
+ int64_t& f_min_volume_duration_ns, double& f_min_volume)
+{
+ if (f_min_volume > cur_min_volume) {
+ f_min_volume = cur_min_volume;
+ f_min_volume_duration_ns = cur_min_volume_duration_ns;
+ } else if (f_min_volume == cur_min_volume) {
+ f_min_volume_duration_ns += cur_min_volume_duration_ns;
+ }
+ if (f_max_volume < cur_max_volume) {
+ f_max_volume = cur_max_volume;
+ f_max_volume_duration_ns = cur_max_volume_duration_ns;
+ } else if (f_max_volume == cur_max_volume) {
+ f_max_volume_duration_ns += cur_max_volume_duration_ns;
+ }
+}
+
bool AudioPowerUsage::saveAsItem_l(
- int32_t device, int64_t duration_ns, int32_t type, double average_vol)
+ int32_t device, int64_t duration_ns, int32_t type, double average_vol,
+ int64_t max_volume_duration_ns, double max_volume,
+ int64_t min_volume_duration_ns, double min_volume)
{
ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
- (long long)duration_ns, average_vol );
+ (long long)duration_ns, average_vol);
if (duration_ns == 0) {
return true; // skip duration 0 usage
}
@@ -193,10 +244,36 @@
item->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, final_volume);
item->setTimestamp(systemTime(SYSTEM_TIME_REALTIME));
- ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f)", __func__,
+ // Update the max/min volume and duration
+ int64_t final_min_volume_duration_ns;
+ int64_t final_max_volume_duration_ns;
+ double final_min_volume;
+ double final_max_volume;
+
+ item->getInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
+ &final_min_volume_duration_ns);
+ item->getDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, &final_min_volume);
+ item->getInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
+ &final_max_volume_duration_ns);
+ item->getDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, &final_max_volume);
+ updateMinMaxVolumeAndDuration(max_volume_duration_ns, max_volume,
+ min_volume_duration_ns, min_volume,
+ final_max_volume_duration_ns, final_max_volume,
+ final_min_volume_duration_ns, final_min_volume);
+ item->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS,
+ final_min_volume_duration_ns);
+ item->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, final_min_volume);
+ item->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS,
+ final_max_volume_duration_ns);
+ item->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, final_max_volume);
+
+ ALOGV("%s: update (%#x, %d, %lld, %f) --> (%lld, %f) min(%lld, %f) max(%lld, %f)",
+ __func__,
device, type,
(long long)item_duration_ns, item_volume,
- (long long)final_duration_ns, final_volume);
+ (long long)final_duration_ns, final_volume,
+ (long long)final_min_volume_duration_ns, final_min_volume,
+ (long long)final_max_volume_duration_ns, final_max_volume);
return true;
}
@@ -208,12 +285,18 @@
sitem->setInt64(AUDIO_POWER_USAGE_PROP_DURATION_NS, duration_ns);
sitem->setInt32(AUDIO_POWER_USAGE_PROP_TYPE, type);
sitem->setDouble(AUDIO_POWER_USAGE_PROP_VOLUME, average_vol);
+ sitem->setInt64(AUDIO_POWER_USAGE_PROP_MIN_VOLUME_DURATION_NS, min_volume_duration_ns);
+ sitem->setDouble(AUDIO_POWER_USAGE_PROP_MIN_VOLUME, min_volume);
+ sitem->setInt64(AUDIO_POWER_USAGE_PROP_MAX_VOLUME_DURATION_NS, max_volume_duration_ns);
+ sitem->setDouble(AUDIO_POWER_USAGE_PROP_MAX_VOLUME, max_volume);
mItems.emplace_back(sitem);
return true;
}
bool AudioPowerUsage::saveAsItems_l(
- int32_t device, int64_t duration_ns, int32_t type, double average_vol)
+ int32_t device, int64_t duration_ns, int32_t type, double average_vol,
+ int64_t max_volume_duration, double max_volume,
+ int64_t min_volume_duration, double min_volume)
{
ALOGV("%s: (%#x, %d, %lld, %f)", __func__, device, type,
(long long)duration_ns, average_vol );
@@ -232,7 +315,9 @@
int32_t tmp_device = device_bits & -device_bits; // get lowest bit
device_bits ^= tmp_device; // clear lowest bit
tmp_device |= input_bit; // restore input bit
- ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol);
+ ret = saveAsItem_l(tmp_device, duration_ns, type, average_vol,
+ max_volume_duration, max_volume,
+ min_volume_duration, min_volume);
ALOGV("%s: device %#x recorded, remaining device_bits = %#x", __func__,
tmp_device, device_bits);
@@ -250,9 +335,28 @@
return;
}
double deviceVolume = 1.;
- if (isTrack && !item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
- return;
+ int64_t maxVolumeDurationNs = 0;
+ double maxVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ int64_t minVolumeDurationNs = 0;
+ double minVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ if (isTrack) {
+ if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEVOLUME, &deviceVolume)) {
+ return;
+ }
+ if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMAXVOLUMEDURATIONNS, &maxVolumeDurationNs)) {
+ return;
+ }
+ if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMAXVOLUME, &maxVolume)) {
+ return;
+ }
+ if (!item->getInt64(AMEDIAMETRICS_PROP_DEVICEMINVOLUMEDURATIONNS, &minVolumeDurationNs)) {
+ return;
+ }
+ if (!item->getDouble(AMEDIAMETRICS_PROP_DEVICEMINVOLUME, &minVolume)) {
+ return;
+ }
}
+
int32_t type = 0;
std::string type_string;
if ((isTrack && mAudioAnalytics->mAnalyticsState->timeMachine().get(
@@ -285,7 +389,8 @@
ALOGV("device = %s => %d", device_strings.c_str(), device);
}
std::lock_guard l(mLock);
- saveAsItems_l(device, deviceTimeNs, type, deviceVolume);
+ saveAsItems_l(device, deviceTimeNs, type, deviceVolume,
+ maxVolumeDurationNs, maxVolume, minVolumeDurationNs, minVolume);
}
void AudioPowerUsage::checkMode(const std::shared_ptr<const mediametrics::Item>& item)
@@ -299,10 +404,17 @@
if (mMode == "AUDIO_MODE_IN_CALL") { // leaving call mode
const int64_t endCallNs = item->getTimestamp();
const int64_t durationNs = endCallNs - mDeviceTimeNs;
+ const int64_t volumeDurationNs = endCallNs - mVolumeTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(endCallNs - mVolumeTimeNs)) / (double)durationNs;
- saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+ mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
+ updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
+ volumeDurationNs, mVoiceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
+ saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
}
} else if (mode == "AUDIO_MODE_IN_CALL") { // entering call mode
mStartCallNs = item->getTimestamp(); // advisory only
@@ -327,10 +439,15 @@
if (mMode == "AUDIO_MODE_IN_CALL") {
const int64_t timeNs = item->getTimestamp();
const int64_t durationNs = timeNs - mDeviceTimeNs;
+ const int64_t volumeDurationNs = timeNs - mVolumeTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(timeNs - mVolumeTimeNs)) / (double)durationNs;
+ mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
mVolumeTimeNs = timeNs;
+ updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
+ volumeDurationNs, mVoiceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
}
}
ALOGV("%s: new voice volume:%lf old voice volume:%lf", __func__, voiceVolume, mVoiceVolume);
@@ -358,15 +475,26 @@
// Save statistics
const int64_t endDeviceNs = item->getTimestamp();
const int64_t durationNs = endDeviceNs - mDeviceTimeNs;
+ const int64_t volumeDurationNs = endDeviceNs - mVolumeTimeNs;
if (durationNs > 0) {
mDeviceVolume = (mDeviceVolume * double(mVolumeTimeNs - mDeviceTimeNs) +
- mVoiceVolume * double(endDeviceNs - mVolumeTimeNs)) / (double)durationNs;
- saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume);
+ mVoiceVolume * double(volumeDurationNs)) / (double)durationNs;
+ updateMinMaxVolumeAndDuration(volumeDurationNs, mVoiceVolume,
+ volumeDurationNs, mVoiceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
+ saveAsItems_l(mPrimaryDevice, durationNs, VOICE_CALL_TYPE, mDeviceVolume,
+ mMaxVoiceVolumeDurationNs, mMaxVoiceVolume,
+ mMinVoiceVolumeDurationNs, mMinVoiceVolume);
}
// reset statistics
mDeviceVolume = 0;
mDeviceTimeNs = endDeviceNs;
mVolumeTimeNs = endDeviceNs;
+ mMaxVoiceVolume = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ mMinVoiceVolume = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ mMaxVoiceVolumeDurationNs = 0;
+ mMinVoiceVolumeDurationNs = 0;
}
ALOGV("%s: new primary device:%#x old primary device:%#x", __func__, device, mPrimaryDevice);
mPrimaryDevice = device;
diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
index 06ab16e..433332c 100644
--- a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
+++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp
@@ -19,15 +19,14 @@
*/
#include <fuzzer/FuzzedDataProvider.h>
#include <media/MediaMetricsItem.h>
+#include <mediametricsservice/AudioTypes.h>
+#include <mediametricsservice/MediaMetricsService.h>
+#include <mediametricsservice/StringUtils.h>
#include <stdio.h>
#include <string.h>
#include <utils/Log.h>
#include <algorithm>
-#include "AudioTypes.h"
-#include "MediaMetricsService.h"
-#include "StringUtils.h"
-
using namespace android;
// low water mark
diff --git a/services/mediametrics/AnalyticsActions.h b/services/mediametrics/include/mediametricsservice/AnalyticsActions.h
similarity index 100%
rename from services/mediametrics/AnalyticsActions.h
rename to services/mediametrics/include/mediametricsservice/AnalyticsActions.h
diff --git a/services/mediametrics/AnalyticsState.h b/services/mediametrics/include/mediametricsservice/AnalyticsState.h
similarity index 100%
rename from services/mediametrics/AnalyticsState.h
rename to services/mediametrics/include/mediametricsservice/AnalyticsState.h
diff --git a/services/mediametrics/AudioAnalytics.h b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
similarity index 100%
rename from services/mediametrics/AudioAnalytics.h
rename to services/mediametrics/include/mediametricsservice/AudioAnalytics.h
diff --git a/services/mediametrics/AudioPowerUsage.h b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
similarity index 80%
rename from services/mediametrics/AudioPowerUsage.h
rename to services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
index 7021902..b7215e6 100644
--- a/services/mediametrics/AudioPowerUsage.h
+++ b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
@@ -26,6 +26,7 @@
namespace android::mediametrics {
+
class AudioAnalytics;
class AudioPowerUsage {
@@ -83,13 +84,21 @@
static bool deviceFromString(const std::string& device_string, int32_t& device);
static int32_t deviceFromStringPairs(const std::string& device_strings);
private:
- bool saveAsItem_l(int32_t device, int64_t duration, int32_t type, double average_vol)
- REQUIRES(mLock);
+ bool saveAsItem_l(int32_t device, int64_t duration, int32_t type, double average_vol,
+ int64_t max_volume_duration, double max_volume,
+ int64_t min_volume_duration, double min_volume)
+ REQUIRES(mLock);
void sendItem(const std::shared_ptr<const mediametrics::Item>& item) const;
void collect();
- bool saveAsItems_l(int32_t device, int64_t duration, int32_t type, double average_vol)
- REQUIRES(mLock);
-
+ bool saveAsItems_l(int32_t device, int64_t duration, int32_t type, double average_vol,
+ int64_t max_volume_duration, double max_volume,
+ int64_t min_volume_duration, double min_volume)
+ REQUIRES(mLock);
+ void updateMinMaxVolumeAndDuration(
+ const int64_t cur_max_volume_duration_ns, const double cur_max_volume,
+ const int64_t cur_min_volume_duration_ns, const double cur_min_volume,
+ int64_t& f_max_volume_duration_ns, double& f_max_volume,
+ int64_t& f_min_volume_duration_ns, double& f_min_volume);
AudioAnalytics * const mAudioAnalytics;
const std::shared_ptr<StatsdLog> mStatsdLog; // mStatsdLog is internally locked
const bool mDisabled;
@@ -100,6 +109,10 @@
double mVoiceVolume GUARDED_BY(mLock) = 0.;
double mDeviceVolume GUARDED_BY(mLock) = 0.;
+ double mMaxVoiceVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MAX_VOLUME;
+ double mMinVoiceVolume GUARDED_BY(mLock) = AMEDIAMETRICS_INITIAL_MIN_VOLUME;
+ int64_t mMaxVoiceVolumeDurationNs GUARDED_BY(mLock) = 0;
+ int64_t mMinVoiceVolumeDurationNs GUARDED_BY(mLock) = 0;
int64_t mStartCallNs GUARDED_BY(mLock) = 0; // advisory only
int64_t mVolumeTimeNs GUARDED_BY(mLock) = 0;
int64_t mDeviceTimeNs GUARDED_BY(mLock) = 0;
diff --git a/services/mediametrics/AudioTypes.h b/services/mediametrics/include/mediametricsservice/AudioTypes.h
similarity index 100%
rename from services/mediametrics/AudioTypes.h
rename to services/mediametrics/include/mediametricsservice/AudioTypes.h
diff --git a/services/mediametrics/HeatMap.h b/services/mediametrics/include/mediametricsservice/HeatMap.h
similarity index 100%
rename from services/mediametrics/HeatMap.h
rename to services/mediametrics/include/mediametricsservice/HeatMap.h
diff --git a/services/mediametrics/LruSet.h b/services/mediametrics/include/mediametricsservice/LruSet.h
similarity index 100%
rename from services/mediametrics/LruSet.h
rename to services/mediametrics/include/mediametricsservice/LruSet.h
diff --git a/services/mediametrics/MediaMetricsService.h b/services/mediametrics/include/mediametricsservice/MediaMetricsService.h
similarity index 100%
rename from services/mediametrics/MediaMetricsService.h
rename to services/mediametrics/include/mediametricsservice/MediaMetricsService.h
diff --git a/services/mediametrics/StatsdLog.h b/services/mediametrics/include/mediametricsservice/StatsdLog.h
similarity index 100%
rename from services/mediametrics/StatsdLog.h
rename to services/mediametrics/include/mediametricsservice/StatsdLog.h
diff --git a/services/mediametrics/StringUtils.h b/services/mediametrics/include/mediametricsservice/StringUtils.h
similarity index 100%
rename from services/mediametrics/StringUtils.h
rename to services/mediametrics/include/mediametricsservice/StringUtils.h
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/include/mediametricsservice/TimeMachine.h
similarity index 100%
rename from services/mediametrics/TimeMachine.h
rename to services/mediametrics/include/mediametricsservice/TimeMachine.h
diff --git a/services/mediametrics/TimedAction.h b/services/mediametrics/include/mediametricsservice/TimedAction.h
similarity index 100%
rename from services/mediametrics/TimedAction.h
rename to services/mediametrics/include/mediametricsservice/TimedAction.h
diff --git a/services/mediametrics/TransactionLog.h b/services/mediametrics/include/mediametricsservice/TransactionLog.h
similarity index 100%
rename from services/mediametrics/TransactionLog.h
rename to services/mediametrics/include/mediametricsservice/TransactionLog.h
diff --git a/services/mediametrics/ValidateId.h b/services/mediametrics/include/mediametricsservice/ValidateId.h
similarity index 100%
rename from services/mediametrics/ValidateId.h
rename to services/mediametrics/include/mediametricsservice/ValidateId.h
diff --git a/services/mediametrics/Wrap.h b/services/mediametrics/include/mediametricsservice/Wrap.h
similarity index 100%
rename from services/mediametrics/Wrap.h
rename to services/mediametrics/include/mediametricsservice/Wrap.h
diff --git a/services/mediametrics/cleaner.h b/services/mediametrics/include/mediametricsservice/cleaner.h
similarity index 100%
rename from services/mediametrics/cleaner.h
rename to services/mediametrics/include/mediametricsservice/cleaner.h
diff --git a/services/mediametrics/iface_statsd.h b/services/mediametrics/include/mediametricsservice/iface_statsd.h
similarity index 100%
rename from services/mediametrics/iface_statsd.h
rename to services/mediametrics/include/mediametricsservice/iface_statsd.h
diff --git a/services/mediametrics/main_mediametrics.cpp b/services/mediametrics/main_mediametrics.cpp
index 3a66538..455d67a 100644
--- a/services/mediametrics/main_mediametrics.cpp
+++ b/services/mediametrics/main_mediametrics.cpp
@@ -18,11 +18,10 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
-#include "MediaMetricsService.h"
-
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
+#include <mediametricsservice/MediaMetricsService.h>
#include <mediautils/LimitProcessMemory.h>
int main(int argc __unused, char **argv)
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
index 102700a..bc7b47b 100644
--- a/services/mediametrics/tests/mediametrics_tests.cpp
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -17,19 +17,18 @@
#define LOG_TAG "mediametrics_tests"
#include <utils/Log.h>
-#include "MediaMetricsService.h"
#include <stdio.h>
#include <unordered_set>
#include <gtest/gtest.h>
#include <media/MediaMetricsItem.h>
+#include <mediametricsservice/AudioTypes.h>
+#include <mediametricsservice/MediaMetricsService.h>
+#include <mediametricsservice/StringUtils.h>
+#include <mediametricsservice/ValidateId.h>
#include <system/audio.h>
-#include "AudioTypes.h"
-#include "StringUtils.h"
-#include "ValidateId.h"
-
using namespace android;
static size_t countNewlines(const char *s) {
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index bc769f0..95bd4bb 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -66,8 +66,7 @@
getFramesPerBurst(), timeoutNanos);
if (result == AAUDIO_ERROR_DISCONNECTED) {
ALOGD("%s() read() returned AAUDIO_ERROR_DISCONNECTED", __func__);
- // We do not need the returned vector.
- (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
+ AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync();
break;
} else if (result != getFramesPerBurst()) {
ALOGW("callbackLoop() read %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index f590fc8..2a5939f 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -147,8 +147,7 @@
getFramesPerBurst(), timeoutNanos);
if (result == AAUDIO_ERROR_DISCONNECTED) {
ALOGD("%s() write() returned AAUDIO_ERROR_DISCONNECTED", __func__);
- // We do not need the returned vector.
- (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
+ AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync();
break;
} else if (result != getFramesPerBurst()) {
ALOGW("callbackLoop() wrote %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 5af0a91..dd421fe 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -214,3 +214,12 @@
}
return result;
}
+
+void AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync() {
+ android::sp<AAudioServiceEndpointShared> holdEndpoint(this);
+ std::thread asyncTask([holdEndpoint]() {
+ // We do not need the returned vector.
+ holdEndpoint->disconnectRegisteredStreams();
+ });
+ asyncTask.detach();
+}
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index 8357567..3e760c4 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -69,6 +69,8 @@
aaudio_result_t stopSharingThread();
+ void handleDisconnectRegisteredStreamsAsync();
+
// An MMAP stream that is shared by multiple clients.
android::sp<AudioStreamInternal> mStreamInternal;
diff --git a/services/tuner/TunerFrontend.cpp b/services/tuner/TunerFrontend.cpp
index a5ef2bb..5116305 100644
--- a/services/tuner/TunerFrontend.cpp
+++ b/services/tuner/TunerFrontend.cpp
@@ -174,6 +174,28 @@
return mFrontend->getHardwareInfo(_aidl_return);
}
+::ndk::ScopedAStatus TunerFrontend::removeOutputPid(int32_t in_pid) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ return mFrontend->removeOutputPid(in_pid);
+}
+
+::ndk::ScopedAStatus TunerFrontend::getFrontendStatusReadiness(
+ const std::vector<FrontendStatusType>& in_statusTypes,
+ std::vector<FrontendStatusReadiness>* _aidl_return) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ return mFrontend->getFrontendStatusReadiness(in_statusTypes, _aidl_return);
+}
+
/////////////// FrontendCallback ///////////////////////
::ndk::ScopedAStatus TunerFrontend::FrontendCallback::onEvent(FrontendEventType frontendEventType) {
ALOGV("FrontendCallback::onEvent, type=%d", frontendEventType);
diff --git a/services/tuner/TunerFrontend.h b/services/tuner/TunerFrontend.h
index 418a751..da471fb 100644
--- a/services/tuner/TunerFrontend.h
+++ b/services/tuner/TunerFrontend.h
@@ -30,6 +30,7 @@
using ::aidl::android::hardware::tv::tuner::FrontendScanType;
using ::aidl::android::hardware::tv::tuner::FrontendSettings;
using ::aidl::android::hardware::tv::tuner::FrontendStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusReadiness;
using ::aidl::android::hardware::tv::tuner::FrontendStatusType;
using ::aidl::android::hardware::tv::tuner::IFrontend;
using ::aidl::android::hardware::tv::tuner::IFrontendCallback;
@@ -63,6 +64,10 @@
vector<FrontendStatus>* _aidl_return) override;
::ndk::ScopedAStatus getFrontendId(int32_t* _aidl_return) override;
::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus removeOutputPid(int32_t in_pid) override;
+ ::ndk::ScopedAStatus getFrontendStatusReadiness(
+ const std::vector<FrontendStatusType>& in_statusTypes,
+ std::vector<FrontendStatusReadiness>* _aidl_return) override;
struct FrontendCallback : public BnFrontendCallback {
FrontendCallback(const shared_ptr<ITunerFrontendCallback> tunerFrontendCallback)
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
index 96f285f..0493f05 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
@@ -19,6 +19,7 @@
import android.hardware.tv.tuner.FrontendScanType;
import android.hardware.tv.tuner.FrontendSettings;
import android.hardware.tv.tuner.FrontendStatus;
+import android.hardware.tv.tuner.FrontendStatusReadiness;
import android.hardware.tv.tuner.FrontendStatusType;
import android.media.tv.tuner.ITunerFrontendCallback;
import android.media.tv.tuner.ITunerLnb;
@@ -99,4 +100,14 @@
* Request hardware information about the frontend.
*/
String getHardwareInfo();
+
+ /**
+ * Filter out unnecessary PID from frontend output.
+ */
+ void removeOutputPid(int pid);
+
+ /**
+ * Gets FrontendStatus’ readiness statuses for given status types.
+ */
+ FrontendStatusReadiness[] getFrontendStatusReadiness(in FrontendStatusType[] statusTypes);
}
diff --git a/services/tuner/hidl/TunerHidlFrontend.cpp b/services/tuner/hidl/TunerHidlFrontend.cpp
index 057f24a..03957f3 100644
--- a/services/tuner/hidl/TunerHidlFrontend.cpp
+++ b/services/tuner/hidl/TunerHidlFrontend.cpp
@@ -428,6 +428,19 @@
static_cast<int32_t>(Result::UNAVAILABLE));
}
+::ndk::ScopedAStatus TunerHidlFrontend::removeOutputPid(int32_t /* in_pid */) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+}
+
+::ndk::ScopedAStatus TunerHidlFrontend::getFrontendStatusReadiness(
+ const std::vector<FrontendStatusType>& /* in_statusTypes */,
+ std::vector<FrontendStatusReadiness>* _aidl_return) {
+ _aidl_return->clear();
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+}
+
void TunerHidlFrontend::setLna(bool bEnable) {
if (mFrontend == nullptr) {
ALOGD("IFrontend is not initialized");
diff --git a/services/tuner/hidl/TunerHidlFrontend.h b/services/tuner/hidl/TunerHidlFrontend.h
index 7ff278c..f698655 100644
--- a/services/tuner/hidl/TunerHidlFrontend.h
+++ b/services/tuner/hidl/TunerHidlFrontend.h
@@ -32,6 +32,7 @@
using ::aidl::android::hardware::tv::tuner::FrontendScanType;
using ::aidl::android::hardware::tv::tuner::FrontendSettings;
using ::aidl::android::hardware::tv::tuner::FrontendStatus;
+using ::aidl::android::hardware::tv::tuner::FrontendStatusReadiness;
using ::aidl::android::hardware::tv::tuner::FrontendStatusType;
using ::android::sp;
using ::android::hardware::hidl_vec;
@@ -83,6 +84,10 @@
vector<FrontendStatus>* _aidl_return) override;
::ndk::ScopedAStatus getFrontendId(int32_t* _aidl_return) override;
::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus removeOutputPid(int32_t in_pid) override;
+ ::ndk::ScopedAStatus getFrontendStatusReadiness(
+ const std::vector<FrontendStatusType>& in_statusTypes,
+ std::vector<FrontendStatusReadiness>* _aidl_return) override;
void setLna(bool in_bEnable);