Merge "AudioFlinger: improve logging for moveEffectChain_l"
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/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 71df58c..6e1e10b 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -28,7 +28,11 @@
"DrmSessionManager.cpp",
"SharedLibrary.cpp",
"DrmHal.cpp",
+ "DrmHalHidl.cpp",
+ "DrmHalAidl.cpp",
"CryptoHal.cpp",
+ "CryptoHalHidl.cpp",
+ "CryptoHalAidl.cpp",
"DrmUtils.cpp",
],
@@ -63,10 +67,12 @@
"android.hardware.drm@1.4",
"libhidlallocatorutils",
"libhidlbase",
+ "android.hardware.drm-V1-ndk",
],
static_libs: [
"resourcemanager_aidl_interface-ndk",
+ "libaidlcommonsupport",
],
export_shared_lib_headers: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index e0db1c4..f95d527 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -16,389 +16,100 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "CryptoHal"
-#include <utils/Log.h>
-
-#include <android/hardware/drm/1.0/types.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-#include <hidlmemory/FrameworkUtils.h>
-#include <media/hardware/CryptoAPI.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaErrors.h>
#include <mediadrm/CryptoHal.h>
+#include <mediadrm/CryptoHalHidl.h>
+#include <mediadrm/CryptoHalAidl.h>
#include <mediadrm/DrmUtils.h>
-using drm::V1_0::BufferType;
-using drm::V1_0::DestinationBuffer;
-using drm::V1_0::ICryptoFactory;
-using drm::V1_0::ICryptoPlugin;
-using drm::V1_0::Mode;
-using drm::V1_0::Pattern;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-
-using ::android::DrmUtils::toStatusT;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::HidlMemory;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-typedef drm::V1_2::Status Status_V1_2;
-
namespace android {
-static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
- hidl_vec<uint8_t> vec;
- vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
- return vec;
+CryptoHal::CryptoHal() {
+ mCryptoHalAidl = sp<CryptoHalAidl>::make();
+ mCryptoHalHidl = sp<CryptoHalHidl>::make();
}
-static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
- hidl_vec<uint8_t> vec;
- vec.resize(size);
- memcpy(vec.data(), ptr, size);
- return vec;
-}
-
-static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
- if (!ptr) {
- return hidl_array<uint8_t, 16>();
- }
- return hidl_array<uint8_t, 16>(ptr);
-}
-
-
-static String8 toString8(hidl_string hString) {
- return String8(hString.c_str());
-}
-
-
-CryptoHal::CryptoHal()
- : mFactories(makeCryptoFactories()),
- mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
- mHeapSeqNum(0) {
-}
-
-CryptoHal::~CryptoHal() {
-}
-
-Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
- Vector<sp<ICryptoFactory>> factories;
-
- auto manager = hardware::defaultServiceManager1_2();
- if (manager != NULL) {
- manager->listManifestByInterface(drm::V1_0::ICryptoFactory::descriptor,
- [&factories](const hidl_vec<hidl_string> ®istered) {
- for (const auto &instance : registered) {
- auto factory = drm::V1_0::ICryptoFactory::getService(instance);
- if (factory != NULL) {
- ALOGD("found drm@1.0 ICryptoFactory %s", instance.c_str());
- factories.push_back(factory);
- }
- }
- }
- );
- manager->listManifestByInterface(drm::V1_1::ICryptoFactory::descriptor,
- [&factories](const hidl_vec<hidl_string> ®istered) {
- for (const auto &instance : registered) {
- auto factory = drm::V1_1::ICryptoFactory::getService(instance);
- if (factory != NULL) {
- ALOGD("found drm@1.1 ICryptoFactory %s", instance.c_str());
- factories.push_back(factory);
- }
- }
- }
- );
- }
-
- if (factories.size() == 0) {
- // must be in passthrough mode, load the default passthrough service
- auto passthrough = ICryptoFactory::getService();
- if (passthrough != NULL) {
- ALOGI("makeCryptoFactories: using default passthrough crypto instance");
- factories.push_back(passthrough);
- } else {
- ALOGE("Failed to find any crypto factories");
- }
- }
- return factories;
-}
-
-sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory,
- const uint8_t uuid[16], const void *initData, size_t initDataSize) {
-
- sp<ICryptoPlugin> plugin;
- Return<void> hResult = factory->createPlugin(toHidlArray16(uuid),
- toHidlVec(initData, initDataSize),
- [&](Status status, const sp<ICryptoPlugin>& hPlugin) {
- if (status != Status::OK) {
- ALOGE("Failed to make crypto plugin");
- return;
- }
- plugin = hPlugin;
- }
- );
- if (!hResult.isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- return plugin;
-}
-
+CryptoHal::~CryptoHal() {}
status_t CryptoHal::initCheck() const {
- return mInitCheck;
+ if (mCryptoHalAidl->initCheck() == OK || mCryptoHalHidl->initCheck() == OK) return OK;
+ if (mCryptoHalAidl->initCheck() == NO_INIT || mCryptoHalHidl->initCheck() == NO_INIT)
+ return NO_INIT;
+ return mCryptoHalHidl->initCheck();
}
-
bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
- Mutex::Autolock autoLock(mLock);
-
- for (size_t i = 0; i < mFactories.size(); i++) {
- if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
- return true;
- }
- }
- return false;
+ return mCryptoHalAidl->isCryptoSchemeSupported(uuid) ||
+ mCryptoHalHidl->isCryptoSchemeSupported(uuid);
}
-status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data,
- size_t size) {
- Mutex::Autolock autoLock(mLock);
-
- for (size_t i = 0; i < mFactories.size(); i++) {
- if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
- mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
- if (mPlugin != NULL) {
- mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
- }
- }
- }
-
- if (mInitCheck == NO_INIT) {
- mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
- }
-
- return mInitCheck;
+status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
+ if (mCryptoHalAidl->createPlugin(uuid, data, size) != OK)
+ return mCryptoHalHidl->createPlugin(uuid, data, size);
+ return OK;
}
status_t CryptoHal::destroyPlugin() {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- mPlugin.clear();
- mPluginV1_2.clear();
- return OK;
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->destroyPlugin();
+ return mCryptoHalHidl->destroyPlugin();
}
-bool CryptoHal::requiresSecureDecoderComponent(const char *mime) const {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return false;
- }
-
- Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
- if (!hResult.isOk()) {
- return false;
- }
- return hResult;
-}
-
-
-/**
- * If the heap base isn't set, get the heap base from the HidlMemory
- * and send it to the HAL so it can map a remote heap of the same
- * size. Once the heap base is established, shared memory buffers
- * are sent by providing an offset into the heap and a buffer size.
- */
-int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) {
- if (heap == NULL || mHeapSeqNum < 0) {
- ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
- return -1;
- }
-
- Mutex::Autolock autoLock(mLock);
-
- int32_t seqNum = mHeapSeqNum++;
- uint32_t bufferId = static_cast<uint32_t>(seqNum);
- mHeapSizes.add(seqNum, heap->size());
- Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
- ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
- return seqNum;
-}
-
-void CryptoHal::clearHeapBase(int32_t seqNum) {
- Mutex::Autolock autoLock(mLock);
-
- /*
- * Clear the remote shared memory mapping by setting the shared
- * buffer base to a null hidl_memory.
- *
- * TODO: Add a releaseSharedBuffer method in a future DRM HAL
- * API version to make this explicit.
- */
- ssize_t index = mHeapSizes.indexOfKey(seqNum);
- if (index >= 0) {
- if (mPlugin != NULL) {
- uint32_t bufferId = static_cast<uint32_t>(seqNum);
- Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
- ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
- }
- mHeapSizes.removeItem(seqNum);
- }
-}
-
-status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) {
- int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
- // memory must be in one of the heaps that have been set
- if (mHeapSizes.indexOfKey(seqNum) < 0) {
- return UNKNOWN_ERROR;
- }
-
- // memory must be within the address space of the heap
- size_t heapSize = mHeapSizes.valueFor(seqNum);
- if (heapSize < buffer.offset + buffer.size ||
- SIZE_MAX - buffer.offset < buffer.size) {
- android_errorWriteLog(0x534e4554, "76221123");
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
-ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
- CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const ::SharedBuffer &hSource, size_t offset,
- const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const ::DestinationBuffer &hDestination, AString *errorDetailMsg) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- Mode hMode;
- switch(mode) {
- case CryptoPlugin::kMode_Unencrypted:
- hMode = Mode::UNENCRYPTED ;
- break;
- case CryptoPlugin::kMode_AES_CTR:
- hMode = Mode::AES_CTR;
- break;
- case CryptoPlugin::kMode_AES_WV:
- hMode = Mode::AES_CBC_CTS;
- break;
- case CryptoPlugin::kMode_AES_CBC:
- hMode = Mode::AES_CBC;
- break;
- default:
- return UNKNOWN_ERROR;
- }
-
- Pattern hPattern;
- hPattern.encryptBlocks = pattern.mEncryptBlocks;
- hPattern.skipBlocks = pattern.mSkipBlocks;
-
- std::vector<SubSample> stdSubSamples;
- for (size_t i = 0; i < numSubSamples; i++) {
- SubSample subSample;
- subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
- subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
- stdSubSamples.push_back(subSample);
- }
- auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
-
- bool secure;
- if (hDestination.type == BufferType::SHARED_MEMORY) {
- status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
- if (status != OK) {
- return status;
- }
- secure = false;
- } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
- secure = true;
- } else {
- android_errorWriteLog(0x534e4554, "70526702");
- return UNKNOWN_ERROR;
- }
-
- status_t status = checkSharedBuffer(hSource);
- if (status != OK) {
- return status;
- }
-
- status_t err = UNKNOWN_ERROR;
- uint32_t bytesWritten = 0;
-
- Return<void> hResult;
-
- mLock.unlock();
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv),
- hMode, hPattern, hSubSamples, hSource, offset, hDestination,
- [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
- if (status == Status_V1_2::OK) {
- bytesWritten = hBytesWritten;
- *errorDetailMsg = toString8(hDetailedError);
- }
- err = toStatusT(status);
- }
- );
- } else {
- hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv),
- hMode, hPattern, hSubSamples, hSource, offset, hDestination,
- [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
- if (status == Status::OK) {
- bytesWritten = hBytesWritten;
- *errorDetailMsg = toString8(hDetailedError);
- }
- err = toStatusT(status);
- }
- );
- }
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- if (err == OK) {
- return bytesWritten;
- }
- return err;
+bool CryptoHal::requiresSecureDecoderComponent(const char* mime) const {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK)
+ return mCryptoHalAidl->requiresSecureDecoderComponent(mime);
+ return mCryptoHalHidl->requiresSecureDecoderComponent(mime);
}
void CryptoHal::notifyResolution(uint32_t width, uint32_t height) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) {
+ mCryptoHalAidl->notifyResolution(width, height);
return;
}
- auto hResult = mPlugin->notifyResolution(width, height);
- ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
+ mCryptoHalHidl->notifyResolution(width, height);
}
-status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t> &sessionId) {
- Mutex::Autolock autoLock(mLock);
+status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
+ return mCryptoHalHidl->setMediaDrmSession(sessionId);
+}
- if (mInitCheck != OK) {
- return mInitCheck;
+ssize_t CryptoHal::decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
+ const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
+ size_t offset, const CryptoPlugin::SubSample* subSamples,
+ size_t numSubSamples, const ::DestinationBuffer& destination,
+ AString* errorDetailMsg) {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK)
+ return mCryptoHalAidl->decrypt(key, iv, mode, pattern, source, offset, subSamples,
+ numSubSamples, destination, errorDetailMsg);
+ return mCryptoHalHidl->decrypt(key, iv, mode, pattern, source, offset, subSamples,
+ numSubSamples, destination, errorDetailMsg);
+}
+
+int32_t CryptoHal::setHeap(const sp<HidlMemory>& heap) {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setHeap(heap);
+ return mCryptoHalHidl->setHeap(heap);
+}
+
+void CryptoHal::unsetHeap(int32_t seqNum) {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) {
+ mCryptoHalAidl->unsetHeap(seqNum);
+ return;
}
- auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId));
- return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+ mCryptoHalHidl->unsetHeap(seqNum);
}
-status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
- Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs);
+status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->getLogMessages(logs);
+ return mCryptoHalHidl->getLogMessages(logs);
}
-} // namespace android
+
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
new file mode 100644
index 0000000..a688728
--- /dev/null
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -0,0 +1,409 @@
+/*
+ * 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 "CryptoHalAidl"
+
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/CryptoHalAidl.h>
+#include <mediadrm/DrmUtils.h>
+
+using ::aidl::android::hardware::drm::BufferType;
+using ::aidl::android::hardware::drm::DecryptResult;
+using DestinationBufferAidl = ::aidl::android::hardware::drm::DestinationBuffer;
+using ::aidl::android::hardware::drm::Mode;
+using ::aidl::android::hardware::drm::Pattern;
+using SharedBufferAidl = ::aidl::android::hardware::drm::SharedBuffer;
+using ::aidl::android::hardware::drm::Status;
+using ::aidl::android::hardware::drm::SubSample;
+using ::aidl::android::hardware::drm::Uuid;
+
+using ::aidl::android::hardware::common::Ashmem;
+
+using ::android::sp;
+using ::android::DrmUtils::toStatusTAidl;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::HidlMemory;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::aidl::android::hardware::drm::Uuid;
+// -------Hidl interface related-----------------
+// TODO: replace before removing hidl interface
+
+using BufferTypeHidl = ::android::hardware::drm::V1_0::BufferType;
+using SharedBufferHidl = ::android::hardware::drm::V1_0::SharedBuffer;
+using DestinationBufferHidl = ::android::hardware::drm::V1_0::DestinationBuffer;
+
+// -------Hidl interface related end-------------
+
+namespace android {
+
+static Uuid toAidlUuid(const uint8_t* uuid) {
+ Uuid uuidAidl;
+ uuidAidl.uuid = std::vector<uint8_t>(uuid, uuid + 16);
+ return uuidAidl;
+}
+
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t>& vector) {
+ auto v = reinterpret_cast<const Byte*>(vector.array());
+ std::vector<Byte> vec(v, v + vector.size());
+ return vec;
+}
+
+// -------Hidl interface related-----------------
+// TODO: replace before removing hidl interface
+status_t CryptoHalAidl::checkSharedBuffer(const SharedBufferHidl& buffer) {
+ int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
+ // memory must be in one of the heaps that have been set
+ if (mHeapSizes.indexOfKey(seqNum) < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ // memory must be within the address space of the heap
+ size_t heapSize = mHeapSizes.valueFor(seqNum);
+ if (heapSize < buffer.offset + buffer.size || SIZE_MAX - buffer.offset < buffer.size) {
+ android_errorWriteLog(0x534e4554, "76221123");
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+static SharedBufferAidl hidlSharedBufferToAidlSharedBuffer(const SharedBufferHidl& buffer) {
+ SharedBufferAidl aidlsb;
+ aidlsb.bufferId = buffer.bufferId;
+ aidlsb.offset = buffer.offset;
+ aidlsb.size = buffer.size;
+ return aidlsb;
+}
+
+static DestinationBufferAidl hidlDestinationBufferToAidlDestinationBuffer(
+ const DestinationBufferHidl& buffer) {
+ DestinationBufferAidl aidldb;
+ // skip negative convert check as count of enum elements are 2
+ aidldb.type = static_cast<BufferType>((int32_t)buffer.type);
+ aidldb.nonsecureMemory = hidlSharedBufferToAidlSharedBuffer(buffer.nonsecureMemory);
+ aidldb.secureMemory = ::android::makeToAidl(buffer.secureMemory.getNativeHandle());
+ return aidldb;
+}
+
+static hidl_vec<uint8_t> toHidlVec(const void* ptr, size_t size) {
+ hidl_vec<uint8_t> vec;
+ vec.resize(size);
+ memcpy(vec.data(), ptr, size);
+ return vec;
+}
+
+static const Vector<uint8_t> toVector(const std::vector<uint8_t>& vec) {
+ Vector<uint8_t> vector;
+ vector.appendArray(vec.data(), vec.size());
+ return *const_cast<const Vector<uint8_t>*>(&vector);
+}
+
+static String8 toString8(const std::string& string) {
+ return String8(string.c_str());
+}
+
+// -------Hidl interface related end--------------
+
+CryptoHalAidl::CryptoHalAidl()
+ : mFactories(makeCryptoFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
+ mHeapSeqNum(0) {}
+
+CryptoHalAidl::~CryptoHalAidl() {}
+
+std::vector<std::shared_ptr<ICryptoFactoryAidl>> CryptoHalAidl::makeCryptoFactories() {
+ std::vector<std::shared_ptr<ICryptoFactoryAidl>> factories;
+ AServiceManager_forEachDeclaredInstance(
+ ICryptoFactoryAidl::descriptor, static_cast<void*>(&factories),
+ [](const char* instance, void* context) {
+ auto fullName = std::string(ICryptoFactoryAidl::descriptor) + "/" + std::string(instance);
+ auto factory = ICryptoFactoryAidl::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_getService(fullName.c_str())));
+ if (factory == nullptr) {
+ ALOGE("not found ICryptoFactoryAidl. Instance name:[%s]", fullName.c_str());
+ return;
+ }
+
+ ALOGI("found ICryptoFactoryAidl. Instance name:[%s]", fullName.c_str());
+ static_cast<std::vector<std::shared_ptr<ICryptoFactoryAidl>>*>(context)
+ ->emplace_back(factory);
+ });
+
+ return factories;
+}
+
+status_t CryptoHalAidl::initCheck() const {
+ return mInitCheck;
+}
+
+bool CryptoHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+
+ bool isSupported = false;
+ Uuid uuidAidl = toAidlUuid(uuid);
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuidAidl, &isSupported).isOk()) {
+ if (isSupported) break;
+ }
+ }
+ return isSupported;
+}
+
+status_t CryptoHalAidl::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ bool isSupported = false;
+ Uuid uuidAidl = toAidlUuid(uuid);
+ std::vector<uint8_t> dataAidl = toStdVec(toVector(toHidlVec(data, size)));
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuidAidl, &isSupported).isOk() && isSupported) {
+ mPlugin = makeCryptoPlugin(mFactories[i], uuidAidl, dataAidl);
+ // Reserve place for future plugins with new versions
+
+ break;
+ }
+ }
+
+ if (mInitCheck == NO_INIT) {
+ mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
+ }
+
+ return mInitCheck;
+}
+
+std::shared_ptr<ICryptoPluginAidl> CryptoHalAidl::makeCryptoPlugin(
+ const std::shared_ptr<ICryptoFactoryAidl>& factory, const Uuid& uuidAidl,
+ const std::vector<uint8_t> initData) {
+ std::shared_ptr<ICryptoPluginAidl> pluginAidl;
+ if (factory->createPlugin(uuidAidl, initData, &pluginAidl).isOk()) {
+ ALOGI("Create ICryptoPluginAidl. UUID:[%s]", uuidAidl.toString().c_str());
+ } else {
+ mInitCheck = DEAD_OBJECT;
+ ALOGE("Failed to create ICryptoPluginAidl. UUID:[%s]", uuidAidl.toString().c_str());
+ }
+
+ return pluginAidl;
+}
+
+status_t CryptoHalAidl::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ mPlugin.reset();
+ return OK;
+}
+
+bool CryptoHalAidl::requiresSecureDecoderComponent(const char* mime) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return false;
+ }
+
+ std::string mimeStr = std::string(mime);
+ bool result;
+ if (!mPlugin->requiresSecureDecoderComponent(mimeStr, &result).isOk()) {
+ ALOGE("Failed to requiresSecureDecoderComponent. mime:[%s]", mime);
+ return false;
+ }
+
+ return result;
+}
+
+void CryptoHalAidl::notifyResolution(uint32_t width, uint32_t height) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ // Check negative width and height after type conversion
+ // Log error and return if any is negative
+ if ((int32_t)width < 0 || (int32_t)height < 0) {
+ ALOGE("Negative width: %d or height %d in notifyResolution", width, height);
+ return;
+ }
+
+ ::ndk::ScopedAStatus status = mPlugin->notifyResolution(width, height);
+ if (!status.isOk()) {
+ ALOGE("notifyResolution txn failed status code: %d", status.getServiceSpecificError());
+ }
+}
+
+status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ auto err = mPlugin->setMediaDrmSession(toStdVec(sessionId));
+ return err.isOk() ? toStatusTAidl(err.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+ssize_t CryptoHalAidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern,
+ const SharedBufferHidl& hSource, size_t offset,
+ const CryptoPlugin::SubSample* subSamples, size_t numSubSamples,
+ const DestinationBufferHidl& hDestination, AString* errorDetailMsg) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ Mode aMode;
+ switch (mode) {
+ case CryptoPlugin::kMode_Unencrypted:
+ aMode = Mode::UNENCRYPTED;
+ break;
+ case CryptoPlugin::kMode_AES_CTR:
+ aMode = Mode::AES_CTR;
+ break;
+ case CryptoPlugin::kMode_AES_WV:
+ aMode = Mode::AES_CBC_CTS;
+ break;
+ case CryptoPlugin::kMode_AES_CBC:
+ aMode = Mode::AES_CBC;
+ break;
+ default:
+ return UNKNOWN_ERROR;
+ }
+
+ Pattern aPattern;
+ aPattern.encryptBlocks = pattern.mEncryptBlocks;
+ aPattern.skipBlocks = pattern.mSkipBlocks;
+
+ std::vector<SubSample> stdSubSamples;
+ for (size_t i = 0; i < numSubSamples; i++) {
+ SubSample subSample;
+ subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
+ subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
+ stdSubSamples.push_back(subSample);
+ }
+
+ bool secure;
+ if (hDestination.type == BufferTypeHidl::SHARED_MEMORY) {
+ status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
+ if (status != OK) {
+ return status;
+ }
+ secure = false;
+ } else if (hDestination.type == BufferTypeHidl::NATIVE_HANDLE) {
+ secure = true;
+ } else {
+ android_errorWriteLog(0x534e4554, "70526702");
+ return UNKNOWN_ERROR;
+ }
+
+ status_t status = checkSharedBuffer(hSource);
+ if (status != OK) {
+ return status;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+ mLock.unlock();
+
+ std::vector<uint8_t> keyIdAidl = std::vector<uint8_t>(keyId, keyId + 16);
+ std::vector<uint8_t> ivAidl = std::vector<uint8_t>(iv, iv + 16);
+ DecryptResult result;
+ err = mPlugin->decrypt(secure, keyIdAidl, ivAidl, aMode, aPattern, stdSubSamples,
+ hidlSharedBufferToAidlSharedBuffer(hSource), offset,
+ hidlDestinationBufferToAidlDestinationBuffer(hDestination), &result)
+ .isOk()
+ ? OK
+ : DEAD_OBJECT;
+
+ *errorDetailMsg = toString8(result.detailedError);
+ if (err != OK) {
+ ALOGE("Failed on decrypt, error message:%s, bytes written:%d", result.detailedError.c_str(),
+ result.bytesWritten);
+ return err;
+ }
+
+ return result.bytesWritten;
+}
+
+int32_t CryptoHalAidl::setHeap(const sp<HidlMemory>& heap) {
+ if (heap == NULL || mHeapSeqNum < 0) {
+ ALOGE("setHeap(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
+ return -1;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+
+ int32_t seqNum = mHeapSeqNum++;
+ uint32_t bufferId = static_cast<uint32_t>(seqNum);
+ mHeapSizes.add(seqNum, heap->size());
+
+ Ashmem memAidl;
+ memAidl.fd.set(heap->handle()->data[0]);
+ memAidl.size = heap->size();
+
+ ALOGE_IF(!mPlugin->setSharedBufferBase(memAidl, bufferId).isOk(),
+ "setSharedBufferBase(): remote call failed");
+ return seqNum;
+}
+
+void CryptoHalAidl::unsetHeap(int32_t seqNum) {
+ Mutex::Autolock autoLock(mLock);
+
+ /*
+ * Clear the remote shared memory mapping by setting the shared
+ * buffer base to a null hidl_memory.
+ *
+ * TODO: Add a releaseSharedBuffer method in a future DRM HAL
+ * API version to make this explicit.
+ */
+ ssize_t index = mHeapSizes.indexOfKey(seqNum);
+ if (index >= 0) {
+ if (mPlugin != NULL) {
+ uint32_t bufferId = static_cast<uint32_t>(seqNum);
+ Ashmem memAidl;
+ memAidl.fd.set(-1);
+ memAidl.size = 0;
+ ALOGE_IF(!mPlugin->setSharedBufferBase(memAidl, bufferId).isOk(),
+ "setSharedBufferBase(): remote call failed");
+ }
+ mHeapSizes.removeItem(seqNum);
+ }
+}
+
+status_t CryptoHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ // Need to convert logmessage
+
+ return DrmUtils::GetLogMessagesAidl<ICryptoPluginAidl>(mPlugin, logs);
+}
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/CryptoHalHidl.cpp b/drm/libmediadrm/CryptoHalHidl.cpp
new file mode 100644
index 0000000..cbb6ddf
--- /dev/null
+++ b/drm/libmediadrm/CryptoHalHidl.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2017 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 "CryptoHalHidl"
+#include <utils/Log.h>
+
+#include <android/hardware/drm/1.0/types.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/CryptoHalHidl.h>
+#include <mediadrm/DrmUtils.h>
+
+using drm::V1_0::BufferType;
+using drm::V1_0::DestinationBuffer;
+using drm::V1_0::ICryptoFactory;
+using drm::V1_0::ICryptoPlugin;
+using drm::V1_0::Mode;
+using drm::V1_0::Pattern;
+using drm::V1_0::SharedBuffer;
+using drm::V1_0::Status;
+using drm::V1_0::SubSample;
+
+using ::android::sp;
+using ::android::DrmUtils::toStatusT;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::HidlMemory;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+typedef drm::V1_2::Status Status_V1_2;
+
+namespace android {
+
+static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t>& vector) {
+ hidl_vec<uint8_t> vec;
+ vec.setToExternal(const_cast<uint8_t*>(vector.array()), vector.size());
+ return vec;
+}
+
+static hidl_vec<uint8_t> toHidlVec(const void* ptr, size_t size) {
+ hidl_vec<uint8_t> vec;
+ vec.resize(size);
+ memcpy(vec.data(), ptr, size);
+ return vec;
+}
+
+static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t* ptr) {
+ if (!ptr) {
+ return hidl_array<uint8_t, 16>();
+ }
+ return hidl_array<uint8_t, 16>(ptr);
+}
+
+static String8 toString8(hidl_string hString) {
+ return String8(hString.c_str());
+}
+
+CryptoHalHidl::CryptoHalHidl()
+ : mFactories(makeCryptoFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
+ mHeapSeqNum(0) {}
+
+CryptoHalHidl::~CryptoHalHidl() {}
+
+Vector<sp<ICryptoFactory>> CryptoHalHidl::makeCryptoFactories() {
+ Vector<sp<ICryptoFactory>> factories;
+
+ auto manager = hardware::defaultServiceManager1_2();
+ if (manager != NULL) {
+ manager->listManifestByInterface(
+ drm::V1_0::ICryptoFactory::descriptor,
+ [&factories](const hidl_vec<hidl_string>& registered) {
+ for (const auto& instance : registered) {
+ auto factory = drm::V1_0::ICryptoFactory::getService(instance);
+ if (factory != NULL) {
+ ALOGD("found drm@1.0 ICryptoFactory %s", instance.c_str());
+ factories.push_back(factory);
+ }
+ }
+ });
+ manager->listManifestByInterface(
+ drm::V1_1::ICryptoFactory::descriptor,
+ [&factories](const hidl_vec<hidl_string>& registered) {
+ for (const auto& instance : registered) {
+ auto factory = drm::V1_1::ICryptoFactory::getService(instance);
+ if (factory != NULL) {
+ ALOGD("found drm@1.1 ICryptoFactory %s", instance.c_str());
+ factories.push_back(factory);
+ }
+ }
+ });
+ }
+
+ if (factories.size() == 0) {
+ // must be in passthrough mode, load the default passthrough service
+ auto passthrough = ICryptoFactory::getService();
+ if (passthrough != NULL) {
+ ALOGI("makeCryptoFactories: using default passthrough crypto instance");
+ factories.push_back(passthrough);
+ } else {
+ ALOGE("Failed to find any crypto factories");
+ }
+ }
+ return factories;
+}
+
+sp<ICryptoPlugin> CryptoHalHidl::makeCryptoPlugin(const sp<ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void* initData,
+ size_t initDataSize) {
+ sp<ICryptoPlugin> plugin;
+ Return<void> hResult =
+ factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
+ [&](Status status, const sp<ICryptoPlugin>& hPlugin) {
+ if (status != Status::OK) {
+ ALOGE("Failed to make crypto plugin");
+ return;
+ }
+ plugin = hPlugin;
+ });
+ if (!hResult.isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ return plugin;
+}
+
+status_t CryptoHalHidl::initCheck() const {
+ return mInitCheck;
+}
+
+bool CryptoHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+status_t CryptoHalHidl::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
+ if (mPlugin != NULL) {
+ mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
+ }
+ }
+ }
+
+ if (mInitCheck == NO_INIT) {
+ mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
+ }
+
+ return mInitCheck;
+}
+
+status_t CryptoHalHidl::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ mPlugin.clear();
+ mPluginV1_2.clear();
+ return OK;
+}
+
+bool CryptoHalHidl::requiresSecureDecoderComponent(const char* mime) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return false;
+ }
+
+ Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
+ if (!hResult.isOk()) {
+ return false;
+ }
+ return hResult;
+}
+
+/**
+ * If the heap base isn't set, get the heap base from the HidlMemory
+ * and send it to the HAL so it can map a remote heap of the same
+ * size. Once the heap base is established, shared memory buffers
+ * are sent by providing an offset into the heap and a buffer size.
+ */
+int32_t CryptoHalHidl::setHeapBase(const sp<HidlMemory>& heap) {
+ if (heap == NULL || mHeapSeqNum < 0) {
+ ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
+ return -1;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+
+ int32_t seqNum = mHeapSeqNum++;
+ uint32_t bufferId = static_cast<uint32_t>(seqNum);
+ mHeapSizes.add(seqNum, heap->size());
+ Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
+ ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
+ return seqNum;
+}
+
+void CryptoHalHidl::clearHeapBase(int32_t seqNum) {
+ Mutex::Autolock autoLock(mLock);
+
+ /*
+ * Clear the remote shared memory mapping by setting the shared
+ * buffer base to a null hidl_memory.
+ *
+ * TODO: Add a releaseSharedBuffer method in a future DRM HAL
+ * API version to make this explicit.
+ */
+ ssize_t index = mHeapSizes.indexOfKey(seqNum);
+ if (index >= 0) {
+ if (mPlugin != NULL) {
+ uint32_t bufferId = static_cast<uint32_t>(seqNum);
+ Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
+ ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
+ }
+ mHeapSizes.removeItem(seqNum);
+ }
+}
+
+status_t CryptoHalHidl::checkSharedBuffer(const ::SharedBuffer& buffer) {
+ int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
+ // memory must be in one of the heaps that have been set
+ if (mHeapSizes.indexOfKey(seqNum) < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ // memory must be within the address space of the heap
+ size_t heapSize = mHeapSizes.valueFor(seqNum);
+ if (heapSize < buffer.offset + buffer.size || SIZE_MAX - buffer.offset < buffer.size) {
+ android_errorWriteLog(0x534e4554, "76221123");
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+ssize_t CryptoHalHidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern,
+ const drm::V1_0::SharedBuffer& hSource, size_t offset,
+ const CryptoPlugin::SubSample* subSamples, size_t numSubSamples,
+ const drm::V1_0::DestinationBuffer& hDestination,
+ AString* errorDetailMsg) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ Mode hMode;
+ switch (mode) {
+ case CryptoPlugin::kMode_Unencrypted:
+ hMode = Mode::UNENCRYPTED;
+ break;
+ case CryptoPlugin::kMode_AES_CTR:
+ hMode = Mode::AES_CTR;
+ break;
+ case CryptoPlugin::kMode_AES_WV:
+ hMode = Mode::AES_CBC_CTS;
+ break;
+ case CryptoPlugin::kMode_AES_CBC:
+ hMode = Mode::AES_CBC;
+ break;
+ default:
+ return UNKNOWN_ERROR;
+ }
+
+ Pattern hPattern;
+ hPattern.encryptBlocks = pattern.mEncryptBlocks;
+ hPattern.skipBlocks = pattern.mSkipBlocks;
+
+ std::vector<SubSample> stdSubSamples;
+ for (size_t i = 0; i < numSubSamples; i++) {
+ SubSample subSample;
+ subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
+ subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
+ stdSubSamples.push_back(subSample);
+ }
+ auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
+
+ bool secure;
+ if (hDestination.type == BufferType::SHARED_MEMORY) {
+ status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
+ if (status != OK) {
+ return status;
+ }
+ secure = false;
+ } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
+ secure = true;
+ } else {
+ android_errorWriteLog(0x534e4554, "70526702");
+ return UNKNOWN_ERROR;
+ }
+
+ status_t status = checkSharedBuffer(hSource);
+ if (status != OK) {
+ return status;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+ uint32_t bytesWritten = 0;
+
+ Return<void> hResult;
+
+ mLock.unlock();
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->decrypt_1_2(
+ secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples,
+ hSource, offset, hDestination,
+ [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+ if (status == Status_V1_2::OK) {
+ bytesWritten = hBytesWritten;
+ *errorDetailMsg = toString8(hDetailedError);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPlugin->decrypt(
+ secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples,
+ hSource, offset, hDestination,
+ [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+ if (status == Status::OK) {
+ bytesWritten = hBytesWritten;
+ *errorDetailMsg = toString8(hDetailedError);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ if (err == OK) {
+ return bytesWritten;
+ }
+ return err;
+}
+
+void CryptoHalHidl::notifyResolution(uint32_t width, uint32_t height) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ auto hResult = mPlugin->notifyResolution(width, height);
+ ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
+}
+
+status_t CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId));
+ return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+}
+
+status_t CryptoHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs);
+}
+} // namespace android
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 40d1e0c..fe8b9f6 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -17,1557 +17,273 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmHal"
-#include <aidl/android/media/BnResourceManagerClient.h>
-#include <android/binder_manager.h>
-#include <android/hardware/drm/1.2/types.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-#include <media/EventMetric.h>
-#include <media/MediaMetrics.h>
-#include <media/PluginMetricsReporting.h>
-#include <media/drm/DrmAPI.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/base64.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaErrors.h>
#include <mediadrm/DrmHal.h>
-#include <mediadrm/DrmSessionClientInterface.h>
-#include <mediadrm/DrmSessionManager.h>
-#include <mediadrm/IDrmMetricsConsumer.h>
+#include <mediadrm/DrmHalAidl.h>
+#include <mediadrm/DrmHalHidl.h>
#include <mediadrm/DrmUtils.h>
-#include <utils/Log.h>
-
-#include <iomanip>
-#include <vector>
-
-using drm::V1_0::KeyedVector;
-using drm::V1_0::KeyRequestType;
-using drm::V1_0::KeyType;
-using drm::V1_0::KeyValue;
-using drm::V1_0::SecureStop;
-using drm::V1_0::SecureStopId;
-using drm::V1_0::Status;
-using drm::V1_1::HdcpLevel;
-using drm::V1_1::SecureStopRelease;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeySetId;
-using drm::V1_2::KeyStatusType;
-using ::android::DrmUtils::toStatusT;
-using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::os::PersistableBundle;
-using ::android::sp;
-
-typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
-typedef drm::V1_2::Status Status_V1_2;
-typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
-
-namespace {
-
-// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
-// in the MediaDrm API.
-constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
-constexpr char kEqualsSign[] = "=";
-
-template<typename T>
-std::string toBase64StringNoPad(const T* data, size_t size) {
- // Note that the base 64 conversion only works with arrays of single-byte
- // values. If the source is empty or is not an array of single-byte values,
- // return empty string.
- if (size == 0 || sizeof(data[0]) != 1) {
- return "";
- }
-
- android::AString outputString;
- encodeBase64(data, size, &outputString);
- // Remove trailing equals padding if it exists.
- while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
- outputString.erase(outputString.size() - 1, 1);
- }
-
- return std::string(outputString.c_str(), outputString.size());
-}
-
-} // anonymous namespace
namespace android {
-#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
-
-static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
- Vector<uint8_t> vector;
- vector.appendArray(vec.data(), vec.size());
- return *const_cast<const Vector<uint8_t> *>(&vector);
+DrmHal::DrmHal() {
+ mDrmHalHidl = sp<DrmHalHidl>::make();
+ mDrmHalAidl = ndk::SharedRefBase::make<DrmHalAidl>();
}
-static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
- hidl_vec<uint8_t> vec;
- vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
- return vec;
-}
-
-static String8 toString8(const hidl_string &string) {
- return String8(string.c_str());
-}
-
-static hidl_string toHidlString(const String8& string) {
- return hidl_string(string.string());
-}
-
-static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
- switch(level) {
- case SecurityLevel::SW_SECURE_CRYPTO:
- return DrmPlugin::kSecurityLevelSwSecureCrypto;
- case SecurityLevel::SW_SECURE_DECODE:
- return DrmPlugin::kSecurityLevelSwSecureDecode;
- case SecurityLevel::HW_SECURE_CRYPTO:
- return DrmPlugin::kSecurityLevelHwSecureCrypto;
- case SecurityLevel::HW_SECURE_DECODE:
- return DrmPlugin::kSecurityLevelHwSecureDecode;
- case SecurityLevel::HW_SECURE_ALL:
- return DrmPlugin::kSecurityLevelHwSecureAll;
- default:
- return DrmPlugin::kSecurityLevelUnknown;
- }
-}
-
-static SecurityLevel toHidlSecurityLevel(DrmPlugin::SecurityLevel level) {
- switch(level) {
- case DrmPlugin::kSecurityLevelSwSecureCrypto:
- return SecurityLevel::SW_SECURE_CRYPTO;
- case DrmPlugin::kSecurityLevelSwSecureDecode:
- return SecurityLevel::SW_SECURE_DECODE;
- case DrmPlugin::kSecurityLevelHwSecureCrypto:
- return SecurityLevel::HW_SECURE_CRYPTO;
- case DrmPlugin::kSecurityLevelHwSecureDecode:
- return SecurityLevel::HW_SECURE_DECODE;
- case DrmPlugin::kSecurityLevelHwSecureAll:
- return SecurityLevel::HW_SECURE_ALL;
- default:
- return SecurityLevel::UNKNOWN;
- }
-}
-
-static DrmPlugin::OfflineLicenseState toOfflineLicenseState(
- OfflineLicenseState licenseState) {
- switch(licenseState) {
- case OfflineLicenseState::USABLE:
- return DrmPlugin::kOfflineLicenseStateUsable;
- case OfflineLicenseState::INACTIVE:
- return DrmPlugin::kOfflineLicenseStateReleased;
- default:
- return DrmPlugin::kOfflineLicenseStateUnknown;
- }
-}
-
-static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel_V1_2 level) {
- switch(level) {
- case HdcpLevel_V1_2::HDCP_NONE:
- return DrmPlugin::kHdcpNone;
- case HdcpLevel_V1_2::HDCP_V1:
- return DrmPlugin::kHdcpV1;
- case HdcpLevel_V1_2::HDCP_V2:
- return DrmPlugin::kHdcpV2;
- case HdcpLevel_V1_2::HDCP_V2_1:
- return DrmPlugin::kHdcpV2_1;
- case HdcpLevel_V1_2::HDCP_V2_2:
- return DrmPlugin::kHdcpV2_2;
- case HdcpLevel_V1_2::HDCP_V2_3:
- return DrmPlugin::kHdcpV2_3;
- case HdcpLevel_V1_2::HDCP_NO_OUTPUT:
- return DrmPlugin::kHdcpNoOutput;
- default:
- return DrmPlugin::kHdcpLevelUnknown;
- }
-}
-static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
- keyedVector) {
- std::vector<KeyValue> stdKeyedVector;
- for (size_t i = 0; i < keyedVector.size(); i++) {
- KeyValue keyValue;
- keyValue.key = toHidlString(keyedVector.keyAt(i));
- keyValue.value = toHidlString(keyedVector.valueAt(i));
- stdKeyedVector.push_back(keyValue);
- }
- return ::KeyedVector(stdKeyedVector);
-}
-
-static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
- hKeyedVector) {
- KeyedVector<String8, String8> keyedVector;
- for (size_t i = 0; i < hKeyedVector.size(); i++) {
- keyedVector.add(toString8(hKeyedVector[i].key),
- toString8(hKeyedVector[i].value));
- }
- return keyedVector;
-}
-
-static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
- hSecureStops) {
- List<Vector<uint8_t>> secureStops;
- for (size_t i = 0; i < hSecureStops.size(); i++) {
- secureStops.push_back(toVector(hSecureStops[i].opaqueData));
- }
- return secureStops;
-}
-
-static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
- hSecureStopIds) {
- List<Vector<uint8_t>> secureStopIds;
- for (size_t i = 0; i < hSecureStopIds.size(); i++) {
- secureStopIds.push_back(toVector(hSecureStopIds[i]));
- }
- return secureStopIds;
-}
-
-static List<Vector<uint8_t>> toKeySetIds(const hidl_vec<KeySetId>&
- hKeySetIds) {
- List<Vector<uint8_t>> keySetIds;
- for (size_t i = 0; i < hKeySetIds.size(); i++) {
- keySetIds.push_back(toVector(hKeySetIds[i]));
- }
- return keySetIds;
-}
-
-Mutex DrmHal::mLock;
-
-struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
- explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
- : mSessionId(sessionId),
- mDrm(drm) {}
-
- ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
- ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
-
- const Vector<uint8_t> mSessionId;
-
- virtual ~DrmSessionClient();
-
-private:
- wp<DrmHal> mDrm;
-
- DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
-};
-
-::ndk::ScopedAStatus DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
- auto sessionId = mSessionId;
- sp<DrmHal> drm = mDrm.promote();
- if (drm == NULL) {
- *_aidl_return = true;
- return ::ndk::ScopedAStatus::ok();
- }
- status_t err = drm->closeSession(sessionId);
- if (err != OK) {
- *_aidl_return = false;
- return ::ndk::ScopedAStatus::ok();
- }
- drm->sendEvent(EventType::SESSION_RECLAIMED,
- toHidlVec(sessionId), hidl_vec<uint8_t>());
- *_aidl_return = true;
- return ::ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
- String8 name;
- sp<DrmHal> drm = mDrm.promote();
- if (drm == NULL) {
- name.append("<deleted>");
- } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK
- || name.isEmpty()) {
- name.append("<Get vendor failed or is empty>");
- }
- name.append("[");
- for (size_t i = 0; i < mSessionId.size(); ++i) {
- name.appendFormat("%02x", mSessionId[i]);
- }
- name.append("]");
- *_aidl_return = name;
- return ::ndk::ScopedAStatus::ok();
-}
-
-DrmHal::DrmSessionClient::~DrmSessionClient() {
- DrmSessionManager::Instance()->removeSession(mSessionId);
-}
-
-DrmHal::DrmHal()
- : mFactories(makeDrmFactories()),
- mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
-}
-
-void DrmHal::closeOpenSessions() {
- Mutex::Autolock autoLock(mLock);
- auto openSessions = mOpenSessions;
- for (size_t i = 0; i < openSessions.size(); i++) {
- mLock.unlock();
- closeSession(openSessions[i]->mSessionId);
- mLock.lock();
- }
- mOpenSessions.clear();
-}
-
-DrmHal::~DrmHal() {
-}
-
-void DrmHal::cleanup() {
- closeOpenSessions();
-
- Mutex::Autolock autoLock(mLock);
- reportFrameworkMetrics(reportPluginMetrics());
-
- setListener(NULL);
- mInitCheck = NO_INIT;
- if (mPluginV1_2 != NULL) {
- if (!mPluginV1_2->setListener(NULL).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- } else if (mPlugin != NULL) {
- if (!mPlugin->setListener(NULL).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- }
- mPlugin.clear();
- mPluginV1_1.clear();
- mPluginV1_2.clear();
- mPluginV1_4.clear();
-}
-
-std::vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
- static std::vector<sp<IDrmFactory>> factories(DrmUtils::MakeDrmFactories());
- if (factories.size() == 0) {
- // must be in passthrough mode, load the default passthrough service
- auto passthrough = IDrmFactory::getService();
- if (passthrough != NULL) {
- DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
- factories.push_back(passthrough);
- } else {
- DrmUtils::LOG2BE("Failed to find any drm factories");
- }
- }
- return factories;
-}
-
-sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
- const uint8_t uuid[16], const String8& appPackageName) {
- mAppPackageName = appPackageName;
- mMetrics.SetAppPackageName(appPackageName);
- mMetrics.SetAppUid(AIBinder_getCallingUid());
-
- sp<IDrmPlugin> plugin;
- Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
- [&](Status status, const sp<IDrmPlugin>& hPlugin) {
- if (status != Status::OK) {
- DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
- return;
- }
- plugin = hPlugin;
- }
- );
-
- if (!hResult.isOk()) {
- DrmUtils::LOG2BE(uuid, "createPlugin remote call failed: %s",
- hResult.description().c_str());
- }
-
- return plugin;
-}
+DrmHal::~DrmHal() {}
status_t DrmHal::initCheck() const {
- return mInitCheck;
+ if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return OK;
+ if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT) return NO_INIT;
+ return mDrmHalHidl->initCheck();
}
-status_t DrmHal::setListener(const sp<IDrmClient>& listener)
-{
- Mutex::Autolock lock(mEventLock);
- mListener = listener;
- return NO_ERROR;
+status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result) {
+ status_t statusResult;
+ statusResult = mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+ if (*result) return statusResult;
+ return mDrmHalHidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
}
-Return<void> DrmHal::sendEvent(EventType hEventType,
- const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
- mMetrics.mEventCounter.Increment(hEventType);
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- DrmPlugin::EventType eventType;
- switch(hEventType) {
- case EventType::PROVISION_REQUIRED:
- eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
- break;
- case EventType::KEY_NEEDED:
- eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
- break;
- case EventType::KEY_EXPIRED:
- eventType = DrmPlugin::kDrmPluginEventKeyExpired;
- break;
- case EventType::VENDOR_DEFINED:
- eventType = DrmPlugin::kDrmPluginEventVendorDefined;
- break;
- case EventType::SESSION_RECLAIMED:
- eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
- break;
- default:
- return Void();
- }
- listener->sendEvent(eventType, sessionId, data);
- }
- return Void();
-}
-
-Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
- int64_t expiryTimeInMS) {
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
- }
- return Void();
-}
-
-Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus_V1_0>& keyStatusList_V1_0, bool hasNewUsableKey) {
- std::vector<KeyStatus> keyStatusVec;
- for (const auto &keyStatus_V1_0 : keyStatusList_V1_0) {
- keyStatusVec.push_back({keyStatus_V1_0.keyId,
- static_cast<KeyStatusType>(keyStatus_V1_0.type)});
- }
- hidl_vec<KeyStatus> keyStatusList_V1_2(keyStatusVec);
- return sendKeysChange_1_2(sessionId, keyStatusList_V1_2, hasNewUsableKey);
-}
-
-Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus>& hKeyStatusList, bool hasNewUsableKey) {
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- std::vector<DrmKeyStatus> keyStatusList;
- size_t nKeys = hKeyStatusList.size();
- for (size_t i = 0; i < nKeys; ++i) {
- const KeyStatus &keyStatus = hKeyStatusList[i];
- uint32_t type;
- switch(keyStatus.type) {
- case KeyStatusType::USABLE:
- type = DrmPlugin::kKeyStatusType_Usable;
- break;
- case KeyStatusType::EXPIRED:
- type = DrmPlugin::kKeyStatusType_Expired;
- break;
- case KeyStatusType::OUTPUTNOTALLOWED:
- type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
- break;
- case KeyStatusType::STATUSPENDING:
- type = DrmPlugin::kKeyStatusType_StatusPending;
- break;
- case KeyStatusType::USABLEINFUTURE:
- type = DrmPlugin::kKeyStatusType_UsableInFuture;
- break;
- case KeyStatusType::INTERNALERROR:
- default:
- type = DrmPlugin::kKeyStatusType_InternalError;
- break;
- }
- keyStatusList.push_back({type, keyStatus.keyId});
- mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
- }
-
- Mutex::Autolock lock(mNotifyLock);
- listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
- } else {
- // There's no listener. But we still want to count the key change
- // events.
- size_t nKeys = hKeyStatusList.size();
- for (size_t i = 0; i < nKeys; i++) {
- mMetrics.mKeyStatusChangeCounter.Increment(hKeyStatusList[i].type);
- }
- }
-
- return Void();
-}
-
-Return<void> DrmHal::sendSessionLostState(
- const hidl_vec<uint8_t>& sessionId) {
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- listener->sendSessionLostState(sessionId);
- }
- return Void();
-}
-
-status_t DrmHal::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
- const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported) {
- *isSupported = false;
-
- // handle default value cases
- if (level == DrmPlugin::kSecurityLevelUnknown) {
- if (mimeType == "") {
- // isCryptoSchemeSupported(uuid)
- *isSupported = true;
- } else {
- // isCryptoSchemeSupported(uuid, mimeType)
- *isSupported = factory->isContentTypeSupported(mimeType.string());
- }
- return OK;
- } else if (mimeType == "") {
- return BAD_VALUE;
- }
-
- sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
- if (factoryV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- } else {
- *isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid,
- mimeType.string(), toHidlSecurityLevel(level));
- return OK;
- }
-}
-
-status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported) {
- Mutex::Autolock autoLock(mLock);
- *isSupported = false;
- for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
- if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
- return matchMimeTypeAndSecurityLevel(mFactories[i],
- uuid, mimeType, level, isSupported);
- }
- }
- return OK;
-}
-
-status_t DrmHal::createPlugin(const uint8_t uuid[16],
- const String8& appPackageName) {
- Mutex::Autolock autoLock(mLock);
-
- for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
- auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
- if (hResult.isOk() && hResult) {
- auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
- if (plugin != NULL) {
- mPlugin = plugin;
- mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
- mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
- mPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mPlugin);
- break;
- }
- }
- }
-
- if (mPlugin == NULL) {
- DrmUtils::LOG2BE(uuid, "No supported hal instance found");
- mInitCheck = ERROR_UNSUPPORTED;
- } else {
- mInitCheck = OK;
- if (mPluginV1_2 != NULL) {
- if (!mPluginV1_2->setListener(this).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- } else if (!mPlugin->setListener(this).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- if (mInitCheck != OK) {
- mPlugin.clear();
- mPluginV1_1.clear();
- mPluginV1_2.clear();
- mPluginV1_4.clear();
- }
- }
-
-
- return mInitCheck;
+status_t DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ status_t statusResult;
+ statusResult = mDrmHalAidl->createPlugin(uuid, appPackageName);
+ if (statusResult != OK) return mDrmHalHidl->createPlugin(uuid, appPackageName);
+ return statusResult;
}
status_t DrmHal::destroyPlugin() {
- cleanup();
- return OK;
+ status_t statusResult = mDrmHalAidl->destroyPlugin();
+ status_t statusResultHidl = mDrmHalHidl->destroyPlugin();
+ if (statusResult != OK) return statusResult;
+ return statusResultHidl;
}
-status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
- Vector<uint8_t> &sessionId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- SecurityLevel hSecurityLevel = toHidlSecurityLevel(level);
- bool setSecurityLevel = true;
-
- if (level == DrmPlugin::kSecurityLevelMax) {
- setSecurityLevel = false;
- } else {
- if (hSecurityLevel == SecurityLevel::UNKNOWN) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
- }
-
- status_t err = UNKNOWN_ERROR;
- bool retry = true;
- do {
- hidl_vec<uint8_t> hSessionId;
-
- Return<void> hResult;
- if (mPluginV1_1 == NULL || !setSecurityLevel) {
- hResult = mPlugin->openSession(
- [&](Status status,const hidl_vec<uint8_t>& id) {
- if (status == Status::OK) {
- sessionId = toVector(id);
- }
- err = toStatusT(status);
- }
- );
- } else {
- hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
- [&](Status status, const hidl_vec<uint8_t>& id) {
- if (status == Status::OK) {
- sessionId = toVector(id);
- }
- err = toStatusT(status);
- }
- );
- }
-
- if (!hResult.isOk()) {
- err = DEAD_OBJECT;
- }
-
- if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
- mLock.unlock();
- // reclaimSession may call back to closeSession, since mLock is
- // shared between Drm instances, we should unlock here to avoid
- // deadlock.
- retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
- mLock.lock();
- } else {
- retry = false;
- }
- } while (retry);
-
- if (err == OK) {
- std::shared_ptr<DrmSessionClient> client =
- ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
- DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
- std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
- mOpenSessions.push_back(client);
- mMetrics.SetSessionStart(sessionId);
- }
-
- mMetrics.mOpenSessionCounter.Increment(err);
- return err;
+status_t DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->openSession(securityLevel, sessionId);
+ return mDrmHalHidl->openSession(securityLevel, sessionId);
}
-status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
- if (status.isOk()) {
- if (status == Status::OK) {
- DrmSessionManager::Instance()->removeSession(sessionId);
- for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
- if (isEqualSessionId((*i)->mSessionId, sessionId)) {
- mOpenSessions.erase(i);
- break;
- }
- }
- }
- status_t response = toStatusT(status);
- mMetrics.SetSessionEnd(sessionId);
- mMetrics.mCloseSessionCounter.Increment(response);
- return response;
- }
- mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
- return DEAD_OBJECT;
+status_t DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->closeSession(sessionId);
+ return mDrmHalHidl->closeSession(sessionId);
}
-static DrmPlugin::KeyRequestType toKeyRequestType(
- KeyRequestType keyRequestType) {
- switch (keyRequestType) {
- case KeyRequestType::INITIAL:
- return DrmPlugin::kKeyRequestType_Initial;
- break;
- case KeyRequestType::RENEWAL:
- return DrmPlugin::kKeyRequestType_Renewal;
- break;
- case KeyRequestType::RELEASE:
- return DrmPlugin::kKeyRequestType_Release;
- break;
- default:
- return DrmPlugin::kKeyRequestType_Unknown;
- break;
- }
+status_t DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
+ String8 const& mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getKeyRequest(sessionId, initData, mimeType, keyType,
+ optionalParameters, request, defaultUrl, keyRequestType);
+ return mDrmHalHidl->getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters,
+ request, defaultUrl, keyRequestType);
}
-static DrmPlugin::KeyRequestType toKeyRequestType_1_1(
- KeyRequestType_V1_1 keyRequestType) {
- switch (keyRequestType) {
- case KeyRequestType_V1_1::NONE:
- return DrmPlugin::kKeyRequestType_None;
- break;
- case KeyRequestType_V1_1::UPDATE:
- return DrmPlugin::kKeyRequestType_Update;
- break;
- default:
- return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType));
- break;
- }
+status_t DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->provideKeyResponse(sessionId, response, keySetId);
+ return mDrmHalHidl->provideKeyResponse(sessionId, response, keySetId);
}
-status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &initData, String8 const &mimeType,
- DrmPlugin::KeyType keyType, KeyedVector<String8,
- String8> const &optionalParameters, Vector<uint8_t> &request,
- String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
- EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- KeyType hKeyType;
- if (keyType == DrmPlugin::kKeyType_Streaming) {
- hKeyType = KeyType::STREAMING;
- } else if (keyType == DrmPlugin::kKeyType_Offline) {
- hKeyType = KeyType::OFFLINE;
- } else if (keyType == DrmPlugin::kKeyType_Release) {
- hKeyType = KeyType::RELEASE;
- } else {
- keyRequestTimer.SetAttribute(BAD_VALUE);
- return BAD_VALUE;
- }
-
- ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
-
- status_t err = UNKNOWN_ERROR;
- Return<void> hResult;
-
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->getKeyRequest_1_2(
- toHidlVec(sessionId), toHidlVec(initData),
- toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType_V1_1 hKeyRequestType,
- const hidl_string& hDefaultUrl) {
- if (status == Status_V1_2::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
- }
- err = toStatusT(status);
- });
- } else if (mPluginV1_1 != NULL) {
- hResult = mPluginV1_1->getKeyRequest_1_1(
- toHidlVec(sessionId), toHidlVec(initData),
- toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType_V1_1 hKeyRequestType,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
- }
- err = toStatusT(status);
- });
- } else {
- hResult = mPlugin->getKeyRequest(
- toHidlVec(sessionId), toHidlVec(initData),
- toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType hKeyRequestType,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- *keyRequestType = toKeyRequestType(hKeyRequestType);
- }
- err = toStatusT(status);
- });
- }
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- keyRequestTimer.SetAttribute(err);
- return err;
+status_t DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeKeys(keySetId);
+ return mDrmHalHidl->removeKeys(keySetId);
}
-status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
- EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
- toHidlVec(response),
- [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
- if (status == Status::OK) {
- keySetId = toVector(hKeySetId);
- }
- err = toStatusT(status);
- }
- );
- err = hResult.isOk() ? err : DEAD_OBJECT;
- keyResponseTimer.SetAttribute(err);
- return err;
+status_t DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->restoreKeys(sessionId, keySetId);
+ return mDrmHalHidl->restoreKeys(sessionId, keySetId);
}
-status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->queryKeyStatus(sessionId, infoMap);
+ return mDrmHalHidl->queryKeyStatus(sessionId, infoMap);
}
-status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
- toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
+ return mDrmHalHidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
}
-status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- ::KeyedVector hInfoMap;
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
- [&](Status status, const hidl_vec<KeyValue>& map) {
- if (status == Status::OK) {
- infoMap = toKeyedVector(map);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->provideProvisionResponse(response, certificate, wrappedKey);
+ return mDrmHalHidl->provideProvisionResponse(response, certificate, wrappedKey);
}
-status_t DrmHal::getProvisionRequest(String8 const &certType,
- String8 const &certAuthority, Vector<uint8_t> &request,
- String8 &defaultUrl) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
- Return<void> hResult;
-
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->getProvisionRequest_1_2(
- toHidlString(certType), toHidlString(certAuthority),
- [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
- const hidl_string& hDefaultUrl) {
- if (status == Status_V1_2::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- }
- err = toStatusT(status);
- }
- );
- } else {
- hResult = mPlugin->getProvisionRequest(
- toHidlString(certType), toHidlString(certAuthority),
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- }
- err = toStatusT(status);
- }
- );
- }
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- mMetrics.mGetProvisionRequestCounter.Increment(err);
- return err;
+status_t DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStops(secureStops);
+ return mDrmHalHidl->getSecureStops(secureStops);
}
-status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
- [&](Status status, const hidl_vec<uint8_t>& hCertificate,
- const hidl_vec<uint8_t>& hWrappedKey) {
- if (status == Status::OK) {
- certificate = toVector(hCertificate);
- wrappedKey = toVector(hWrappedKey);
- }
- err = toStatusT(status);
- }
- );
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- mMetrics.mProvideProvisionResponseCounter.Increment(err);
- return err;
+status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStopIds(secureStopIds);
+ return mDrmHalHidl->getSecureStopIds(secureStopIds);
}
-status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getSecureStops(
- [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
- if (status == Status::OK) {
- secureStops = toSecureStops(hSecureStops);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStop(ssid, secureStop);
+ return mDrmHalHidl->getSecureStop(ssid, secureStop);
}
-
-status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPluginV1_1->getSecureStopIds(
- [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
- if (status == Status::OK) {
- secureStopIds = toSecureStopIds(hSecureStopIds);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->releaseSecureStops(ssRelease);
+ return mDrmHalHidl->releaseSecureStops(ssRelease);
}
-
-status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
- [&](Status status, const SecureStop& hSecureStop) {
- if (status == Status::OK) {
- secureStop = toVector(hSecureStop.opaqueData);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
-}
-
-status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status(Status::ERROR_DRM_UNKNOWN);
- if (mPluginV1_1 != NULL) {
- SecureStopRelease secureStopRelease;
- secureStopRelease.opaqueData = toHidlVec(ssRelease);
- status = mPluginV1_1->releaseSecureStops(secureStopRelease);
- } else {
- status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
- }
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
-}
-
-status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeSecureStop(ssid);
+ return mDrmHalHidl->removeSecureStop(ssid);
}
status_t DrmHal::removeAllSecureStops() {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status(Status::ERROR_DRM_UNKNOWN);
- if (mPluginV1_1 != NULL) {
- status = mPluginV1_1->removeAllSecureStops();
- } else {
- status = mPlugin->releaseAllSecureStops();
- }
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeAllSecureStops();
+ return mDrmHalHidl->removeAllSecureStops();
}
-status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
- DrmPlugin::HdcpLevel *max) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- if (connected == NULL || max == NULL) {
- return BAD_VALUE;
- }
- status_t err = UNKNOWN_ERROR;
-
- *connected = DrmPlugin::kHdcpLevelUnknown;
- *max = DrmPlugin::kHdcpLevelUnknown;
-
- Return<void> hResult;
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->getHdcpLevels_1_2(
- [&](Status_V1_2 status, const HdcpLevel_V1_2& hConnected, const HdcpLevel_V1_2& hMax) {
- if (status == Status_V1_2::OK) {
- *connected = toHdcpLevel(hConnected);
- *max = toHdcpLevel(hMax);
- }
- err = toStatusT(status);
- });
- } else if (mPluginV1_1 != NULL) {
- hResult = mPluginV1_1->getHdcpLevels(
- [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
- if (status == Status::OK) {
- *connected = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hConnected));
- *max = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hMax));
- }
- err = toStatusT(status);
- });
- } else {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getHdcpLevels(connectedLevel, maxLevel);
+ return mDrmHalHidl->getHdcpLevels(connectedLevel, maxLevel);
}
-status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- if (open == NULL || max == NULL) {
- return BAD_VALUE;
- }
- status_t err = UNKNOWN_ERROR;
-
- *open = 0;
- *max = 0;
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<void> hResult = mPluginV1_1->getNumberOfSessions(
- [&](Status status, uint32_t hOpen, uint32_t hMax) {
- if (status == Status::OK) {
- *open = hOpen;
- *max = hMax;
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getNumberOfSessions(currentSessions, maxSessions);
+ return mDrmHalHidl->getNumberOfSessions(currentSessions, maxSessions);
}
-status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
- DrmPlugin::SecurityLevel *level) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- if (level == NULL) {
- return BAD_VALUE;
- }
- status_t err = UNKNOWN_ERROR;
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- *level = DrmPlugin::kSecurityLevelUnknown;
-
- Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
- [&](Status status, SecurityLevel hLevel) {
- if (status == Status::OK) {
- *level = toSecurityLevel(hLevel);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecurityLevel(sessionId, level);
+ return mDrmHalHidl->getSecurityLevel(sessionId, level);
}
-status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- }
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
- [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
- if (status == Status::OK) {
- keySetIds = toKeySetIds(hKeySetIds);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getOfflineLicenseKeySetIds(keySetIds);
+ return mDrmHalHidl->getOfflineLicenseKeySetIds(keySetIds);
}
-status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const &keySetId) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- }
-
- Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeOfflineLicense(keySetId);
+ return mDrmHalHidl->removeOfflineLicense(keySetId);
}
-status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const &keySetId,
- DrmPlugin::OfflineLicenseState *licenseState) const {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- }
- *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPluginV1_2->getOfflineLicenseState(toHidlVec(keySetId),
- [&](Status status, OfflineLicenseState hLicenseState) {
- if (status == Status::OK) {
- *licenseState = toOfflineLicenseState(hLicenseState);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getOfflineLicenseState(keySetId, licenseState);
+ return mDrmHalHidl->getOfflineLicenseState(keySetId, licenseState);
}
-status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
- Mutex::Autolock autoLock(mLock);
- return getPropertyStringInternal(name, value);
+status_t DrmHal::getPropertyString(String8 const& name, String8& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyString(name, value);
+ return mDrmHalHidl->getPropertyString(name, value);
}
-status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
- // This function is internal to the class and should only be called while
- // mLock is already held.
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
- [&](Status status, const hidl_string& hValue) {
- if (status == Status::OK) {
- value = toString8(hValue);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyByteArray(name, value);
+ return mDrmHalHidl->getPropertyByteArray(name, value);
}
-status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
- Mutex::Autolock autoLock(mLock);
- return getPropertyByteArrayInternal(name, value);
+status_t DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyString(name, value);
+ return mDrmHalHidl->setPropertyString(name, value);
}
-status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
- // This function is internal to the class and should only be called while
- // mLock is already held.
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
- [&](Status status, const hidl_vec<uint8_t>& hValue) {
- if (status == Status::OK) {
- value = toVector(hValue);
- }
- err = toStatusT(status);
- }
- );
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- if (name == kPropertyDeviceUniqueId) {
- mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
- }
- return err;
+status_t DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyByteArray(name, value);
+ return mDrmHalHidl->setPropertyByteArray(name, value);
}
-status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
- toHidlString(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getMetrics(consumer);
+ return mDrmHalHidl->getMetrics(consumer);
}
-status_t DrmHal::setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
- toHidlVec(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->setCipherAlgorithm(sessionId, algorithm);
+ return mDrmHalHidl->setCipherAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer> &consumer) {
- if (consumer == nullptr) {
- return UNEXPECTED_NULL;
- }
- consumer->consumeFrameworkMetrics(mMetrics);
-
- // Append vendor metrics if they are supported.
- if (mPluginV1_1 != NULL) {
- String8 vendor;
- String8 description;
- if (getPropertyStringInternal(String8("vendor"), vendor) != OK
- || vendor.isEmpty()) {
- ALOGE("Get vendor failed or is empty");
- vendor = "NONE";
- }
- if (getPropertyStringInternal(String8("description"), description) != OK
- || description.isEmpty()) {
- ALOGE("Get description failed or is empty.");
- description = "NONE";
- }
- vendor += ".";
- vendor += description;
-
- hidl_vec<DrmMetricGroup> pluginMetrics;
- status_t err = UNKNOWN_ERROR;
-
- Return<void> status = mPluginV1_1->getMetrics(
- [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
- if (status != Status::OK) {
- ALOGV("Error getting plugin metrics: %d", status);
- } else {
- consumer->consumeHidlMetrics(vendor, pluginMetrics);
- }
- err = toStatusT(status);
- });
- return status.isOk() ? err : DEAD_OBJECT;
- }
-
- return OK;
+status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setMacAlgorithm(sessionId, algorithm);
+ return mDrmHalHidl->setMacAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- Return<Status> status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
- toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->encrypt(sessionId, keyId, input, iv, output);
+ return mDrmHalHidl->encrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
- toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->decrypt(sessionId, keyId, input, iv, output);
+ return mDrmHalHidl->decrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
- toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
- [&](Status status, const hidl_vec<uint8_t>& hOutput) {
- if (status == Status::OK) {
- output = toVector(hOutput);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->sign(sessionId, keyId, message, signature);
+ return mDrmHalHidl->sign(sessionId, keyId, message, signature);
}
-status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
- toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
- [&](Status status, const hidl_vec<uint8_t>& hOutput) {
- if (status == Status::OK) {
- output = toVector(hOutput);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->verify(sessionId, keyId, message, signature, match);
+ return mDrmHalHidl->verify(sessionId, keyId, message, signature, match);
}
-status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
- Vector<uint8_t> &signature) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
- toHidlVec(keyId), toHidlVec(message),
- [&](Status status, const hidl_vec<uint8_t>& hSignature) {
- if (status == Status::OK) {
- signature = toVector(hSignature);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+ return mDrmHalHidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
}
-status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature, bool &match) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
- toHidlVec(message), toHidlVec(signature),
- [&](Status status, bool hMatch) {
- if (status == Status::OK) {
- match = hMatch;
- } else {
- match = false;
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::setListener(const sp<IDrmClient>& listener) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setListener(listener);
+ return mDrmHalHidl->setListener(listener);
}
-status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm, Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
- toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
- [&](Status status, const hidl_vec<uint8_t>& hSignature) {
- if (status == Status::OK) {
- signature = toVector(hSignature);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->requiresSecureDecoder(mime, required);
+ return mDrmHalHidl->requiresSecureDecoder(mime, required);
}
-std::string DrmHal::reportFrameworkMetrics(const std::string& pluginMetrics) const
-{
- mediametrics_handle_t item(mediametrics_create("mediadrm"));
- mediametrics_setUid(item, mMetrics.GetAppUid());
- String8 vendor;
- String8 description;
- status_t result = getPropertyStringInternal(String8("vendor"), vendor);
- if (result != OK) {
- ALOGE("Failed to get vendor from drm plugin: %d", result);
- } else {
- mediametrics_setCString(item, "vendor", vendor.c_str());
- }
- result = getPropertyStringInternal(String8("description"), description);
- if (result != OK) {
- ALOGE("Failed to get description from drm plugin: %d", result);
- } else {
- mediametrics_setCString(item, "description", description.c_str());
- }
-
- std::string serializedMetrics;
- result = mMetrics.GetSerializedMetrics(&serializedMetrics);
- if (result != OK) {
- ALOGE("Failed to serialize framework metrics: %d", result);
- }
- std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
- serializedMetrics.size());
- if (!b64EncodedMetrics.empty()) {
- mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
- }
- if (!pluginMetrics.empty()) {
- mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str());
- }
- if (!mediametrics_selfRecord(item)) {
- ALOGE("Failed to self record framework metrics");
- }
- mediametrics_delete(item);
- return serializedMetrics;
+status_t DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->requiresSecureDecoder(mime, securityLevel, required);
+ return mDrmHalHidl->requiresSecureDecoder(mime, securityLevel, required);
}
-std::string DrmHal::reportPluginMetrics() const
-{
- Vector<uint8_t> metricsVector;
- String8 vendor;
- String8 description;
- std::string metricsString;
- if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
- getPropertyStringInternal(String8("description"), description) == OK &&
- getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
- metricsString = toBase64StringNoPad(metricsVector.array(),
- metricsVector.size());
- status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
- description, mMetrics.GetAppUid());
- if (res != OK) {
- ALOGE("Metrics were retrieved but could not be reported: %d", res);
- }
- }
- return metricsString;
+status_t DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPlaybackId(sessionId, playbackId);
+ return mDrmHalHidl->setPlaybackId(sessionId, playbackId);
}
-status_t DrmHal::requiresSecureDecoder(const char *mime, bool *required) const {
- Mutex::Autolock autoLock(mLock);
- if (mPluginV1_4 == NULL) {
- return false;
- }
- auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
- if (!hResult.isOk()) {
- DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
- }
- if (required) {
- *required = hResult;
- }
- return OK;
-}
-
-status_t DrmHal::requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const {
- Mutex::Autolock autoLock(mLock);
- if (mPluginV1_4 == NULL) {
- return false;
- }
- auto hLevel = toHidlSecurityLevel(securityLevel);
- auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
- if (!hResult.isOk()) {
- DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
- }
- if (required) {
- *required = hResult;
- }
- return OK;
-}
-
-status_t DrmHal::setPlaybackId(Vector<uint8_t> const &sessionId, const char *playbackId) {
- Mutex::Autolock autoLock(mLock);
- if (mPluginV1_4 == NULL) {
- return ERROR_UNSUPPORTED;
- }
- auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
- return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
-}
-
-status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
- Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getLogMessages(logs);
+ return mDrmHalHidl->getLogMessages(logs);
}
} // namespace android
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
new file mode 100644
index 0000000..7df57a3
--- /dev/null
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -0,0 +1,1326 @@
+/*
+ * 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 "DrmHalAidl"
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <media/PluginMetricsReporting.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/DrmHalAidl.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmUtils.h>
+
+using ::android::DrmUtils::toStatusTAidl;
+
+using ::aidl::android::hardware::drm::DrmMetricNamedValue;
+using ::aidl::android::hardware::drm::DrmMetricValue;
+using ::aidl::android::hardware::drm::HdcpLevel;
+using ::aidl::android::hardware::drm::HdcpLevels;
+using ::aidl::android::hardware::drm::KeyRequest;
+using ::aidl::android::hardware::drm::KeyRequestType;
+using ::aidl::android::hardware::drm::KeySetId;
+using ::aidl::android::hardware::drm::KeyStatus;
+using ::aidl::android::hardware::drm::KeyStatusType;
+using ::aidl::android::hardware::drm::KeyType;
+using ::aidl::android::hardware::drm::KeyValue;
+using ::aidl::android::hardware::drm::NumberOfSessions;
+using ::aidl::android::hardware::drm::OfflineLicenseState;
+using ::aidl::android::hardware::drm::OpaqueData;
+using ::aidl::android::hardware::drm::ProvideProvisionResponseResult;
+using ::aidl::android::hardware::drm::ProvisionRequest;
+using ::aidl::android::hardware::drm::SecureStop;
+using ::aidl::android::hardware::drm::SecureStopId;
+using ::aidl::android::hardware::drm::SecurityLevel;
+using ::aidl::android::hardware::drm::Status;
+using ::aidl::android::hardware::drm::Uuid;
+using DrmMetricGroupAidl = ::aidl::android::hardware::drm::DrmMetricGroup;
+using DrmMetricGroupHidl = ::android::hardware::drm::V1_1::DrmMetricGroup;
+using DrmMetricAidl = ::aidl::android::hardware::drm::DrmMetric;
+using DrmMetricHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Metric;
+using ValueHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Value;
+using AttributeHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Attribute;
+using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
+using EventTypeAidl = ::aidl::android::hardware::drm::EventType;
+using KeyStatusAidl = ::aidl::android::hardware::drm::KeyStatus;
+using ::android::hardware::hidl_vec;
+
+namespace {
+
+constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
+constexpr char kEqualsSign[] = "=";
+
+template <typename T>
+std::string toBase64StringNoPad(const T* data, size_t size) {
+ // Note that the base 64 conversion only works with arrays of single-byte
+ // values. If the source is empty or is not an array of single-byte values,
+ // return empty string.
+ if (size == 0 || sizeof(data[0]) != 1) {
+ return "";
+ }
+
+ android::AString outputString;
+ encodeBase64(data, size, &outputString);
+ // Remove trailing equals padding if it exists.
+ while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
+ outputString.erase(outputString.size() - 1, 1);
+ }
+
+ return std::string(outputString.c_str(), outputString.size());
+}
+
+} // anonymous namespace
+
+namespace android {
+
+#define INIT_CHECK() \
+ { \
+ if (mInitCheck != OK) return mInitCheck; \
+ }
+
+static Uuid toAidlUuid(const uint8_t* uuid) {
+ Uuid uuidAidl;
+ uuidAidl.uuid = std::vector<uint8_t>(uuid, uuid + 16);
+ return uuidAidl;
+}
+
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t>& vector) {
+ auto v = reinterpret_cast<const Byte*>(vector.array());
+ std::vector<Byte> vec(v, v + vector.size());
+ return vec;
+}
+
+static const Vector<uint8_t> toVector(const std::vector<uint8_t>& vec) {
+ Vector<uint8_t> vector;
+ vector.appendArray(vec.data(), vec.size());
+ return *const_cast<const Vector<uint8_t>*>(&vector);
+}
+
+static String8 toString8(const std::string& string) {
+ return String8(string.c_str());
+}
+
+static std::string toStdString(const String8& string8) {
+ return std::string(string8.string());
+}
+
+static std::vector<KeyValue> toKeyValueVector(const KeyedVector<String8, String8>& keyedVector) {
+ std::vector<KeyValue> stdKeyedVector;
+ for (size_t i = 0; i < keyedVector.size(); i++) {
+ KeyValue keyValue;
+ keyValue.key = toStdString(keyedVector.keyAt(i));
+ keyValue.value = toStdString(keyedVector.valueAt(i));
+ stdKeyedVector.push_back(keyValue);
+ }
+ return stdKeyedVector;
+}
+
+static KeyedVector<String8, String8> toKeyedVector(const std::vector<KeyValue>& keyValueVec) {
+ KeyedVector<String8, String8> keyedVector;
+ for (size_t i = 0; i < keyValueVec.size(); i++) {
+ keyedVector.add(toString8(keyValueVec[i].key), toString8(keyValueVec[i].value));
+ }
+ return keyedVector;
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType::INITIAL:
+ return DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case KeyRequestType::RENEWAL:
+ return DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case KeyRequestType::RELEASE:
+ return DrmPlugin::kKeyRequestType_Release;
+ break;
+ case KeyRequestType::NONE:
+ return DrmPlugin::kKeyRequestType_None;
+ break;
+ case KeyRequestType::UPDATE:
+ return DrmPlugin::kKeyRequestType_Update;
+ break;
+ default:
+ return DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+}
+
+static List<Vector<uint8_t>> toSecureStops(const std::vector<SecureStop>& aSecureStops) {
+ List<Vector<uint8_t>> secureStops;
+ for (size_t i = 0; i < aSecureStops.size(); i++) {
+ secureStops.push_back(toVector(aSecureStops[i].opaqueData));
+ }
+ return secureStops;
+}
+
+static List<Vector<uint8_t>> toSecureStopIds(const std::vector<SecureStopId>& aSecureStopIds) {
+ List<Vector<uint8_t>> secureStopIds;
+ for (size_t i = 0; i < aSecureStopIds.size(); i++) {
+ secureStopIds.push_back(toVector(aSecureStopIds[i].secureStopId));
+ }
+ return secureStopIds;
+}
+
+static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
+ switch (level) {
+ case HdcpLevel::HDCP_NONE:
+ return DrmPlugin::kHdcpNone;
+ case HdcpLevel::HDCP_V1:
+ return DrmPlugin::kHdcpV1;
+ case HdcpLevel::HDCP_V2:
+ return DrmPlugin::kHdcpV2;
+ case HdcpLevel::HDCP_V2_1:
+ return DrmPlugin::kHdcpV2_1;
+ case HdcpLevel::HDCP_V2_2:
+ return DrmPlugin::kHdcpV2_2;
+ case HdcpLevel::HDCP_V2_3:
+ return DrmPlugin::kHdcpV2_3;
+ case HdcpLevel::HDCP_NO_OUTPUT:
+ return DrmPlugin::kHdcpNoOutput;
+ default:
+ return DrmPlugin::kHdcpLevelUnknown;
+ }
+}
+
+static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
+ switch (level) {
+ case SecurityLevel::SW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelSwSecureCrypto;
+ case SecurityLevel::SW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelSwSecureDecode;
+ case SecurityLevel::HW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelHwSecureCrypto;
+ case SecurityLevel::HW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelHwSecureDecode;
+ case SecurityLevel::HW_SECURE_ALL:
+ return DrmPlugin::kSecurityLevelHwSecureAll;
+ case SecurityLevel::DEFAULT:
+ return DrmPlugin::kSecurityLevelMax;
+ default:
+ return DrmPlugin::kSecurityLevelUnknown;
+ }
+}
+
+static SecurityLevel toAidlSecurityLevel(DrmPlugin::SecurityLevel level) {
+ switch (level) {
+ case DrmPlugin::kSecurityLevelSwSecureCrypto:
+ return SecurityLevel::SW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelSwSecureDecode:
+ return SecurityLevel::SW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureCrypto:
+ return SecurityLevel::HW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelHwSecureDecode:
+ return SecurityLevel::HW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureAll:
+ return SecurityLevel::HW_SECURE_ALL;
+ case DrmPlugin::kSecurityLevelMax:
+ return SecurityLevel::DEFAULT;
+ default:
+ return SecurityLevel::UNKNOWN;
+ }
+}
+
+static List<Vector<uint8_t>> toKeySetIds(const std::vector<KeySetId>& hKeySetIds) {
+ List<Vector<uint8_t>> keySetIds;
+ for (size_t i = 0; i < hKeySetIds.size(); i++) {
+ keySetIds.push_back(toVector(hKeySetIds[i].keySetId));
+ }
+ return keySetIds;
+}
+
+static DrmPlugin::OfflineLicenseState toOfflineLicenseState(OfflineLicenseState licenseState) {
+ switch (licenseState) {
+ case OfflineLicenseState::USABLE:
+ return DrmPlugin::kOfflineLicenseStateUsable;
+ case OfflineLicenseState::INACTIVE:
+ return DrmPlugin::kOfflineLicenseStateReleased;
+ default:
+ return DrmPlugin::kOfflineLicenseStateUnknown;
+ }
+}
+
+template <typename T = uint8_t>
+static hidl_vec<T> toHidlVec(const Vector<T>& vector) {
+ hidl_vec<T> vec;
+ vec.setToExternal(const_cast<T*>(vector.array()), vector.size());
+ return vec;
+}
+
+Mutex DrmHalAidl::mLock;
+
+static hidl_vec<DrmMetricGroupHidl> toDrmMetricGroupHidl(std::vector<DrmMetricGroupAidl> result) {
+ Vector<DrmMetricGroupHidl> resultHidl;
+ for (auto r : result) {
+ DrmMetricGroupHidl re;
+ Vector<DrmMetricHidl> tmpMetric;
+ for (auto m : r.metrics) {
+ DrmMetricHidl me;
+ me.name = m.name;
+ Vector<AttributeHidl> aTmp;
+ for (auto attr : m.attributes) {
+ AttributeHidl attrHidl;
+ attrHidl.name = attr.name;
+
+ switch (attr.value.getTag()) {
+ case DrmMetricValue::Tag::int64Value:
+ attrHidl.type = DrmMetricGroupHidl::ValueType::INT64_TYPE;
+ attrHidl.int64Value = attr.value.get<DrmMetricValue::Tag::int64Value>();
+ break;
+ case DrmMetricValue::Tag::doubleValue:
+ attrHidl.type = DrmMetricGroupHidl::ValueType::DOUBLE_TYPE;
+ attrHidl.doubleValue = attr.value.get<DrmMetricValue::Tag::doubleValue>();
+ break;
+ case DrmMetricValue::Tag::stringValue:
+ attrHidl.type = DrmMetricGroupHidl::ValueType::STRING_TYPE;
+ attrHidl.stringValue = attr.value.get<DrmMetricValue::Tag::stringValue>();
+ break;
+ default:
+ break;
+ }
+
+ aTmp.push_back(attrHidl);
+ }
+
+ me.attributes = toHidlVec<AttributeHidl>(aTmp);
+
+ Vector<ValueHidl> vTmp;
+ for (auto value : m.values) {
+ ValueHidl valueHidl;
+ valueHidl.componentName = value.name;
+ switch (value.value.getTag()) {
+ case DrmMetricValue::Tag::int64Value:
+ valueHidl.type = DrmMetricGroupHidl::ValueType::INT64_TYPE;
+ valueHidl.int64Value = value.value.get<DrmMetricValue::Tag::int64Value>();
+ break;
+ case DrmMetricValue::Tag::doubleValue:
+ valueHidl.type = DrmMetricGroupHidl::ValueType::DOUBLE_TYPE;
+ valueHidl.doubleValue = value.value.get<DrmMetricValue::Tag::doubleValue>();
+ break;
+ case DrmMetricValue::Tag::stringValue:
+ valueHidl.type = DrmMetricGroupHidl::ValueType::STRING_TYPE;
+ valueHidl.stringValue = value.value.get<DrmMetricValue::Tag::stringValue>();
+ break;
+ default:
+ break;
+ }
+
+ vTmp.push_back(valueHidl);
+ }
+
+ me.values = toHidlVec<ValueHidl>(vTmp);
+ tmpMetric.push_back(me);
+ }
+
+ re.metrics = toHidlVec<DrmMetricHidl>(tmpMetric);
+ resultHidl.push_back(re);
+ }
+
+ return toHidlVec<DrmMetricGroupHidl>(resultHidl);
+}
+
+// DrmSessionClient Definition
+
+struct DrmHalAidl::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
+ explicit DrmSessionClient(DrmHalAidl* drm, const Vector<uint8_t>& sessionId)
+ : mSessionId(sessionId), mDrm(drm) {}
+
+ ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
+
+ const Vector<uint8_t> mSessionId;
+
+ virtual ~DrmSessionClient();
+
+ private:
+ wp<DrmHalAidl> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
+::ndk::ScopedAStatus DrmHalAidl::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+ auto sessionId = mSessionId;
+ sp<DrmHalAidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ status_t err = drm->closeSession(sessionId);
+ if (err != OK) {
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ drm->onEvent(EventTypeAidl::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>());
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmHalAidl::DrmSessionClient::getName(::std::string* _aidl_return) {
+ String8 name;
+ sp<DrmHalAidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ name.append("<deleted>");
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+ name.append("<Get vendor failed or is empty>");
+ }
+ name.append("[");
+ for (size_t i = 0; i < mSessionId.size(); ++i) {
+ name.appendFormat("%02x", mSessionId[i]);
+ }
+ name.append("]");
+ *_aidl_return = name;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+DrmHalAidl::DrmSessionClient::~DrmSessionClient() {
+ DrmSessionManager::Instance()->removeSession(mSessionId);
+}
+
+// DrmHalAidl methods
+DrmHalAidl::DrmHalAidl()
+ : mFactories(makeDrmFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
+
+status_t DrmHalAidl::initCheck() const {
+ return mInitCheck;
+}
+
+DrmHalAidl::~DrmHalAidl() {}
+
+std::vector<std::shared_ptr<IDrmFactoryAidl>> DrmHalAidl::makeDrmFactories() {
+ std::vector<std::shared_ptr<IDrmFactoryAidl>> factories;
+ AServiceManager_forEachDeclaredInstance(
+ IDrmFactoryAidl::descriptor, static_cast<void*>(&factories),
+ [](const char* instance, void* context) {
+ auto fullName = std::string(IDrmFactoryAidl::descriptor) + "/" + std::string(instance);
+ auto factory = IDrmFactoryAidl::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_getService(fullName.c_str())));
+ if (factory == nullptr) {
+ ALOGE("not found IDrmFactory. Instance name:[%s]", fullName.c_str());
+ return;
+ }
+
+ ALOGI("found IDrmFactory. Instance name:[%s]", fullName.c_str());
+ static_cast<std::vector<std::shared_ptr<IDrmFactoryAidl>>*>(context)->emplace_back(
+ factory);
+ });
+
+ return factories;
+}
+
+status_t DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
+ Mutex::Autolock lock(mEventLock);
+ mListener = listener;
+ return NO_ERROR;
+}
+
+status_t DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
+ Mutex::Autolock autoLock(mLock);
+ *isSupported = false;
+ Uuid uuidAidl = toAidlUuid(uuid);
+ SecurityLevel levelAidl = static_cast<SecurityLevel>((int32_t)level);
+ std::string mimeTypeStr = mimeType.string();
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ if (mFactories[i]
+ ->isCryptoSchemeSupported(uuidAidl, mimeTypeStr, levelAidl, isSupported)
+ .isOk()) {
+ if (*isSupported) break;
+ }
+ }
+
+ return OK;
+}
+
+status_t DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ Mutex::Autolock autoLock(mLock);
+
+ Uuid uuidAidl = toAidlUuid(uuid);
+ std::string appPackageNameAidl = toStdString(appPackageName);
+ std::shared_ptr<IDrmPluginAidl> pluginAidl;
+ mMetrics.SetAppPackageName(appPackageName);
+ mMetrics.SetAppUid(AIBinder_getCallingUid());
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ ::ndk::ScopedAStatus status =
+ mFactories[i]->createPlugin(uuidAidl, appPackageNameAidl, &pluginAidl);
+ if (status.isOk()) {
+ if (pluginAidl != NULL) {
+ mPlugin = pluginAidl;
+ break;
+ }
+ } else {
+ DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d",
+ status.getServiceSpecificError());
+ }
+ }
+
+ if (mPlugin == NULL) {
+ DrmUtils::LOG2BE(uuid, "No supported hal instance found");
+ mInitCheck = ERROR_UNSUPPORTED;
+ } else {
+ mInitCheck = OK;
+
+ if (!mPlugin->setListener(shared_from_this()).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+
+ if (mInitCheck != OK) {
+ mPlugin.reset();
+ }
+ }
+
+ return mInitCheck;
+}
+
+status_t DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ SecurityLevel aSecurityLevel = toAidlSecurityLevel(level);
+
+ if (aSecurityLevel == SecurityLevel::UNKNOWN) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+ bool retry = true;
+ do {
+ std::vector<uint8_t> aSessionId;
+
+ ::ndk::ScopedAStatus status = mPlugin->openSession(aSecurityLevel, &aSessionId);
+ if (status.isOk()) sessionId = toVector(aSessionId);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+
+ if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
+ mLock.unlock();
+ // reclaimSession may call back to closeSession, since mLock is
+ // shared between Drm instances, we should unlock here to avoid
+ // deadlock.
+ retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
+ mLock.lock();
+ } else {
+ retry = false;
+ }
+ } while (retry);
+
+ if (err == OK) {
+ std::shared_ptr<DrmSessionClient> client =
+ ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
+ DrmSessionManager::Instance()->addSession(
+ AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
+ sessionId);
+ mOpenSessions.push_back(client);
+ mMetrics.SetSessionStart(sessionId);
+ }
+
+ mMetrics.mOpenSessionCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
+ ::ndk::ScopedAStatus status = mPlugin->closeSession(sessionIdAidl);
+ if (status.isOk()) {
+ DrmSessionManager::Instance()->removeSession(sessionId);
+ for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+ if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+ mOpenSessions.erase(i);
+ break;
+ }
+ }
+
+ status_t response = toStatusTAidl(status.getServiceSpecificError());
+ mMetrics.SetSessionEnd(sessionId);
+ mMetrics.mCloseSessionCounter.Increment(response);
+ return response;
+ }
+ mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
+ return DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ KeyType aKeyType;
+ if (keyType == DrmPlugin::kKeyType_Streaming) {
+ aKeyType = KeyType::STREAMING;
+ } else if (keyType == DrmPlugin::kKeyType_Offline) {
+ aKeyType = KeyType::OFFLINE;
+ } else if (keyType == DrmPlugin::kKeyType_Release) {
+ aKeyType = KeyType::RELEASE;
+ } else {
+ keyRequestTimer.SetAttribute(BAD_VALUE);
+ return BAD_VALUE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
+ std::vector<uint8_t> initDataAidl = toStdVec(initData);
+ KeyRequest keyRequest;
+
+ ::ndk::ScopedAStatus status =
+ mPlugin->getKeyRequest(sessionIdAidl, initDataAidl, toStdString(mimeType), aKeyType,
+ toKeyValueVector(optionalParameters), &keyRequest);
+ if (status.isOk()) {
+ request = toVector(keyRequest.request);
+ defaultUrl = toString8(keyRequest.defaultUrl);
+ *keyRequestType = toKeyRequestType(keyRequest.requestType);
+ }
+
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ keyRequestTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
+ std::vector<uint8_t> responseAidl = toStdVec(response);
+ KeySetId keySetIdsAidl;
+ ::ndk::ScopedAStatus status =
+ mPlugin->provideKeyResponse(sessionIdAidl, responseAidl, &keySetIdsAidl);
+
+ if (status.isOk()) keySetId = toVector(keySetIdsAidl.keySetId);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ keyResponseTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->removeKeys(toStdVec(keySetId));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ KeySetId keySetIdsAidl;
+ keySetIdsAidl.keySetId = toStdVec(keySetId);
+ ::ndk::ScopedAStatus status = mPlugin->restoreKeys(toStdVec(sessionId), keySetIdsAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<KeyValue> infoMapAidl;
+ ::ndk::ScopedAStatus status = mPlugin->queryKeyStatus(toStdVec(sessionId), &infoMapAidl);
+
+ infoMap = toKeyedVector(infoMapAidl);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ ProvisionRequest requestAidl;
+ ::ndk::ScopedAStatus status = mPlugin->getProvisionRequest(
+ toStdString(certType), toStdString(certAuthority), &requestAidl);
+
+ request = toVector(requestAidl.request);
+ defaultUrl = toString8(requestAidl.defaultUrl);
+
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ mMetrics.mGetProvisionRequestCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+ ProvideProvisionResponseResult result;
+ ::ndk::ScopedAStatus status = mPlugin->provideProvisionResponse(toStdVec(response), &result);
+
+ certificate = toVector(result.certificate);
+ wrappedKey = toVector(result.wrappedKey);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<SecureStop> result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecureStops(&result);
+
+ secureStops = toSecureStops(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<SecureStopId> result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecureStopIds(&result);
+
+ secureStopIds = toSecureStopIds(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ SecureStopId ssidAidl;
+ ssidAidl.secureStopId = toStdVec(ssid);
+
+ SecureStop result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecureStop(ssidAidl, &result);
+
+ secureStop = toVector(result.opaqueData);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ OpaqueData ssId;
+ ssId.opaqueData = toStdVec(ssRelease);
+ ::ndk::ScopedAStatus status = mPlugin->releaseSecureStops(ssId);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+ Mutex::Autolock autoLock(mLock);
+
+ INIT_CHECK();
+
+ SecureStopId ssidAidl;
+ ssidAidl.secureStopId = toStdVec(ssid);
+ ::ndk::ScopedAStatus status = mPlugin->removeSecureStop(ssidAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::removeAllSecureStops() {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->releaseAllSecureStops();
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (connected == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+
+ *connected = DrmPlugin::kHdcpLevelUnknown;
+ *max = DrmPlugin::kHdcpLevelUnknown;
+
+ HdcpLevels lvlsAidl;
+ ::ndk::ScopedAStatus status = mPlugin->getHdcpLevels(&lvlsAidl);
+
+ *connected = toHdcpLevel(lvlsAidl.connectedLevel);
+ *max = toHdcpLevel(lvlsAidl.maxLevel);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (open == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+
+ *open = 0;
+ *max = 0;
+
+ NumberOfSessions result;
+ ::ndk::ScopedAStatus status = mPlugin->getNumberOfSessions(&result);
+
+ *open = result.currentSessions;
+ *max = result.maxSessions;
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (level == NULL) {
+ return BAD_VALUE;
+ }
+
+ *level = DrmPlugin::kSecurityLevelUnknown;
+
+ SecurityLevel result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecurityLevel(toStdVec(sessionId), &result);
+
+ *level = toSecurityLevel(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<KeySetId> result;
+ ::ndk::ScopedAStatus status = mPlugin->getOfflineLicenseKeySetIds(&result);
+
+ keySetIds = toKeySetIds(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ KeySetId keySetIdAidl;
+ keySetIdAidl.keySetId = toStdVec(keySetId);
+ ::ndk::ScopedAStatus status = mPlugin->removeOfflineLicense(keySetIdAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
+ Mutex::Autolock autoLock(mLock);
+
+ INIT_CHECK();
+ *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
+
+ KeySetId keySetIdAidl;
+ keySetIdAidl.keySetId = toStdVec(keySetId);
+
+ OfflineLicenseState result;
+ ::ndk::ScopedAStatus status = mPlugin->getOfflineLicenseState(keySetIdAidl, &result);
+
+ *licenseState = toOfflineLicenseState(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyStringInternal(name, value);
+}
+
+status_t DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ std::string result;
+ ::ndk::ScopedAStatus status = mPlugin->getPropertyString(toStdString(name), &result);
+
+ value = toString8(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyByteArrayInternal(name, value);
+}
+
+status_t DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status = mPlugin->getPropertyByteArray(toStdString(name), &result);
+
+ value = toVector(result);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ if (name == kPropertyDeviceUniqueId) {
+ mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ }
+ return err;
+}
+
+status_t DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->setPropertyString(toStdString(name), toStdString(value));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->setPropertyByteArray(toStdString(name), toStdVec(value));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ if (consumer == nullptr) {
+ return UNEXPECTED_NULL;
+ }
+ consumer->consumeFrameworkMetrics(mMetrics);
+
+ // Append vendor metrics if they are supported.
+
+ String8 vendor;
+ String8 description;
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+ ALOGE("Get vendor failed or is empty");
+ vendor = "NONE";
+ }
+ if (getPropertyStringInternal(String8("description"), description) != OK ||
+ description.isEmpty()) {
+ ALOGE("Get description failed or is empty.");
+ description = "NONE";
+ }
+ vendor += ".";
+ vendor += description;
+
+ hidl_vec<DrmMetricGroupHidl> pluginMetrics;
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<DrmMetricGroupAidl> result;
+ ::ndk::ScopedAStatus status = mPlugin->getMetrics(&result);
+
+ if (status.isOk()) {
+ pluginMetrics = toDrmMetricGroupHidl(result);
+ consumer->consumeHidlMetrics(vendor, pluginMetrics);
+ }
+
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+
+ return err;
+}
+
+status_t DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::ndk::ScopedAStatus status =
+ mPlugin->setCipherAlgorithm(toStdVec(sessionId), toStdString(algorithm));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::ndk::ScopedAStatus status =
+ mPlugin->setMacAlgorithm(toStdVec(sessionId), toStdString(algorithm));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status = mPlugin->encrypt(toStdVec(sessionId), toStdVec(keyId),
+ toStdVec(input), toStdVec(iv), &result);
+
+ output = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status = mPlugin->decrypt(toStdVec(sessionId), toStdVec(keyId),
+ toStdVec(input), toStdVec(iv), &result);
+
+ output = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status =
+ mPlugin->sign(toStdVec(sessionId), toStdVec(keyId), toStdVec(message), &result);
+
+ signature = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::ndk::ScopedAStatus status = mPlugin->verify(toStdVec(sessionId), toStdVec(keyId),
+ toStdVec(message), toStdVec(signature), &match);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status =
+ mPlugin->signRSA(toStdVec(sessionId), toStdString(algorithm), toStdVec(message),
+ toStdVec(wrappedKey), &result);
+
+ signature = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::string mimeAidl(mime);
+ ::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoderDefault(mimeAidl, required);
+ if (!status.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
+ return DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t DrmHalAidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ auto aLevel = toAidlSecurityLevel(securityLevel);
+ std::string mimeAidl(mime);
+ ::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoder(mimeAidl, aLevel, required);
+ if (!status.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
+ return DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ std::string playbackIdAidl(playbackId);
+ ::ndk::ScopedAStatus status = mPlugin->setPlaybackId(toStdVec(sessionId), playbackIdAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs);
+}
+
+void DrmHalAidl::closeOpenSessions() {
+ Mutex::Autolock autoLock(mLock);
+ auto openSessions = mOpenSessions;
+ for (size_t i = 0; i < openSessions.size(); i++) {
+ mLock.unlock();
+ closeSession(openSessions[i]->mSessionId);
+ mLock.lock();
+ }
+ mOpenSessions.clear();
+}
+
+std::string DrmHalAidl::reportPluginMetrics() const {
+ Vector<uint8_t> metricsVector;
+ String8 vendor;
+ String8 description;
+ std::string metricsString;
+ if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
+ getPropertyStringInternal(String8("description"), description) == OK &&
+ getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
+ metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
+ status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
+ mMetrics.GetAppUid());
+ if (res != OK) {
+ ALOGE("Metrics were retrieved but could not be reported: %d", res);
+ }
+ }
+ return metricsString;
+}
+
+std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
+ mediametrics_handle_t item(mediametrics_create("mediadrm"));
+ mediametrics_setUid(item, mMetrics.GetAppUid());
+ String8 vendor;
+ String8 description;
+ status_t result = getPropertyStringInternal(String8("vendor"), vendor);
+ if (result != OK) {
+ ALOGE("Failed to get vendor from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "vendor", vendor.c_str());
+ }
+ result = getPropertyStringInternal(String8("description"), description);
+ if (result != OK) {
+ ALOGE("Failed to get description from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "description", description.c_str());
+ }
+
+ std::string serializedMetrics;
+ result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ if (result != OK) {
+ ALOGE("Failed to serialize framework metrics: %d", result);
+ }
+ std::string b64EncodedMetrics =
+ toBase64StringNoPad(serializedMetrics.data(), serializedMetrics.size());
+ if (!b64EncodedMetrics.empty()) {
+ mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
+ }
+ if (!pluginMetrics.empty()) {
+ mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str());
+ }
+ if (!mediametrics_selfRecord(item)) {
+ ALOGE("Failed to self record framework metrics");
+ }
+ mediametrics_delete(item);
+ return serializedMetrics;
+}
+
+void DrmHalAidl::cleanup() {
+ closeOpenSessions();
+
+ Mutex::Autolock autoLock(mLock);
+ reportFrameworkMetrics(reportPluginMetrics());
+
+ setListener(NULL);
+ mInitCheck = NO_INIT;
+ if (mPlugin != NULL) {
+ if (!mPlugin->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ }
+
+ mPlugin.reset();
+}
+
+status_t DrmHalAidl::destroyPlugin() {
+ cleanup();
+ return OK;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onEvent(EventTypeAidl eventTypeAidl,
+ const std::vector<uint8_t>& sessionId,
+ const std::vector<uint8_t>& data) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mMetrics.mEventCounter.Increment((uint32_t)eventTypeAidl);
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ DrmPlugin::EventType eventType;
+ switch (eventTypeAidl) {
+ case EventTypeAidl::PROVISION_REQUIRED:
+ eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
+ break;
+ case EventTypeAidl::KEY_NEEDED:
+ eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
+ break;
+ case EventTypeAidl::KEY_EXPIRED:
+ eventType = DrmPlugin::kDrmPluginEventKeyExpired;
+ break;
+ case EventTypeAidl::VENDOR_DEFINED:
+ eventType = DrmPlugin::kDrmPluginEventVendorDefined;
+ break;
+ case EventTypeAidl::SESSION_RECLAIMED:
+ eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
+ break;
+ default:
+ return _aidl_status;
+ }
+
+ listener->sendEvent(eventType, toHidlVec(toVector(sessionId)), toHidlVec(toVector(data)));
+ }
+
+ return _aidl_status;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onExpirationUpdate(const std::vector<uint8_t>& sessionId,
+ int64_t expiryTimeInMS) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendExpirationUpdate(toHidlVec(toVector(sessionId)), expiryTimeInMS);
+ }
+
+ return _aidl_status;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onKeysChange(const std::vector<uint8_t>& sessionId,
+ const std::vector<KeyStatus>& keyStatusListAidl,
+ bool hasNewUsableKey) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ std::vector<DrmKeyStatus> keyStatusList;
+ size_t nKeys = keyStatusListAidl.size();
+ for (size_t i = 0; i < nKeys; ++i) {
+ const KeyStatus& keyStatus = keyStatusListAidl[i];
+ uint32_t type;
+ switch (keyStatus.type) {
+ case KeyStatusType::USABLE:
+ type = DrmPlugin::kKeyStatusType_Usable;
+ break;
+ case KeyStatusType::EXPIRED:
+ type = DrmPlugin::kKeyStatusType_Expired;
+ break;
+ case KeyStatusType::OUTPUTNOTALLOWED:
+ type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
+ break;
+ case KeyStatusType::STATUSPENDING:
+ type = DrmPlugin::kKeyStatusType_StatusPending;
+ break;
+ case KeyStatusType::USABLEINFUTURE:
+ type = DrmPlugin::kKeyStatusType_UsableInFuture;
+ break;
+ case KeyStatusType::INTERNALERROR:
+ default:
+ type = DrmPlugin::kKeyStatusType_InternalError;
+ break;
+ }
+ keyStatusList.push_back({type, toHidlVec(toVector(keyStatus.keyId))});
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)keyStatus.type);
+ }
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendKeysChange(toHidlVec(toVector(sessionId)), keyStatusList, hasNewUsableKey);
+ }
+ else {
+ // There's no listener. But we still want to count the key change
+ // events.
+ size_t nKeys = keyStatusListAidl.size();
+
+ for (size_t i = 0; i < nKeys; i++) {
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)keyStatusListAidl[i].type);
+ }
+ }
+
+ return _aidl_status;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onSessionLostState(const std::vector<uint8_t>& sessionId) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendSessionLostState(toHidlVec(toVector(sessionId)));
+ }
+
+ return _aidl_status;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
new file mode 100644
index 0000000..a5dd4d7
--- /dev/null
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -0,0 +1,1516 @@
+/*
+ * 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 "DrmHalHidl"
+
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <android/binder_manager.h>
+#include <android/hardware/drm/1.2/types.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <media/EventMetric.h>
+#include <media/MediaMetrics.h>
+#include <media/PluginMetricsReporting.h>
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/DrmHalHidl.h>
+#include <mediadrm/DrmSessionClientInterface.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmUtils.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/Log.h>
+
+#include <iomanip>
+#include <vector>
+
+using ::android::sp;
+using ::android::DrmUtils::toStatusT;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+using ::android::os::PersistableBundle;
+using drm::V1_0::KeyedVector;
+using drm::V1_0::KeyRequestType;
+using drm::V1_0::KeyType;
+using drm::V1_0::KeyValue;
+using drm::V1_0::SecureStop;
+using drm::V1_0::SecureStopId;
+using drm::V1_0::Status;
+using drm::V1_1::HdcpLevel;
+using drm::V1_1::SecureStopRelease;
+using drm::V1_1::SecurityLevel;
+using drm::V1_2::KeySetId;
+using drm::V1_2::KeyStatusType;
+
+typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
+typedef drm::V1_2::Status Status_V1_2;
+typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
+
+namespace {
+
+// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
+// in the MediaDrm API.
+constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
+constexpr char kEqualsSign[] = "=";
+
+template <typename T>
+std::string toBase64StringNoPad(const T* data, size_t size) {
+ // Note that the base 64 conversion only works with arrays of single-byte
+ // values. If the source is empty or is not an array of single-byte values,
+ // return empty string.
+ if (size == 0 || sizeof(data[0]) != 1) {
+ return "";
+ }
+
+ android::AString outputString;
+ encodeBase64(data, size, &outputString);
+ // Remove trailing equals padding if it exists.
+ while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
+ outputString.erase(outputString.size() - 1, 1);
+ }
+
+ return std::string(outputString.c_str(), outputString.size());
+}
+
+} // anonymous namespace
+
+namespace android {
+
+#define INIT_CHECK() \
+ { \
+ if (mInitCheck != OK) return mInitCheck; \
+ }
+
+static const Vector<uint8_t> toVector(const hidl_vec<uint8_t>& vec) {
+ Vector<uint8_t> vector;
+ vector.appendArray(vec.data(), vec.size());
+ return *const_cast<const Vector<uint8_t>*>(&vector);
+}
+
+static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t>& vector) {
+ hidl_vec<uint8_t> vec;
+ vec.setToExternal(const_cast<uint8_t*>(vector.array()), vector.size());
+ return vec;
+}
+
+static String8 toString8(const hidl_string& string) {
+ return String8(string.c_str());
+}
+
+static hidl_string toHidlString(const String8& string) {
+ return hidl_string(string.string());
+}
+
+static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
+ switch (level) {
+ case SecurityLevel::SW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelSwSecureCrypto;
+ case SecurityLevel::SW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelSwSecureDecode;
+ case SecurityLevel::HW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelHwSecureCrypto;
+ case SecurityLevel::HW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelHwSecureDecode;
+ case SecurityLevel::HW_SECURE_ALL:
+ return DrmPlugin::kSecurityLevelHwSecureAll;
+ default:
+ return DrmPlugin::kSecurityLevelUnknown;
+ }
+}
+
+static SecurityLevel toHidlSecurityLevel(DrmPlugin::SecurityLevel level) {
+ switch (level) {
+ case DrmPlugin::kSecurityLevelSwSecureCrypto:
+ return SecurityLevel::SW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelSwSecureDecode:
+ return SecurityLevel::SW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureCrypto:
+ return SecurityLevel::HW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelHwSecureDecode:
+ return SecurityLevel::HW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureAll:
+ return SecurityLevel::HW_SECURE_ALL;
+ default:
+ return SecurityLevel::UNKNOWN;
+ }
+}
+
+static DrmPlugin::OfflineLicenseState toOfflineLicenseState(OfflineLicenseState licenseState) {
+ switch (licenseState) {
+ case OfflineLicenseState::USABLE:
+ return DrmPlugin::kOfflineLicenseStateUsable;
+ case OfflineLicenseState::INACTIVE:
+ return DrmPlugin::kOfflineLicenseStateReleased;
+ default:
+ return DrmPlugin::kOfflineLicenseStateUnknown;
+ }
+}
+
+static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel_V1_2 level) {
+ switch (level) {
+ case HdcpLevel_V1_2::HDCP_NONE:
+ return DrmPlugin::kHdcpNone;
+ case HdcpLevel_V1_2::HDCP_V1:
+ return DrmPlugin::kHdcpV1;
+ case HdcpLevel_V1_2::HDCP_V2:
+ return DrmPlugin::kHdcpV2;
+ case HdcpLevel_V1_2::HDCP_V2_1:
+ return DrmPlugin::kHdcpV2_1;
+ case HdcpLevel_V1_2::HDCP_V2_2:
+ return DrmPlugin::kHdcpV2_2;
+ case HdcpLevel_V1_2::HDCP_V2_3:
+ return DrmPlugin::kHdcpV2_3;
+ case HdcpLevel_V1_2::HDCP_NO_OUTPUT:
+ return DrmPlugin::kHdcpNoOutput;
+ default:
+ return DrmPlugin::kHdcpLevelUnknown;
+ }
+}
+static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>& keyedVector) {
+ std::vector<KeyValue> stdKeyedVector;
+ for (size_t i = 0; i < keyedVector.size(); i++) {
+ KeyValue keyValue;
+ keyValue.key = toHidlString(keyedVector.keyAt(i));
+ keyValue.value = toHidlString(keyedVector.valueAt(i));
+ stdKeyedVector.push_back(keyValue);
+ }
+ return ::KeyedVector(stdKeyedVector);
+}
+
+static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector& hKeyedVector) {
+ KeyedVector<String8, String8> keyedVector;
+ for (size_t i = 0; i < hKeyedVector.size(); i++) {
+ keyedVector.add(toString8(hKeyedVector[i].key), toString8(hKeyedVector[i].value));
+ }
+ return keyedVector;
+}
+
+static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>& hSecureStops) {
+ List<Vector<uint8_t>> secureStops;
+ for (size_t i = 0; i < hSecureStops.size(); i++) {
+ secureStops.push_back(toVector(hSecureStops[i].opaqueData));
+ }
+ return secureStops;
+}
+
+static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>& hSecureStopIds) {
+ List<Vector<uint8_t>> secureStopIds;
+ for (size_t i = 0; i < hSecureStopIds.size(); i++) {
+ secureStopIds.push_back(toVector(hSecureStopIds[i]));
+ }
+ return secureStopIds;
+}
+
+static List<Vector<uint8_t>> toKeySetIds(const hidl_vec<KeySetId>& hKeySetIds) {
+ List<Vector<uint8_t>> keySetIds;
+ for (size_t i = 0; i < hKeySetIds.size(); i++) {
+ keySetIds.push_back(toVector(hKeySetIds[i]));
+ }
+ return keySetIds;
+}
+
+Mutex DrmHalHidl::mLock;
+
+struct DrmHalHidl::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
+ explicit DrmSessionClient(DrmHalHidl* drm, const Vector<uint8_t>& sessionId)
+ : mSessionId(sessionId), mDrm(drm) {}
+
+ ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
+
+ const Vector<uint8_t> mSessionId;
+
+ virtual ~DrmSessionClient();
+
+ private:
+ wp<DrmHalHidl> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
+::ndk::ScopedAStatus DrmHalHidl::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+ auto sessionId = mSessionId;
+ sp<DrmHalHidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ status_t err = drm->closeSession(sessionId);
+ if (err != OK) {
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ drm->sendEvent(EventType::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>());
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmHalHidl::DrmSessionClient::getName(::std::string* _aidl_return) {
+ String8 name;
+ sp<DrmHalHidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ name.append("<deleted>");
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+ name.append("<Get vendor failed or is empty>");
+ }
+ name.append("[");
+ for (size_t i = 0; i < mSessionId.size(); ++i) {
+ name.appendFormat("%02x", mSessionId[i]);
+ }
+ name.append("]");
+ *_aidl_return = name;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+DrmHalHidl::DrmSessionClient::~DrmSessionClient() {
+ DrmSessionManager::Instance()->removeSession(mSessionId);
+}
+
+DrmHalHidl::DrmHalHidl()
+ : mFactories(makeDrmFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
+
+void DrmHalHidl::closeOpenSessions() {
+ Mutex::Autolock autoLock(mLock);
+ auto openSessions = mOpenSessions;
+ for (size_t i = 0; i < openSessions.size(); i++) {
+ mLock.unlock();
+ closeSession(openSessions[i]->mSessionId);
+ mLock.lock();
+ }
+ mOpenSessions.clear();
+}
+
+DrmHalHidl::~DrmHalHidl() {}
+
+void DrmHalHidl::cleanup() {
+ closeOpenSessions();
+
+ Mutex::Autolock autoLock(mLock);
+ reportFrameworkMetrics(reportPluginMetrics());
+
+ setListener(NULL);
+ mInitCheck = NO_INIT;
+ if (mPluginV1_2 != NULL) {
+ if (!mPluginV1_2->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ } else if (mPlugin != NULL) {
+ if (!mPlugin->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ }
+ mPlugin.clear();
+ mPluginV1_1.clear();
+ mPluginV1_2.clear();
+ mPluginV1_4.clear();
+}
+
+std::vector<sp<IDrmFactory>> DrmHalHidl::makeDrmFactories() {
+ static std::vector<sp<IDrmFactory>> factories(DrmUtils::MakeDrmFactories());
+ if (factories.size() == 0) {
+ // must be in passthrough mode, load the default passthrough service
+ auto passthrough = IDrmFactory::getService();
+ if (passthrough != NULL) {
+ DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
+ factories.push_back(passthrough);
+ } else {
+ DrmUtils::LOG2BE("Failed to find any drm factories");
+ }
+ }
+ return factories;
+}
+
+sp<IDrmPlugin> DrmHalHidl::makeDrmPlugin(const sp<IDrmFactory>& factory, const uint8_t uuid[16],
+ const String8& appPackageName) {
+ mAppPackageName = appPackageName;
+ mMetrics.SetAppPackageName(appPackageName);
+ mMetrics.SetAppUid(AIBinder_getCallingUid());
+
+ sp<IDrmPlugin> plugin;
+ Return<void> hResult = factory->createPlugin(
+ uuid, appPackageName.string(), [&](Status status, const sp<IDrmPlugin>& hPlugin) {
+ if (status != Status::OK) {
+ DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
+ return;
+ }
+ plugin = hPlugin;
+ });
+
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE(uuid, "createPlugin remote call failed: %s",
+ hResult.description().c_str());
+ }
+
+ return plugin;
+}
+
+status_t DrmHalHidl::initCheck() const {
+ return mInitCheck;
+}
+
+status_t DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
+ Mutex::Autolock lock(mEventLock);
+ mListener = listener;
+ return NO_ERROR;
+}
+
+Return<void> DrmHalHidl::sendEvent(EventType hEventType, const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<uint8_t>& data) {
+ mMetrics.mEventCounter.Increment((uint32_t)hEventType);
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ DrmPlugin::EventType eventType;
+ switch (hEventType) {
+ case EventType::PROVISION_REQUIRED:
+ eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
+ break;
+ case EventType::KEY_NEEDED:
+ eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
+ break;
+ case EventType::KEY_EXPIRED:
+ eventType = DrmPlugin::kDrmPluginEventKeyExpired;
+ break;
+ case EventType::VENDOR_DEFINED:
+ eventType = DrmPlugin::kDrmPluginEventVendorDefined;
+ break;
+ case EventType::SESSION_RECLAIMED:
+ eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
+ break;
+ default:
+ return Void();
+ }
+ listener->sendEvent(eventType, sessionId, data);
+ }
+ return Void();
+}
+
+Return<void> DrmHalHidl::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+ int64_t expiryTimeInMS) {
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+ }
+ return Void();
+}
+
+Return<void> DrmHalHidl::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_0>& keyStatusList_V1_0,
+ bool hasNewUsableKey) {
+ std::vector<KeyStatus> keyStatusVec;
+ for (const auto& keyStatus_V1_0 : keyStatusList_V1_0) {
+ keyStatusVec.push_back(
+ {keyStatus_V1_0.keyId, static_cast<KeyStatusType>(keyStatus_V1_0.type)});
+ }
+ hidl_vec<KeyStatus> keyStatusList_V1_2(keyStatusVec);
+ return sendKeysChange_1_2(sessionId, keyStatusList_V1_2, hasNewUsableKey);
+}
+
+Return<void> DrmHalHidl::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& hKeyStatusList,
+ bool hasNewUsableKey) {
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ std::vector<DrmKeyStatus> keyStatusList;
+ size_t nKeys = hKeyStatusList.size();
+ for (size_t i = 0; i < nKeys; ++i) {
+ const KeyStatus& keyStatus = hKeyStatusList[i];
+ uint32_t type;
+ switch (keyStatus.type) {
+ case KeyStatusType::USABLE:
+ type = DrmPlugin::kKeyStatusType_Usable;
+ break;
+ case KeyStatusType::EXPIRED:
+ type = DrmPlugin::kKeyStatusType_Expired;
+ break;
+ case KeyStatusType::OUTPUTNOTALLOWED:
+ type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
+ break;
+ case KeyStatusType::STATUSPENDING:
+ type = DrmPlugin::kKeyStatusType_StatusPending;
+ break;
+ case KeyStatusType::USABLEINFUTURE:
+ type = DrmPlugin::kKeyStatusType_UsableInFuture;
+ break;
+ case KeyStatusType::INTERNALERROR:
+ default:
+ type = DrmPlugin::kKeyStatusType_InternalError;
+ break;
+ }
+ keyStatusList.push_back({type, keyStatus.keyId});
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)keyStatus.type);
+ }
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+ } else {
+ // There's no listener. But we still want to count the key change
+ // events.
+ size_t nKeys = hKeyStatusList.size();
+ for (size_t i = 0; i < nKeys; i++) {
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)hKeyStatusList[i].type);
+ }
+ }
+
+ return Void();
+}
+
+Return<void> DrmHalHidl::sendSessionLostState(const hidl_vec<uint8_t>& sessionId) {
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendSessionLostState(sessionId);
+ }
+ return Void();
+}
+
+status_t DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool* isSupported) {
+ *isSupported = false;
+
+ // handle default value cases
+ if (level == DrmPlugin::kSecurityLevelUnknown) {
+ if (mimeType == "") {
+ // isCryptoSchemeSupported(uuid)
+ *isSupported = true;
+ } else {
+ // isCryptoSchemeSupported(uuid, mimeType)
+ *isSupported = factory->isContentTypeSupported(mimeType.string());
+ }
+ return OK;
+ } else if (mimeType == "") {
+ return BAD_VALUE;
+ }
+
+ sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
+ if (factoryV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ } else {
+ *isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
+ toHidlSecurityLevel(level));
+ return OK;
+ }
+}
+
+status_t DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
+ Mutex::Autolock autoLock(mLock);
+ *isSupported = false;
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ return matchMimeTypeAndSecurityLevel(mFactories[i], uuid, mimeType, level, isSupported);
+ }
+ }
+ return OK;
+}
+
+status_t DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ Mutex::Autolock autoLock(mLock);
+
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
+ if (hResult.isOk() && hResult) {
+ auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+ if (plugin != NULL) {
+ mPlugin = plugin;
+ mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
+ mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
+ mPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mPlugin);
+ break;
+ }
+ }
+ }
+
+ if (mPlugin == NULL) {
+ DrmUtils::LOG2BE(uuid, "No supported hal instance found");
+ mInitCheck = ERROR_UNSUPPORTED;
+ } else {
+ mInitCheck = OK;
+ if (mPluginV1_2 != NULL) {
+ if (!mPluginV1_2->setListener(this).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ } else if (!mPlugin->setListener(this).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ if (mInitCheck != OK) {
+ mPlugin.clear();
+ mPluginV1_1.clear();
+ mPluginV1_2.clear();
+ mPluginV1_4.clear();
+ }
+ }
+
+ return mInitCheck;
+}
+
+status_t DrmHalHidl::destroyPlugin() {
+ cleanup();
+ return OK;
+}
+
+status_t DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ SecurityLevel hSecurityLevel = toHidlSecurityLevel(level);
+ bool setSecurityLevel = true;
+
+ if (level == DrmPlugin::kSecurityLevelMax) {
+ setSecurityLevel = false;
+ } else {
+ if (hSecurityLevel == SecurityLevel::UNKNOWN) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+ }
+
+ status_t err = UNKNOWN_ERROR;
+ bool retry = true;
+ do {
+ hidl_vec<uint8_t> hSessionId;
+
+ Return<void> hResult;
+ if (mPluginV1_1 == NULL || !setSecurityLevel) {
+ hResult = mPlugin->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
+ if (status == Status::OK) {
+ sessionId = toVector(id);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
+ [&](Status status, const hidl_vec<uint8_t>& id) {
+ if (status == Status::OK) {
+ sessionId = toVector(id);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ if (!hResult.isOk()) {
+ err = DEAD_OBJECT;
+ }
+
+ if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
+ mLock.unlock();
+ // reclaimSession may call back to closeSession, since mLock is
+ // shared between Drm instances, we should unlock here to avoid
+ // deadlock.
+ retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
+ mLock.lock();
+ } else {
+ retry = false;
+ }
+ } while (retry);
+
+ if (err == OK) {
+ std::shared_ptr<DrmSessionClient> client =
+ ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
+ DrmSessionManager::Instance()->addSession(
+ AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
+ sessionId);
+ mOpenSessions.push_back(client);
+ mMetrics.SetSessionStart(sessionId);
+ }
+
+ mMetrics.mOpenSessionCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
+ if (status.isOk()) {
+ if (status == Status::OK) {
+ DrmSessionManager::Instance()->removeSession(sessionId);
+ for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+ if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+ mOpenSessions.erase(i);
+ break;
+ }
+ }
+ }
+ status_t response = toStatusT(status);
+ mMetrics.SetSessionEnd(sessionId);
+ mMetrics.mCloseSessionCounter.Increment(response);
+ return response;
+ }
+ mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
+ return DEAD_OBJECT;
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType::INITIAL:
+ return DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case KeyRequestType::RENEWAL:
+ return DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case KeyRequestType::RELEASE:
+ return DrmPlugin::kKeyRequestType_Release;
+ break;
+ default:
+ return DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType_1_1(KeyRequestType_V1_1 keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType_V1_1::NONE:
+ return DrmPlugin::kKeyRequestType_None;
+ break;
+ case KeyRequestType_V1_1::UPDATE:
+ return DrmPlugin::kKeyRequestType_Update;
+ break;
+ default:
+ return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType));
+ break;
+ }
+}
+
+status_t DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ KeyType hKeyType;
+ if (keyType == DrmPlugin::kKeyType_Streaming) {
+ hKeyType = KeyType::STREAMING;
+ } else if (keyType == DrmPlugin::kKeyType_Offline) {
+ hKeyType = KeyType::OFFLINE;
+ } else if (keyType == DrmPlugin::kKeyType_Release) {
+ hKeyType = KeyType::RELEASE;
+ } else {
+ keyRequestTimer.SetAttribute(BAD_VALUE);
+ return BAD_VALUE;
+ }
+
+ ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
+
+ status_t err = UNKNOWN_ERROR;
+ Return<void> hResult;
+
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getKeyRequest_1_2(
+ toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType,
+ hOptionalParameters,
+ [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) {
+ if (status == Status_V1_2::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ } else if (mPluginV1_1 != NULL) {
+ hResult = mPluginV1_1->getKeyRequest_1_1(
+ toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType,
+ hOptionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPlugin->getKeyRequest(
+ toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType,
+ hOptionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ keyRequestTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response),
+ [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
+ if (status == Status::OK) {
+ keySetId = toVector(hKeySetId);
+ }
+ err = toStatusT(status);
+ });
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ keyResponseTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId), toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::KeyedVector hInfoMap;
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->queryKeyStatus(
+ toHidlVec(sessionId), [&](Status status, const hidl_vec<KeyValue>& map) {
+ if (status == Status::OK) {
+ infoMap = toKeyedVector(map);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+ Return<void> hResult;
+
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getProvisionRequest_1_2(
+ toHidlString(certType), toHidlString(certAuthority),
+ [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status_V1_2::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPlugin->getProvisionRequest(toHidlString(certType), toHidlString(certAuthority),
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ mMetrics.mGetProvisionRequestCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->provideProvisionResponse(
+ toHidlVec(response), [&](Status status, const hidl_vec<uint8_t>& hCertificate,
+ const hidl_vec<uint8_t>& hWrappedKey) {
+ if (status == Status::OK) {
+ certificate = toVector(hCertificate);
+ wrappedKey = toVector(hWrappedKey);
+ }
+ err = toStatusT(status);
+ });
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->getSecureStops([&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
+ if (status == Status::OK) {
+ secureStops = toSecureStops(hSecureStops);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_1->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
+ if (status == Status::OK) {
+ secureStopIds = toSecureStopIds(hSecureStopIds);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->getSecureStop(
+ toHidlVec(ssid), [&](Status status, const SecureStop& hSecureStop) {
+ if (status == Status::OK) {
+ secureStop = toVector(hSecureStop.opaqueData);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status(Status::ERROR_DRM_UNKNOWN);
+ if (mPluginV1_1 != NULL) {
+ SecureStopRelease secureStopRelease;
+ secureStopRelease.opaqueData = toHidlVec(ssRelease);
+ status = mPluginV1_1->releaseSecureStops(secureStopRelease);
+ } else {
+ status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
+ }
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::removeAllSecureStops() {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status(Status::ERROR_DRM_UNKNOWN);
+ if (mPluginV1_1 != NULL) {
+ status = mPluginV1_1->removeAllSecureStops();
+ } else {
+ status = mPlugin->releaseAllSecureStops();
+ }
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (connected == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ *connected = DrmPlugin::kHdcpLevelUnknown;
+ *max = DrmPlugin::kHdcpLevelUnknown;
+
+ Return<void> hResult;
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getHdcpLevels_1_2([&](Status_V1_2 status,
+ const HdcpLevel_V1_2& hConnected,
+ const HdcpLevel_V1_2& hMax) {
+ if (status == Status_V1_2::OK) {
+ *connected = toHdcpLevel(hConnected);
+ *max = toHdcpLevel(hMax);
+ }
+ err = toStatusT(status);
+ });
+ } else if (mPluginV1_1 != NULL) {
+ hResult = mPluginV1_1->getHdcpLevels(
+ [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
+ if (status == Status::OK) {
+ *connected = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hConnected));
+ *max = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hMax));
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (open == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ *open = 0;
+ *max = 0;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ Return<void> hResult =
+ mPluginV1_1->getNumberOfSessions([&](Status status, uint32_t hOpen, uint32_t hMax) {
+ if (status == Status::OK) {
+ *open = hOpen;
+ *max = hMax;
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (level == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ *level = DrmPlugin::kSecurityLevelUnknown;
+
+ Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
+ [&](Status status, SecurityLevel hLevel) {
+ if (status == Status::OK) {
+ *level = toSecurityLevel(hLevel);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
+ [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
+ if (status == Status::OK) {
+ keySetIds = toKeySetIds(hKeySetIds);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+ *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_2->getOfflineLicenseState(
+ toHidlVec(keySetId), [&](Status status, OfflineLicenseState hLicenseState) {
+ if (status == Status::OK) {
+ *licenseState = toOfflineLicenseState(hLicenseState);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyStringInternal(name, value);
+}
+
+status_t DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->getPropertyString(
+ toHidlString(name), [&](Status status, const hidl_string& hValue) {
+ if (status == Status::OK) {
+ value = toString8(hValue);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyByteArrayInternal(name, value);
+}
+
+status_t DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->getPropertyByteArray(
+ toHidlString(name), [&](Status status, const hidl_vec<uint8_t>& hValue) {
+ if (status == Status::OK) {
+ value = toVector(hValue);
+ }
+ err = toStatusT(status);
+ });
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ if (name == kPropertyDeviceUniqueId) {
+ mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ }
+ return err;
+}
+
+status_t DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->setPropertyString(toHidlString(name), toHidlString(value));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name), toHidlVec(value));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ if (consumer == nullptr) {
+ return UNEXPECTED_NULL;
+ }
+ consumer->consumeFrameworkMetrics(mMetrics);
+
+ // Append vendor metrics if they are supported.
+ if (mPluginV1_1 != NULL) {
+ String8 vendor;
+ String8 description;
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+ ALOGE("Get vendor failed or is empty");
+ vendor = "NONE";
+ }
+ if (getPropertyStringInternal(String8("description"), description) != OK ||
+ description.isEmpty()) {
+ ALOGE("Get description failed or is empty.");
+ description = "NONE";
+ }
+ vendor += ".";
+ vendor += description;
+
+ hidl_vec<DrmMetricGroup> pluginMetrics;
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> status =
+ mPluginV1_1->getMetrics([&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
+ if (status != Status::OK) {
+ ALOGV("Error getting plugin metrics: %d", status);
+ } else {
+ consumer->consumeHidlMetrics(vendor, pluginMetrics);
+ }
+ err = toStatusT(status);
+ });
+ return status.isOk() ? err : DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Return<Status> status =
+ mPlugin->setCipherAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->encrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
+ toHidlVec(iv), [&](Status status, const hidl_vec<uint8_t>& hOutput) {
+ if (status == Status::OK) {
+ output = toVector(hOutput);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->decrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
+ toHidlVec(iv), [&](Status status, const hidl_vec<uint8_t>& hOutput) {
+ if (status == Status::OK) {
+ output = toVector(hOutput);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->sign(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
+ [&](Status status, const hidl_vec<uint8_t>& hSignature) {
+ if (status == Status::OK) {
+ signature = toVector(hSignature);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->verify(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
+ toHidlVec(signature), [&](Status status, bool hMatch) {
+ if (status == Status::OK) {
+ match = hMatch;
+ } else {
+ match = false;
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->signRSA(
+ toHidlVec(sessionId), toHidlString(algorithm), toHidlVec(message),
+ toHidlVec(wrappedKey), [&](Status status, const hidl_vec<uint8_t>& hSignature) {
+ if (status == Status::OK) {
+ signature = toVector(hSignature);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+std::string DrmHalHidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
+ mediametrics_handle_t item(mediametrics_create("mediadrm"));
+ mediametrics_setUid(item, mMetrics.GetAppUid());
+ String8 vendor;
+ String8 description;
+ status_t result = getPropertyStringInternal(String8("vendor"), vendor);
+ if (result != OK) {
+ ALOGE("Failed to get vendor from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "vendor", vendor.c_str());
+ }
+ result = getPropertyStringInternal(String8("description"), description);
+ if (result != OK) {
+ ALOGE("Failed to get description from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "description", description.c_str());
+ }
+
+ std::string serializedMetrics;
+ result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ if (result != OK) {
+ ALOGE("Failed to serialize framework metrics: %d", result);
+ }
+ std::string b64EncodedMetrics =
+ toBase64StringNoPad(serializedMetrics.data(), serializedMetrics.size());
+ if (!b64EncodedMetrics.empty()) {
+ mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
+ }
+ if (!pluginMetrics.empty()) {
+ mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str());
+ }
+ if (!mediametrics_selfRecord(item)) {
+ ALOGE("Failed to self record framework metrics");
+ }
+ mediametrics_delete(item);
+ return serializedMetrics;
+}
+
+std::string DrmHalHidl::reportPluginMetrics() const {
+ Vector<uint8_t> metricsVector;
+ String8 vendor;
+ String8 description;
+ std::string metricsString;
+ if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
+ getPropertyStringInternal(String8("description"), description) == OK &&
+ getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
+ metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
+ status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
+ mMetrics.GetAppUid());
+ if (res != OK) {
+ ALOGE("Metrics were retrieved but could not be reported: %d", res);
+ }
+ }
+ return metricsString;
+}
+
+status_t DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ if (mPluginV1_4 == NULL) {
+ return false;
+ }
+ auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (required) {
+ *required = hResult;
+ }
+ return OK;
+}
+
+status_t DrmHalHidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ if (mPluginV1_4 == NULL) {
+ return false;
+ }
+ auto hLevel = toHidlSecurityLevel(securityLevel);
+ auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (required) {
+ *required = hResult;
+ }
+ return OK;
+}
+
+status_t DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+ Mutex::Autolock autoLock(mLock);
+ if (mPluginV1_4 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+ auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
+ return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index 996fd19..77b5343 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -123,20 +123,19 @@
});
mKeyStatusChangeCounter.ExportValues(
- [&](const KeyStatusType key_status_type, const int64_t value) {
+ [&](const uint32_t key_status_type, const int64_t value) {
DrmFrameworkMetrics::Counter *counter =
metrics.add_key_status_change_counter();
counter->set_count(value);
- counter->mutable_attributes()->set_key_status_type(
- (uint32_t)key_status_type);
+ counter->mutable_attributes()->set_key_status_type(key_status_type);
});
mEventCounter.ExportValues(
- [&](const EventType event_type, const int64_t value) {
+ [&](const uint32_t event_type, const int64_t value) {
DrmFrameworkMetrics::Counter *counter =
metrics.add_event_callback_counter();
counter->set_count(value);
- counter->mutable_attributes()->set_event_type((uint32_t)event_type);
+ counter->mutable_attributes()->set_event_type(event_type);
});
mGetDeviceUniqueIdCounter.ExportValues(
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
index 5f0b26e..dca3050 100644
--- a/drm/libmediadrm/DrmMetricsConsumer.cpp
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -32,26 +32,24 @@
namespace {
-template <typename T> std::string GetAttributeName(T type);
-
-template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
- static const char *type_names[] = {"USABLE", "EXPIRED",
+std::string GetAttributeName(std::string typeName, uint32_t attribute) {
+ if (typeName == "KeyStatusChange") {
+ static const char *type_names[] = {"USABLE", "EXPIRED",
"OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
"INTERNAL_ERROR", "USABLE_IN_FUTURE"};
- if (((size_t)type) >= arraysize(type_names)) {
- return "UNKNOWN_TYPE";
+ if (attribute >= arraysize(type_names)) {
+ return "UNKNOWN_TYPE";
+ }
+ return type_names[attribute];
}
- return type_names[(size_t)type];
-}
-
-template <> std::string GetAttributeName<EventType>(EventType type) {
+
static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
"KEY_EXPIRED", "VENDOR_DEFINED",
"SESSION_RECLAIMED"};
- if (((size_t)type) >= arraysize(type_names)) {
+ if (attribute >= arraysize(type_names)) {
return "UNKNOWN_TYPE";
}
- return type_names[(size_t)type];
+ return type_names[attribute];
}
template <typename T>
@@ -87,14 +85,14 @@
template <typename T>
void ExportCounterMetricWithAttributeNames(
- const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
+ const android::CounterMetric<T> &counter, std::string typeName, PersistableBundle *metrics) {
if (!metrics) {
ALOGE("metrics was unexpectedly null.");
return;
}
- counter.ExportValues([&](const T &attribute, const int64_t value) {
+ counter.ExportValues([&](const uint32_t attribute, const int64_t value) {
std::string name = counter.metric_name() + "." +
- GetAttributeName(attribute) + ".count";
+ GetAttributeName(typeName, attribute) + ".count";
metrics->putLong(android::String16(name.c_str()), value);
});
}
@@ -196,8 +194,8 @@
ExportEventMetric(metrics.mProvideKeyResponseTimeUs, mBundle);
ExportCounterMetric(metrics.mGetProvisionRequestCounter, mBundle);
ExportCounterMetric(metrics.mProvideProvisionResponseCounter, mBundle);
- ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, mBundle);
- ExportCounterMetricWithAttributeNames(metrics.mEventCounter, mBundle);
+ ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, "KeyStatusChange", mBundle);
+ ExportCounterMetricWithAttributeNames(metrics.mEventCounter, "Event", mBundle);
ExportCounterMetric(metrics.mGetDeviceUniqueIdCounter, mBundle);
ExportSessionLifespans(metrics.GetSessionLifespans(), mBundle);
return android::OK;
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 0b117a3..bca292d 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -32,10 +32,10 @@
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/HidlSupport.h>
+#include <cutils/properties.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
-#include <cutils/properties.h>
#include <mediadrm/CryptoHal.h>
#include <mediadrm/DrmHal.h>
@@ -57,10 +57,10 @@
namespace {
-template<typename Hal>
-Hal *MakeObject(status_t *pstatus) {
+template <typename Hal>
+Hal* MakeObject(status_t* pstatus) {
status_t err = OK;
- status_t &status = pstatus ? *pstatus : err;
+ status_t& status = pstatus ? *pstatus : err;
auto obj = new Hal();
status = obj->initCheck();
if (status != OK && status != NO_INIT) {
@@ -70,43 +70,44 @@
}
template <typename Hal, typename V, typename M>
-void MakeHidlFactories(const uint8_t uuid[16], V &factories, M& instances) {
+void MakeHidlFactories(const uint8_t uuid[16], V& factories, M& instances) {
sp<HServiceManager> serviceManager = HServiceManager::getService();
if (serviceManager == nullptr) {
LOG2BE("Failed to get service manager");
return;
}
- serviceManager->listManifestByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> ®istered) {
- for (const auto &instance : registered) {
- auto factory = Hal::getService(instance);
- if (factory != nullptr) {
- instances[instance.c_str()] = Hal::descriptor;
- if (!uuid) {
- factories.push_back(factory);
- continue;
+ serviceManager->listManifestByInterface(
+ Hal::descriptor, [&](const hidl_vec<hidl_string>& registered) {
+ for (const auto& instance : registered) {
+ auto factory = Hal::getService(instance);
+ if (factory != nullptr) {
+ instances[instance.c_str()] = Hal::descriptor;
+ if (!uuid) {
+ factories.push_back(factory);
+ continue;
+ }
+ auto supported = factory->isCryptoSchemeSupported(uuid);
+ if (!supported.isOk()) {
+ LOG2BE(uuid, "isCryptoSchemeSupported txn failed: %s",
+ supported.description().c_str());
+ continue;
+ }
+ if (supported) {
+ factories.push_back(factory);
+ }
+ }
}
- auto supported = factory->isCryptoSchemeSupported(uuid);
- if (!supported.isOk()) {
- LOG2BE(uuid, "isCryptoSchemeSupported txn failed: %s",
- supported.description().c_str());
- continue;
- }
- if (supported) {
- factories.push_back(factory);
- }
- }
- }
- });
+ });
}
template <typename Hal, typename V>
-void MakeHidlFactories(const uint8_t uuid[16], V &factories) {
+void MakeHidlFactories(const uint8_t uuid[16], V& factories) {
std::map<std::string, std::string> instances;
MakeHidlFactories<Hal>(uuid, factories, instances);
}
-hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
+hidl_vec<uint8_t> toHidlVec(const void* ptr, size_t size) {
hidl_vec<uint8_t> vec(size);
if (ptr != nullptr) {
memcpy(vec.data(), ptr, size);
@@ -114,19 +115,19 @@
return vec;
}
-hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
+hidl_array<uint8_t, 16> toHidlArray16(const uint8_t* ptr) {
if (ptr == nullptr) {
return hidl_array<uint8_t, 16>();
}
return hidl_array<uint8_t, 16>(ptr);
}
-sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory> &factory,
- const uint8_t uuid[16], const char *appPackageName) {
+sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory>& factory, const uint8_t uuid[16],
+ const char* appPackageName) {
sp<::V1_0::IDrmPlugin> plugin;
auto err = factory->createPlugin(
toHidlArray16(uuid), hidl_string(appPackageName),
- [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
+ [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin>& hPlugin) {
if (status != ::V1_0::Status::OK) {
LOG2BE(uuid, "MakeDrmPlugin failed: %d", status);
return;
@@ -141,13 +142,13 @@
}
}
-sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory> &factory,
- const uint8_t uuid[16], const void *initData,
+sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void* initData,
size_t initDataSize) {
sp<::V1_0::ICryptoPlugin> plugin;
auto err = factory->createPlugin(
toHidlArray16(uuid), toHidlVec(initData, initDataSize),
- [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
+ [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin>& hPlugin) {
if (status != ::V1_0::Status::OK) {
LOG2BE(uuid, "MakeCryptoPlugin failed: %d", status);
return;
@@ -162,17 +163,17 @@
}
}
-} // namespace
+} // namespace
bool UseDrmService() {
return property_get_bool("mediadrm.use_mediadrmserver", true);
}
-sp<IDrm> MakeDrm(status_t *pstatus) {
+sp<IDrm> MakeDrm(status_t* pstatus) {
return MakeObject<DrmHal>(pstatus);
}
-sp<ICrypto> MakeCrypto(status_t *pstatus) {
+sp<ICrypto> MakeCrypto(status_t* pstatus) {
return MakeObject<CryptoHal>(pstatus);
}
@@ -191,9 +192,9 @@
}
std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
- const char *appPackageName) {
+ const char* appPackageName) {
std::vector<sp<::V1_0::IDrmPlugin>> plugins;
- for (const auto &factory : MakeDrmFactories(uuid)) {
+ for (const auto& factory : MakeDrmFactories(uuid)) {
plugins.push_back(MakeDrmPlugin(factory, uuid, appPackageName));
}
return plugins;
@@ -209,10 +210,11 @@
return cryptoFactories;
}
-std::vector<sp<ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16], const void *initData,
- size_t initDataSize) {
- std::vector<sp<ICryptoPlugin>> plugins;
- for (const auto &factory : MakeCryptoFactories(uuid)) {
+std::vector<sp<::V1_0::ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16],
+ const void* initData,
+ size_t initDataSize) {
+ std::vector<sp<::V1_0::ICryptoPlugin>> plugins;
+ for (const auto& factory : MakeCryptoFactories(uuid)) {
plugins.push_back(MakeCryptoPlugin(factory, uuid, initData, initDataSize));
}
return plugins;
@@ -220,90 +222,90 @@
status_t toStatusT_1_4(::V1_4::Status status) {
switch (status) {
- case ::V1_4::Status::OK:
- return OK;
- case ::V1_4::Status::BAD_VALUE:
- return BAD_VALUE;
- case ::V1_4::Status::ERROR_DRM_CANNOT_HANDLE:
- return ERROR_DRM_CANNOT_HANDLE;
- case ::V1_4::Status::ERROR_DRM_DECRYPT:
- return ERROR_DRM_DECRYPT;
- case ::V1_4::Status::ERROR_DRM_DEVICE_REVOKED:
- return ERROR_DRM_DEVICE_REVOKED;
- case ::V1_4::Status::ERROR_DRM_FRAME_TOO_LARGE:
- return ERROR_DRM_FRAME_TOO_LARGE;
- case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
- return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
- case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_SECURITY:
- return ERROR_DRM_INSUFFICIENT_SECURITY;
- case ::V1_4::Status::ERROR_DRM_INVALID_STATE:
- return ERROR_DRM_INVALID_STATE;
- case ::V1_4::Status::ERROR_DRM_LICENSE_EXPIRED:
- return ERROR_DRM_LICENSE_EXPIRED;
- case ::V1_4::Status::ERROR_DRM_NO_LICENSE:
- return ERROR_DRM_NO_LICENSE;
- case ::V1_4::Status::ERROR_DRM_NOT_PROVISIONED:
- return ERROR_DRM_NOT_PROVISIONED;
- case ::V1_4::Status::ERROR_DRM_RESOURCE_BUSY:
- return ERROR_DRM_RESOURCE_BUSY;
- case ::V1_4::Status::ERROR_DRM_RESOURCE_CONTENTION:
- return ERROR_DRM_RESOURCE_CONTENTION;
- case ::V1_4::Status::ERROR_DRM_SESSION_LOST_STATE:
- return ERROR_DRM_SESSION_LOST_STATE;
- case ::V1_4::Status::ERROR_DRM_SESSION_NOT_OPENED:
- return ERROR_DRM_SESSION_NOT_OPENED;
+ case ::V1_4::Status::OK:
+ return OK;
+ case ::V1_4::Status::BAD_VALUE:
+ return BAD_VALUE;
+ case ::V1_4::Status::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ case ::V1_4::Status::ERROR_DRM_DECRYPT:
+ return ERROR_DRM_DECRYPT;
+ case ::V1_4::Status::ERROR_DRM_DEVICE_REVOKED:
+ return ERROR_DRM_DEVICE_REVOKED;
+ case ::V1_4::Status::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ case ::V1_4::Status::ERROR_DRM_INVALID_STATE:
+ return ERROR_DRM_INVALID_STATE;
+ case ::V1_4::Status::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ case ::V1_4::Status::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ case ::V1_4::Status::ERROR_DRM_NOT_PROVISIONED:
+ return ERROR_DRM_NOT_PROVISIONED;
+ case ::V1_4::Status::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ case ::V1_4::Status::ERROR_DRM_RESOURCE_CONTENTION:
+ return ERROR_DRM_RESOURCE_CONTENTION;
+ case ::V1_4::Status::ERROR_DRM_SESSION_LOST_STATE:
+ return ERROR_DRM_SESSION_LOST_STATE;
+ case ::V1_4::Status::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
- // New in S / drm@1.4:
- case ::V1_4::Status::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
- return ERROR_DRM_ZERO_SUBSAMPLES;
- case ::V1_4::Status::CRYPTO_LIBRARY_ERROR:
- return ERROR_DRM_CRYPTO_LIBRARY;
- case ::V1_4::Status::GENERAL_OEM_ERROR:
- return ERROR_DRM_GENERIC_OEM;
- case ::V1_4::Status::GENERAL_PLUGIN_ERROR:
- return ERROR_DRM_GENERIC_PLUGIN;
- case ::V1_4::Status::INIT_DATA_INVALID:
- return ERROR_DRM_INIT_DATA;
- case ::V1_4::Status::KEY_NOT_LOADED:
- return ERROR_DRM_KEY_NOT_LOADED;
- case ::V1_4::Status::LICENSE_PARSE_ERROR:
- return ERROR_DRM_LICENSE_PARSE;
- case ::V1_4::Status::LICENSE_POLICY_ERROR:
- return ERROR_DRM_LICENSE_POLICY;
- case ::V1_4::Status::LICENSE_RELEASE_ERROR:
- return ERROR_DRM_LICENSE_RELEASE;
- case ::V1_4::Status::LICENSE_REQUEST_REJECTED:
- return ERROR_DRM_LICENSE_REQUEST_REJECTED;
- case ::V1_4::Status::LICENSE_RESTORE_ERROR:
- return ERROR_DRM_LICENSE_RESTORE;
- case ::V1_4::Status::LICENSE_STATE_ERROR:
- return ERROR_DRM_LICENSE_STATE;
- case ::V1_4::Status::MALFORMED_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MALFORMED;
- case ::V1_4::Status::MEDIA_FRAMEWORK_ERROR:
- return ERROR_DRM_MEDIA_FRAMEWORK;
- case ::V1_4::Status::MISSING_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MISSING;
- case ::V1_4::Status::PROVISIONING_CERTIFICATE_ERROR:
- return ERROR_DRM_PROVISIONING_CERTIFICATE;
- case ::V1_4::Status::PROVISIONING_CONFIGURATION_ERROR:
- return ERROR_DRM_PROVISIONING_CONFIG;
- case ::V1_4::Status::PROVISIONING_PARSE_ERROR:
- return ERROR_DRM_PROVISIONING_PARSE;
- case ::V1_4::Status::PROVISIONING_REQUEST_REJECTED:
- return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
- case ::V1_4::Status::RETRYABLE_PROVISIONING_ERROR:
- return ERROR_DRM_PROVISIONING_RETRY;
- case ::V1_4::Status::SECURE_STOP_RELEASE_ERROR:
- return ERROR_DRM_SECURE_STOP_RELEASE;
- case ::V1_4::Status::STORAGE_READ_FAILURE:
- return ERROR_DRM_STORAGE_READ;
- case ::V1_4::Status::STORAGE_WRITE_FAILURE:
- return ERROR_DRM_STORAGE_WRITE;
+ // New in S / drm@1.4:
+ case ::V1_4::Status::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ return ERROR_DRM_ZERO_SUBSAMPLES;
+ case ::V1_4::Status::CRYPTO_LIBRARY_ERROR:
+ return ERROR_DRM_CRYPTO_LIBRARY;
+ case ::V1_4::Status::GENERAL_OEM_ERROR:
+ return ERROR_DRM_GENERIC_OEM;
+ case ::V1_4::Status::GENERAL_PLUGIN_ERROR:
+ return ERROR_DRM_GENERIC_PLUGIN;
+ case ::V1_4::Status::INIT_DATA_INVALID:
+ return ERROR_DRM_INIT_DATA;
+ case ::V1_4::Status::KEY_NOT_LOADED:
+ return ERROR_DRM_KEY_NOT_LOADED;
+ case ::V1_4::Status::LICENSE_PARSE_ERROR:
+ return ERROR_DRM_LICENSE_PARSE;
+ case ::V1_4::Status::LICENSE_POLICY_ERROR:
+ return ERROR_DRM_LICENSE_POLICY;
+ case ::V1_4::Status::LICENSE_RELEASE_ERROR:
+ return ERROR_DRM_LICENSE_RELEASE;
+ case ::V1_4::Status::LICENSE_REQUEST_REJECTED:
+ return ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ case ::V1_4::Status::LICENSE_RESTORE_ERROR:
+ return ERROR_DRM_LICENSE_RESTORE;
+ case ::V1_4::Status::LICENSE_STATE_ERROR:
+ return ERROR_DRM_LICENSE_STATE;
+ case ::V1_4::Status::MALFORMED_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MALFORMED;
+ case ::V1_4::Status::MEDIA_FRAMEWORK_ERROR:
+ return ERROR_DRM_MEDIA_FRAMEWORK;
+ case ::V1_4::Status::MISSING_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MISSING;
+ case ::V1_4::Status::PROVISIONING_CERTIFICATE_ERROR:
+ return ERROR_DRM_PROVISIONING_CERTIFICATE;
+ case ::V1_4::Status::PROVISIONING_CONFIGURATION_ERROR:
+ return ERROR_DRM_PROVISIONING_CONFIG;
+ case ::V1_4::Status::PROVISIONING_PARSE_ERROR:
+ return ERROR_DRM_PROVISIONING_PARSE;
+ case ::V1_4::Status::PROVISIONING_REQUEST_REJECTED:
+ return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+ case ::V1_4::Status::RETRYABLE_PROVISIONING_ERROR:
+ return ERROR_DRM_PROVISIONING_RETRY;
+ case ::V1_4::Status::SECURE_STOP_RELEASE_ERROR:
+ return ERROR_DRM_SECURE_STOP_RELEASE;
+ case ::V1_4::Status::STORAGE_READ_FAILURE:
+ return ERROR_DRM_STORAGE_READ;
+ case ::V1_4::Status::STORAGE_WRITE_FAILURE:
+ return ERROR_DRM_STORAGE_WRITE;
- case ::V1_4::Status::ERROR_DRM_UNKNOWN:
- default:
- return ERROR_DRM_UNKNOWN;
+ case ::V1_4::Status::ERROR_DRM_UNKNOWN:
+ default:
+ return ERROR_DRM_UNKNOWN;
}
return ERROR_DRM_UNKNOWN;
}
@@ -312,20 +314,34 @@
char logPriorityToChar(::V1_4::LogPriority priority) {
char p = 'U';
switch (priority) {
- case ::V1_4::LogPriority::VERBOSE: p = 'V'; break;
- case ::V1_4::LogPriority::DEBUG: p = 'D'; break;
- case ::V1_4::LogPriority::INFO: p = 'I'; break;
- case ::V1_4::LogPriority::WARN: p = 'W'; break;
- case ::V1_4::LogPriority::ERROR: p = 'E'; break;
- case ::V1_4::LogPriority::FATAL: p = 'F'; break;
- default: p = 'U'; break;
+ case ::V1_4::LogPriority::VERBOSE:
+ p = 'V';
+ break;
+ case ::V1_4::LogPriority::DEBUG:
+ p = 'D';
+ break;
+ case ::V1_4::LogPriority::INFO:
+ p = 'I';
+ break;
+ case ::V1_4::LogPriority::WARN:
+ p = 'W';
+ break;
+ case ::V1_4::LogPriority::ERROR:
+ p = 'E';
+ break;
+ case ::V1_4::LogPriority::FATAL:
+ p = 'F';
+ break;
+ default:
+ p = 'U';
+ break;
}
return p;
}
} // namespace
-std::string GetExceptionMessage(status_t err, const char *msg,
- const Vector<::V1_4::LogMessage> &logs) {
+std::string GetExceptionMessage(status_t err, const char* msg,
+ const Vector<::V1_4::LogMessage>& logs) {
std::string ruler("==============================");
std::string header("Beginning of DRM Plugin Log");
std::string footer("End of DRM Plugin Log");
@@ -355,7 +371,7 @@
return msg8.c_str();
}
-void LogBuffer::addLog(const ::V1_4::LogMessage &log) {
+void LogBuffer::addLog(const ::V1_4::LogMessage& log) {
std::unique_lock<std::mutex> lock(mMutex);
mBuffer.push_back(log);
while (mBuffer.size() > MAX_CAPACITY) {
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index 49bbad4..a85e3cf 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -36,6 +36,7 @@
"libmediadrm",
"liblog",
"resourcemanager_aidl_interface-ndk",
+ "libaidlcommonsupport",
],
header_libs: [
"libmedia_headers",
@@ -59,6 +60,7 @@
"android.hardware.drm@1.4",
"libhidlallocatorutils",
"libhidlbase",
+ "android.hardware.drm-V1-ndk",
],
fuzz_config: {
cc: [
diff --git a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
index 8df0477..eabd41f 100644
--- a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
+++ b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
@@ -24,6 +24,8 @@
#include <mediadrm/DrmHal.h>
#include <utils/String8.h>
#include "fuzzer/FuzzedDataProvider.h"
+#include <binder/PersistableBundle.h>
+#include <android/hardware/drm/1.0/types.h>
#define AES_BLOCK_SIZE 16
#define UNUSED_PARAM __attribute__((unused))
@@ -33,6 +35,7 @@
using android::hardware::fromHeap;
using ::android::os::PersistableBundle;
using drm::V1_0::BufferType;
+using ::android::hardware::drm::V1_0::DestinationBuffer;
enum {
INVALID_UUID = 0,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 5fd39e6..5be59f0 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -15,25 +15,12 @@
*/
#ifndef CRYPTO_HAL_H_
-
#define CRYPTO_HAL_H_
-#include <android/hardware/drm/1.0/ICryptoFactory.h>
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.1/ICryptoFactory.h>
-#include <android/hardware/drm/1.2/ICryptoPlugin.h>
-#include <android/hardware/drm/1.4/ICryptoPlugin.h>
-
#include <mediadrm/ICrypto.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::ICryptoFactory;
-using drm::V1_0::ICryptoPlugin;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::DestinationBuffer;
-
using ::android::hardware::HidlMemory;
class IMemoryHeap;
@@ -43,67 +30,30 @@
struct CryptoHal : public ICrypto {
CryptoHal();
virtual ~CryptoHal();
-
virtual status_t initCheck() const;
-
virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
-
virtual status_t createPlugin(
const uint8_t uuid[16], const void *data, size_t size);
-
virtual status_t destroyPlugin();
-
virtual bool requiresSecureDecoderComponent(
const char *mime) const;
-
virtual void notifyResolution(uint32_t width, uint32_t height);
-
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
-
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const ::SharedBuffer &source, size_t offset,
+ const drm::V1_0::SharedBuffer &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const ::DestinationBuffer &destination,
+ const drm::V1_0::DestinationBuffer &destination,
AString *errorDetailMsg);
-
- virtual int32_t setHeap(const sp<HidlMemory>& heap) {
- return setHeapBase(heap);
- }
- virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
-
+ virtual int32_t setHeap(const sp<HidlMemory>& heap);
+ virtual void unsetHeap(int32_t seqNum);
virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
-
private:
- mutable Mutex mLock;
-
- const Vector<sp<ICryptoFactory>> mFactories;
- sp<ICryptoPlugin> mPlugin;
- sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
-
- /**
- * mInitCheck is:
- * NO_INIT if a plugin hasn't been created yet
- * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
- * OK after a plugin has been created and mPlugin is valid
- */
- status_t mInitCheck;
-
- KeyedVector<int32_t, size_t> mHeapSizes;
- int32_t mHeapSeqNum;
-
- Vector<sp<ICryptoFactory>> makeCryptoFactories();
- sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
- const uint8_t uuid[16], const void *initData, size_t size);
-
- int32_t setHeapBase(const sp<HidlMemory>& heap);
- void clearHeapBase(int32_t seqNum);
-
- status_t checkSharedBuffer(const ::SharedBuffer& buffer);
-
+ sp<ICrypto> mCryptoHalHidl;
+ sp<ICrypto> mCryptoHalAidl;
DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
};
-} // namespace android
+}
-#endif // CRYPTO_HAL_H_
+#endif
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
new file mode 100644
index 0000000..a25b091
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#ifndef CRYPTO_HAL_AIDL_H_
+#define CRYPTO_HAL_AIDL_H_
+
+#include <aidl/android/hardware/drm/ICryptoFactory.h>
+#include <aidl/android/hardware/drm/ICryptoPlugin.h>
+
+#include <mediadrm/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+using ICryptoFactoryAidl = ::aidl::android::hardware::drm::ICryptoFactory;
+using ICryptoPluginAidl = ::aidl::android::hardware::drm::ICryptoPlugin;
+using ::aidl::android::hardware::drm::Uuid;
+
+// -------Hidl interface related-----------------
+// TODO: replace before removing hidl interface
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::SharedBuffer;
+
+using ::android::hardware::HidlMemory;
+
+// -------Hidl interface related end-------------
+
+class IMemoryHeap;
+
+namespace android {
+
+struct CryptoHalAidl : public ICrypto {
+ CryptoHalAidl();
+ virtual ~CryptoHalAidl();
+ virtual status_t initCheck() const;
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+ virtual status_t createPlugin(const uint8_t uuid[16], const void* data, size_t size);
+ virtual status_t destroyPlugin();
+ virtual bool requiresSecureDecoderComponent(const char* mime) const;
+ virtual void notifyResolution(uint32_t width, uint32_t height);
+ virtual status_t setMediaDrmSession(const Vector<uint8_t>& sessionId);
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
+ const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
+ size_t offset, const CryptoPlugin::SubSample* subSamples,
+ size_t numSubSamples, const ::DestinationBuffer& destination,
+ AString* errorDetailMsg);
+ virtual int32_t setHeap(const sp<HidlMemory>& heap);
+ virtual void unsetHeap(int32_t seqNum);
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+
+ private:
+ mutable Mutex mLock;
+
+ const std::vector<std::shared_ptr<ICryptoFactoryAidl>> mFactories;
+ std::shared_ptr<ICryptoPluginAidl> mPlugin;
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ KeyedVector<int32_t, size_t> mHeapSizes;
+ int32_t mHeapSeqNum;
+
+ std::vector<std::shared_ptr<ICryptoFactoryAidl>> makeCryptoFactories();
+ std::shared_ptr<ICryptoPluginAidl> makeCryptoPlugin(
+ const std::shared_ptr<ICryptoFactoryAidl>& factory, const Uuid& uuidAidl,
+ const std::vector<uint8_t> initData);
+
+ status_t checkSharedBuffer(const ::SharedBuffer& buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(CryptoHalAidl);
+};
+
+} // namespace android
+
+#endif // CRYPTO_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
new file mode 100644
index 0000000..6db1e89
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#ifndef CRYPTO_HAL_HIDL_H_
+#define CRYPTO_HAL_HIDL_H_
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
+#include <android/hardware/drm/1.4/ICryptoPlugin.h>
+
+#include <mediadrm/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::ICryptoFactory;
+using drm::V1_0::ICryptoPlugin;
+using drm::V1_0::SharedBuffer;
+using drm::V1_0::DestinationBuffer;
+
+using ::android::hardware::HidlMemory;
+
+class IMemoryHeap;
+
+namespace android {
+
+struct CryptoHalHidl : public ICrypto {
+ CryptoHalHidl();
+ virtual ~CryptoHalHidl();
+
+ virtual status_t initCheck() const;
+
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+
+ virtual status_t createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size);
+
+ virtual status_t destroyPlugin();
+
+ virtual bool requiresSecureDecoderComponent(
+ const char *mime) const;
+
+ virtual void notifyResolution(uint32_t width, uint32_t height);
+
+ virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const ::SharedBuffer &source, size_t offset,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ const ::DestinationBuffer &destination,
+ AString *errorDetailMsg);
+
+ virtual int32_t setHeap(const sp<HidlMemory>& heap) {
+ return setHeapBase(heap);
+ }
+ virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
+
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+
+private:
+ mutable Mutex mLock;
+
+ const Vector<sp<ICryptoFactory>> mFactories;
+ sp<ICryptoPlugin> mPlugin;
+ sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ KeyedVector<int32_t, size_t> mHeapSizes;
+ int32_t mHeapSeqNum;
+
+ Vector<sp<ICryptoFactory>> makeCryptoFactories();
+ sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void *initData, size_t size);
+
+ int32_t setHeapBase(const sp<HidlMemory>& heap);
+ void clearHeapBase(int32_t seqNum);
+
+ status_t checkSharedBuffer(const ::SharedBuffer& buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(CryptoHalHidl);
+};
+
+} // namespace android
+
+#endif // CRYPTO_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index 7eb1dec..bb58585 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -14,77 +14,27 @@
* limitations under the License.
*/
-#ifndef DRM_HAL_H_
-
-#define DRM_HAL_H_
-
-#include <android/hardware/drm/1.0/IDrmFactory.h>
-#include <android/hardware/drm/1.0/IDrmPlugin.h>
-#include <android/hardware/drm/1.1/IDrmFactory.h>
-#include <android/hardware/drm/1.1/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmFactory.h>
-#include <android/hardware/drm/1.2/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmPluginListener.h>
-#include <android/hardware/drm/1.4/IDrmPlugin.h>
-#include <android/hardware/drm/1.4/types.h>
-
-#include <media/drm/DrmAPI.h>
-#include <mediadrm/DrmMetrics.h>
-#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/IDrm.h>
-#include <mediadrm/IDrmClient.h>
-#include <mediadrm/IDrmMetricsConsumer.h>
-#include <utils/threads.h>
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::EventType;
-using drm::V1_0::IDrmFactory;
-using drm::V1_0::IDrmPlugin;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeyStatus;
-using drm::V1_2::OfflineLicenseState;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
-typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
+#ifndef DRM_HAL_H_
+#define DRM_HAL_H_
namespace android {
-struct DrmSessionClientInterface;
-
-inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
- if (l.size() != r.size()) return false;
- return memcmp(l.array(), r.array(), l.size()) == 0;
-}
-
-struct DrmHal : public IDrm,
- public IDrmPluginListener_V1_2 {
-
- struct DrmSessionClient;
-
+struct DrmHal : public IDrm {
DrmHal();
virtual ~DrmHal();
-
virtual status_t initCheck() const;
-
virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8& mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported);
-
+ const String8 &mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *result);
virtual status_t createPlugin(const uint8_t uuid[16],
const String8 &appPackageName);
-
virtual status_t destroyPlugin();
-
- virtual status_t openSession(DrmPlugin::SecurityLevel level,
+ virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t> &sessionId);
-
virtual status_t closeSession(Vector<uint8_t> const &sessionId);
-
virtual status_t
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
@@ -92,168 +42,88 @@
KeyedVector<String8, String8> const &optionalParameters,
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType);
-
virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &response,
Vector<uint8_t> &keySetId);
-
virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
-
virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keySetId);
-
virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
KeyedVector<String8, String8> &infoMap) const;
-
virtual status_t getProvisionRequest(String8 const &certType,
String8 const &certAuthority,
Vector<uint8_t> &request,
- String8 &defaulUrl);
-
+ String8 &defaultUrl);
virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey);
-
virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
-
virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
virtual status_t removeAllSecureStops();
-
virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel) const;
virtual status_t getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const;
virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const;
-
virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const;
-
- virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+ virtual status_t getPropertyString(String8 const &name, String8 &value) const;
virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value ) const;
- virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
+ Vector<uint8_t> &value) const;
+ virtual status_t setPropertyString(String8 const &name,
+ String8 const &value ) const;
virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const;
+ Vector<uint8_t> const &value) const;
virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
-
virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
String8 const &algorithm);
-
virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
String8 const &algorithm);
-
virtual status_t encrypt(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &input,
Vector<uint8_t> const &iv,
Vector<uint8_t> &output);
-
virtual status_t decrypt(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &input,
Vector<uint8_t> const &iv,
Vector<uint8_t> &output);
-
virtual status_t sign(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &message,
Vector<uint8_t> &signature);
-
virtual status_t verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &message,
Vector<uint8_t> const &signature,
bool &match);
-
virtual status_t signRSA(Vector<uint8_t> const &sessionId,
String8 const &algorithm,
Vector<uint8_t> const &message,
Vector<uint8_t> const &wrappedKey,
Vector<uint8_t> &signature);
-
virtual status_t setListener(const sp<IDrmClient>& listener);
-
virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
-
virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
bool *required) const;
-
virtual status_t setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId);
-
virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
- // Methods of IDrmPluginListener
- Return<void> sendEvent(EventType eventType,
- const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
-
- Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
- int64_t expiryTimeInMS);
-
- Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
-
- Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
-
- Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
-
private:
- static Mutex mLock;
-
- sp<IDrmClient> mListener;
- mutable Mutex mEventLock;
- mutable Mutex mNotifyLock;
-
- const std::vector<sp<IDrmFactory>> mFactories;
- sp<IDrmPlugin> mPlugin;
- sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
- sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
- sp<drm::V1_4::IDrmPlugin> mPluginV1_4;
- String8 mAppPackageName;
-
- // Mutable to allow modification within GetPropertyByteArray.
- mutable MediaDrmMetrics mMetrics;
-
- std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
- void closeOpenSessions();
- void cleanup();
-
- /**
- * mInitCheck is:
- * NO_INIT if a plugin hasn't been created yet
- * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
- * OK after a plugin has been created and mPlugin is valid
- */
- status_t mInitCheck;
-
- std::vector<sp<IDrmFactory>> makeDrmFactories();
- sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
- const uint8_t uuid[16], const String8& appPackageName);
-
- void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
-
- std::string reportPluginMetrics() const;
- std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
- status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
- status_t getPropertyByteArrayInternal(String8 const &name,
- Vector<uint8_t> &value) const;
- status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
- const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported);
-
+ sp<IDrm> mDrmHalHidl;
+ std::shared_ptr<IDrm> mDrmHalAidl;
DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
};
-} // namespace android
+} // namespace android
-#endif // DRM_HAL_H_
+#endif
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
new file mode 100644
index 0000000..6720734
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+#ifndef DRM_HAL_AIDL_H_
+#define DRM_HAL_AIDL_H_
+
+#include <aidl/android/hardware/drm/BnDrmPluginListener.h>
+#include <aidl/android/hardware/drm/IDrmFactory.h>
+#include <aidl/android/hardware/drm/IDrmPlugin.h>
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <mediadrm/DrmMetrics.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrm.h>
+#include <memory>
+
+using ::aidl::android::hardware::drm::BnDrmPluginListener;
+using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
+using IDrmFactoryAidl = ::aidl::android::hardware::drm::IDrmFactory;
+using EventTypeAidl = ::aidl::android::hardware::drm::EventType;
+using KeyStatusAidl = ::aidl::android::hardware::drm::KeyStatus;
+using ::aidl::android::hardware::drm::Uuid;
+
+namespace android {
+struct DrmHalAidl : public IDrm,
+ public BnDrmPluginListener,
+ std::enable_shared_from_this<BnDrmPluginListener> {
+ struct DrmSessionClient;
+ DrmHalAidl();
+ virtual ~DrmHalAidl();
+ virtual status_t initCheck() const;
+ virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual status_t createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+ virtual status_t destroyPlugin();
+ virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+ Vector<uint8_t>& sessionId);
+ virtual status_t closeSession(Vector<uint8_t> const& sessionId);
+ virtual status_t getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType);
+ virtual status_t provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response, Vector<uint8_t>& keySetId);
+ virtual status_t removeKeys(Vector<uint8_t> const& keySetId);
+ virtual status_t restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId);
+ virtual status_t queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const;
+ virtual status_t getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl);
+ virtual status_t provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey);
+ virtual status_t getSecureStops(List<Vector<uint8_t>>& secureStops);
+ virtual status_t getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+ virtual status_t getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+ virtual status_t releaseSecureStops(Vector<uint8_t> const& ssRelease);
+ virtual status_t removeSecureStop(Vector<uint8_t> const& ssid);
+ virtual status_t removeAllSecureStops();
+ virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const;
+ virtual status_t getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+ virtual status_t getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const;
+ virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+ virtual status_t removeOfflineLicense(Vector<uint8_t> const& keySetId);
+ virtual status_t getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const;
+ virtual status_t getPropertyString(String8 const& name, String8& value) const;
+ virtual status_t getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+ virtual status_t setPropertyString(String8 const& name, String8 const& value) const;
+ virtual status_t setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+ virtual status_t getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+ virtual status_t setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+ virtual status_t setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+ virtual status_t encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual status_t decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual status_t sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+ virtual status_t verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match);
+ virtual status_t signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature);
+ virtual status_t setListener(const sp<IDrmClient>& listener);
+ virtual status_t requiresSecureDecoder(const char* mime, bool* required) const;
+ virtual status_t requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const;
+ virtual status_t setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+ // Methods of IDrmPluginListenerAidl
+ ::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
+ const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_data);
+ ::ndk::ScopedAStatus onExpirationUpdate(const std::vector<uint8_t>& in_sessionId,
+ int64_t in_expiryTimeInMS);
+ ::ndk::ScopedAStatus onKeysChange(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<KeyStatusAidl>& in_keyStatusList,
+ bool in_hasNewUsableKey);
+ ::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
+
+ private:
+ static Mutex mLock;
+ sp<IDrmClient> mListener;
+ mutable Mutex mEventLock;
+ mutable Mutex mNotifyLock;
+ const std::vector<std::shared_ptr<IDrmFactoryAidl>> mFactories;
+ std::shared_ptr<IDrmPluginAidl> mPlugin;
+ std::vector<std::shared_ptr<IDrmFactoryAidl>> makeDrmFactories();
+ status_t mInitCheck;
+ mutable MediaDrmMetrics mMetrics;
+ std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
+ void cleanup();
+ void closeOpenSessions();
+ std::string reportPluginMetrics() const;
+ std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
+ status_t getPropertyStringInternal(String8 const& name, String8& value) const;
+ status_t getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
+ DISALLOW_EVIL_CONSTRUCTORS(DrmHalAidl);
+};
+
+} // namespace android
+
+#endif
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
new file mode 100644
index 0000000..91dc700
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
@@ -0,0 +1,258 @@
+/*
+ * 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.
+ */
+
+#ifndef DRM_HAL_HIDL_H_
+#define DRM_HAL_HIDL_H_
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
+#include <android/hardware/drm/1.4/IDrmPlugin.h>
+#include <android/hardware/drm/1.4/types.h>
+
+#include <media/drm/DrmAPI.h>
+#include <mediadrm/DrmMetrics.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/threads.h>
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::EventType;
+using drm::V1_0::IDrmFactory;
+using drm::V1_0::IDrmPlugin;
+using drm::V1_0::IDrmPluginListener;
+using drm::V1_1::SecurityLevel;
+using drm::V1_2::KeyStatus;
+using drm::V1_2::OfflineLicenseState;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
+
+namespace android {
+
+struct DrmSessionClientInterface;
+
+inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
+ if (l.size() != r.size()) return false;
+ return memcmp(l.array(), r.array(), l.size()) == 0;
+}
+
+struct DrmHalHidl : public IDrm,
+ public IDrmPluginListener_V1_2 {
+
+ struct DrmSessionClient;
+
+ DrmHalHidl();
+ virtual ~DrmHalHidl();
+
+ virtual status_t initCheck() const;
+
+ virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
+ const String8& mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool *isSupported);
+
+ virtual status_t createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
+
+ virtual status_t destroyPlugin();
+
+ virtual status_t openSession(DrmPlugin::SecurityLevel level,
+ Vector<uint8_t> &sessionId);
+
+ virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+
+ virtual status_t
+ getKeyRequest(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &initData,
+ String8 const &mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const &optionalParameters,
+ Vector<uint8_t> &request, String8 &defaultUrl,
+ DrmPlugin::KeyRequestType *keyRequestType);
+
+ virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
+
+ virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+
+ virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
+
+ virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
+
+ virtual status_t getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl);
+
+ virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
+
+ virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
+ virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+ virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+
+ virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
+ virtual status_t removeAllSecureStops();
+
+ virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ DrmPlugin::HdcpLevel *maxLevel) const;
+ virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ uint32_t *maxSessions) const;
+ virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ DrmPlugin::SecurityLevel *level) const;
+
+ virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+ virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
+ virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ DrmPlugin::OfflineLicenseState *licenseState) const;
+
+ virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+ virtual status_t getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value ) const;
+ virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
+ virtual status_t setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const;
+ virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+
+ virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+
+ virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+
+ virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual status_t sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+
+ virtual status_t verify(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &signature,
+ bool &match);
+
+ virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
+
+ virtual status_t setListener(const sp<IDrmClient>& listener);
+
+ virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
+
+ virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
+
+ virtual status_t setPlaybackId(
+ Vector<uint8_t> const &sessionId,
+ const char *playbackId);
+
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+
+ // Methods of IDrmPluginListener
+ Return<void> sendEvent(EventType eventType,
+ const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
+
+ Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+ int64_t expiryTimeInMS);
+
+ Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
+
+ Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
+
+ Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
+
+private:
+ static Mutex mLock;
+
+ sp<IDrmClient> mListener;
+ mutable Mutex mEventLock;
+ mutable Mutex mNotifyLock;
+
+ const std::vector<sp<IDrmFactory>> mFactories;
+ sp<IDrmPlugin> mPlugin;
+ sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
+ sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
+ sp<drm::V1_4::IDrmPlugin> mPluginV1_4;
+ String8 mAppPackageName;
+
+ // Mutable to allow modification within GetPropertyByteArray.
+ mutable MediaDrmMetrics mMetrics;
+
+ std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
+ void closeOpenSessions();
+ void cleanup();
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ std::vector<sp<IDrmFactory>> makeDrmFactories();
+ sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& appPackageName);
+
+ void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
+
+ std::string reportPluginMetrics() const;
+ std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
+ status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
+ status_t getPropertyByteArrayInternal(String8 const &name,
+ Vector<uint8_t> &value) const;
+ status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
+ const uint8_t uuid[16],
+ const String8 &mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool *isSupported);
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmHalHidl);
+};
+
+} // namespace android
+
+#endif // DRM_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetrics.h b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
index 100b8f7..e1775c7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetrics.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
@@ -50,12 +50,10 @@
CounterMetric<status_t> mGetProvisionRequestCounter;
// Count of provideProvisionResponse calls.
CounterMetric<status_t> mProvideProvisionResponseCounter;
-
// Count of key status events broken out by status type.
- CounterMetric<::android::hardware::drm::V1_2::KeyStatusType>
- mKeyStatusChangeCounter;
+ CounterMetric<uint32_t> mKeyStatusChangeCounter;
// Count of events broken out by event type
- CounterMetric<::android::hardware::drm::V1_0::EventType> mEventCounter;
+ CounterMetric<uint32_t> mEventCounter;
// Count getPropertyByteArray calls to retrieve the device unique id.
CounterMetric<status_t> mGetDeviceUniqueIdCounter;
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index ec0b878..5679cfd 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -38,12 +38,18 @@
#include <mutex>
#include <string>
#include <vector>
+#include <aidl/android/hardware/drm/LogMessage.h>
+#include <aidl/android/hardware/drm/Status.h>
using namespace ::android::hardware::drm;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
+using ::aidl::android::hardware::drm::LogPriority;
+using ::aidl::android::hardware::drm::LogMessage;
+using StatusAidl = ::aidl::android::hardware::drm::Status;
+
namespace android {
struct ICrypto;
@@ -180,6 +186,136 @@
return toStatusT_1_4(err);
}
+inline status_t toStatusTAidl(int32_t serviceError) {
+ auto status = static_cast<StatusAidl>(serviceError);
+ switch (status) {
+ case StatusAidl::OK:
+ return OK;
+ case StatusAidl::BAD_VALUE:
+ return BAD_VALUE;
+ case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ case StatusAidl::ERROR_DRM_DECRYPT:
+ return ERROR_DRM_DECRYPT;
+ case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
+ return ERROR_DRM_DEVICE_REVOKED;
+ case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ case StatusAidl::ERROR_DRM_INVALID_STATE:
+ return ERROR_DRM_INVALID_STATE;
+ case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ case StatusAidl::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
+ return ERROR_DRM_NOT_PROVISIONED;
+ case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
+ return ERROR_DRM_RESOURCE_CONTENTION;
+ case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
+ return ERROR_DRM_SESSION_LOST_STATE;
+ case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
+
+ // New in S / drm@1.4:
+ case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ return ERROR_DRM_ZERO_SUBSAMPLES;
+ case StatusAidl::CRYPTO_LIBRARY_ERROR:
+ return ERROR_DRM_CRYPTO_LIBRARY;
+ case StatusAidl::GENERAL_OEM_ERROR:
+ return ERROR_DRM_GENERIC_OEM;
+ case StatusAidl::GENERAL_PLUGIN_ERROR:
+ return ERROR_DRM_GENERIC_PLUGIN;
+ case StatusAidl::INIT_DATA_INVALID:
+ return ERROR_DRM_INIT_DATA;
+ case StatusAidl::KEY_NOT_LOADED:
+ return ERROR_DRM_KEY_NOT_LOADED;
+ case StatusAidl::LICENSE_PARSE_ERROR:
+ return ERROR_DRM_LICENSE_PARSE;
+ case StatusAidl::LICENSE_POLICY_ERROR:
+ return ERROR_DRM_LICENSE_POLICY;
+ case StatusAidl::LICENSE_RELEASE_ERROR:
+ return ERROR_DRM_LICENSE_RELEASE;
+ case StatusAidl::LICENSE_REQUEST_REJECTED:
+ return ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ case StatusAidl::LICENSE_RESTORE_ERROR:
+ return ERROR_DRM_LICENSE_RESTORE;
+ case StatusAidl::LICENSE_STATE_ERROR:
+ return ERROR_DRM_LICENSE_STATE;
+ case StatusAidl::MALFORMED_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MALFORMED;
+ case StatusAidl::MEDIA_FRAMEWORK_ERROR:
+ return ERROR_DRM_MEDIA_FRAMEWORK;
+ case StatusAidl::MISSING_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MISSING;
+ case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
+ return ERROR_DRM_PROVISIONING_CERTIFICATE;
+ case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
+ return ERROR_DRM_PROVISIONING_CONFIG;
+ case StatusAidl::PROVISIONING_PARSE_ERROR:
+ return ERROR_DRM_PROVISIONING_PARSE;
+ case StatusAidl::PROVISIONING_REQUEST_REJECTED:
+ return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+ case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
+ return ERROR_DRM_PROVISIONING_RETRY;
+ case StatusAidl::SECURE_STOP_RELEASE_ERROR:
+ return ERROR_DRM_SECURE_STOP_RELEASE;
+ case StatusAidl::STORAGE_READ_FAILURE:
+ return ERROR_DRM_STORAGE_READ;
+ case StatusAidl::STORAGE_WRITE_FAILURE:
+ return ERROR_DRM_STORAGE_WRITE;
+
+ case StatusAidl::ERROR_DRM_UNKNOWN:
+ default:
+ return ERROR_DRM_UNKNOWN;
+ }
+ return ERROR_DRM_UNKNOWN;
+}
+
+template<typename T, typename U>
+status_t GetLogMessagesAidl(const std::shared_ptr<U> &obj, Vector<::V1_4::LogMessage> &logs) {
+ std::shared_ptr<T> plugin = obj;
+ if (obj == NULL) {
+ LOG2BW("%s obj is null", U::descriptor);
+ } else if (plugin == NULL) {
+ LOG2BW("Cannot cast %s obj to %s plugin", U::descriptor, T::descriptor);
+ }
+
+ std::vector<LogMessage> pluginLogsAidl;
+ if (plugin != NULL) {
+ if(!plugin->getLogMessages(&pluginLogsAidl).isOk()) {
+ LOG2BW("%s::getLogMessages remote call failed", T::descriptor);
+ }
+ }
+
+ std::vector<::V1_4::LogMessage> pluginLogs;
+ for (LogMessage log : pluginLogsAidl) {
+ ::V1_4::LogMessage logHidl;
+ logHidl.timeMs = log.timeMs;
+ // skip negative convert check as count of enum elements is 7
+ logHidl.priority = static_cast<::V1_4::LogPriority>((int32_t)log.priority);
+ logHidl.message = log.message;
+ pluginLogs.push_back(logHidl);
+ }
+
+ auto allLogs(gLogBuf.getLogs());
+ LOG2BD("framework logs size %zu; plugin logs size %zu",
+ allLogs.size(), pluginLogs.size());
+ std::copy(pluginLogs.begin(), pluginLogs.end(), std::back_inserter(allLogs));
+ std::sort(allLogs.begin(), allLogs.end(),
+ [](const ::V1_4::LogMessage &a, const ::V1_4::LogMessage &b) {
+ return a.timeMs < b.timeMs;
+ });
+
+ logs.appendVector(allLogs);
+ return OK;
+}
+
template<typename T, typename U>
status_t GetLogMessages(const sp<U> &obj, Vector<::V1_4::LogMessage> &logs) {
sp<T> plugin = T::castFrom(obj);
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index f362d60..237a88b 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -83,8 +83,8 @@
metrics.mProvideProvisionResponseCounter.Increment(OK);
metrics.mGetDeviceUniqueIdCounter.Increment(OK);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
- metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
+ metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
PersistableBundle bundle;
DrmMetricsConsumer consumer(&bundle);
@@ -151,16 +151,16 @@
metrics.mGetDeviceUniqueIdCounter.Increment(OK);
metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::EXPIRED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::OUTPUTNOTALLOWED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::STATUSPENDING);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::INTERNALERROR);
- metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
- metrics.mEventCounter.Increment(EventType::KEY_NEEDED);
- metrics.mEventCounter.Increment(EventType::KEY_EXPIRED);
- metrics.mEventCounter.Increment(EventType::VENDOR_DEFINED);
- metrics.mEventCounter.Increment(EventType::SESSION_RECLAIMED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::EXPIRED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::OUTPUTNOTALLOWED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::STATUSPENDING);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::INTERNALERROR);
+ metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_NEEDED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_EXPIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::VENDOR_DEFINED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::SESSION_RECLAIMED);
android::Vector<uint8_t> sessionId1;
sessionId1.push_back(1);
@@ -284,16 +284,16 @@
metrics.mGetDeviceUniqueIdCounter.Increment(OK);
metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::EXPIRED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::OUTPUTNOTALLOWED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::STATUSPENDING);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::INTERNALERROR);
- metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
- metrics.mEventCounter.Increment(EventType::KEY_NEEDED);
- metrics.mEventCounter.Increment(EventType::KEY_EXPIRED);
- metrics.mEventCounter.Increment(EventType::VENDOR_DEFINED);
- metrics.mEventCounter.Increment(EventType::SESSION_RECLAIMED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::EXPIRED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::OUTPUTNOTALLOWED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::STATUSPENDING);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::INTERNALERROR);
+ metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_NEEDED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_EXPIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::VENDOR_DEFINED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::SESSION_RECLAIMED);
std::string serializedMetrics;
ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
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 4b96956..70e742c 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,
@@ -683,6 +687,9 @@
LEVEL_DV_MAIN_UHD_30, ///< Dolby Vision main tier uhd30
LEVEL_DV_MAIN_UHD_48, ///< Dolby Vision main tier uhd48
LEVEL_DV_MAIN_UHD_60, ///< Dolby Vision main tier uhd60
+ LEVEL_DV_MAIN_UHD_120, ///< Dolby Vision main tier uhd120
+ LEVEL_DV_MAIN_8K_30, ///< Dolby Vision main tier 8k30
+ LEVEL_DV_MAIN_8K_60, ///< Dolby Vision main tier 8k60
LEVEL_DV_HIGH_HD_24 = _C2_PL_DV_BASE + 0x100, ///< Dolby Vision high tier hd24
LEVEL_DV_HIGH_HD_30, ///< Dolby Vision high tier hd30
@@ -693,6 +700,9 @@
LEVEL_DV_HIGH_UHD_30, ///< Dolby Vision high tier uhd30
LEVEL_DV_HIGH_UHD_48, ///< Dolby Vision high tier uhd48
LEVEL_DV_HIGH_UHD_60, ///< Dolby Vision high tier uhd60
+ LEVEL_DV_HIGH_UHD_120, ///< Dolby Vision high tier uhd120
+ LEVEL_DV_HIGH_8K_30, ///< Dolby Vision high tier 8k30
+ LEVEL_DV_HIGH_8K_60, ///< Dolby Vision high tier 8k60
// AV1 levels
LEVEL_AV1_2 = _C2_PL_AV1_BASE , ///< AV1 Level 2
@@ -1605,16 +1615,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 ----------------------------------- */
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 1f8b33d..5df28f0 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1018,29 +1018,31 @@
} else {
pixelFormatInfo = nullptr;
}
- std::optional<uint32_t> flexPixelFormat{};
- std::optional<uint32_t> flexPlanarPixelFormat{};
- std::optional<uint32_t> flexSemiPlanarPixelFormat{};
+ // bit depth -> format
+ std::map<uint32_t, uint32_t> flexPixelFormat;
+ std::map<uint32_t, uint32_t> flexPlanarPixelFormat;
+ std::map<uint32_t, uint32_t> flexSemiPlanarPixelFormat;
if (pixelFormatInfo && *pixelFormatInfo) {
for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
const C2FlexiblePixelFormatDescriptorStruct &desc =
pixelFormatInfo->m.values[i];
- if (desc.bitDepth != 8
- || desc.subsampling != C2Color::YUV_420
+ if (desc.subsampling != C2Color::YUV_420
// TODO(b/180076105): some device report wrong layout
// || desc.layout == C2Color::INTERLEAVED_PACKED
// || desc.layout == C2Color::INTERLEAVED_ALIGNED
|| desc.layout == C2Color::UNKNOWN_LAYOUT) {
continue;
}
- if (!flexPixelFormat) {
- flexPixelFormat = desc.pixelFormat;
+ if (flexPixelFormat.count(desc.bitDepth) == 0) {
+ flexPixelFormat.emplace(desc.bitDepth, desc.pixelFormat);
}
- if (desc.layout == C2Color::PLANAR_PACKED && !flexPlanarPixelFormat) {
- flexPlanarPixelFormat = desc.pixelFormat;
+ if (desc.layout == C2Color::PLANAR_PACKED
+ && flexPlanarPixelFormat.count(desc.bitDepth) == 0) {
+ flexPlanarPixelFormat.emplace(desc.bitDepth, desc.pixelFormat);
}
- if (desc.layout == C2Color::SEMIPLANAR_PACKED && !flexSemiPlanarPixelFormat) {
- flexSemiPlanarPixelFormat = desc.pixelFormat;
+ if (desc.layout == C2Color::SEMIPLANAR_PACKED
+ && flexSemiPlanarPixelFormat.count(desc.bitDepth) == 0) {
+ flexSemiPlanarPixelFormat.emplace(desc.bitDepth, desc.pixelFormat);
}
}
}
@@ -1050,7 +1052,7 @@
if (!(config->mDomain & Config::IS_ENCODER)) {
if (surface == nullptr) {
const char *prefix = "";
- if (flexSemiPlanarPixelFormat) {
+ if (flexSemiPlanarPixelFormat.count(8) != 0) {
format = COLOR_FormatYUV420SemiPlanar;
prefix = "semi-";
} else {
@@ -1067,17 +1069,34 @@
if ((config->mDomain & Config::IS_ENCODER) || !surface) {
switch (format) {
case COLOR_FormatYUV420Flexible:
- format = flexPixelFormat.value_or(COLOR_FormatYUV420Planar);
+ format = COLOR_FormatYUV420Planar;
+ if (flexPixelFormat.count(8) != 0) {
+ format = flexPixelFormat[8];
+ }
break;
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420PackedPlanar:
- format = flexPlanarPixelFormat.value_or(
- flexPixelFormat.value_or(format));
+ if (flexPlanarPixelFormat.count(8) != 0) {
+ format = flexPlanarPixelFormat[8];
+ } else if (flexPixelFormat.count(8) != 0) {
+ format = flexPixelFormat[8];
+ }
break;
case COLOR_FormatYUV420SemiPlanar:
case COLOR_FormatYUV420PackedSemiPlanar:
- format = flexSemiPlanarPixelFormat.value_or(
- flexPixelFormat.value_or(format));
+ if (flexSemiPlanarPixelFormat.count(8) != 0) {
+ format = flexSemiPlanarPixelFormat[8];
+ } else if (flexPixelFormat.count(8) != 0) {
+ format = flexPixelFormat[8];
+ }
+ break;
+ case COLOR_FormatYUVP010:
+ format = COLOR_FormatYUVP010;
+ if (flexSemiPlanarPixelFormat.count(10) != 0) {
+ format = flexSemiPlanarPixelFormat[10];
+ } else if (flexPixelFormat.count(10) != 0) {
+ format = flexPixelFormat[10];
+ }
break;
default:
// No-op
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/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 4070478..2d3c70a 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>
@@ -358,21 +363,22 @@
break;
case COLOR_FormatYUVP010:
+ // stride is in bytes
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
mediaImage->mPlane[mediaImage->Y].mColInc = 2;
- mediaImage->mPlane[mediaImage->Y].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
- mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride * 2;
+ mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
mediaImage->mPlane[mediaImage->U].mColInc = 4;
- mediaImage->mPlane[mediaImage->U].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->U].mRowInc = stride;
mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
- mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 2 + 2;
+ mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
mediaImage->mPlane[mediaImage->V].mColInc = 4;
- mediaImage->mPlane[mediaImage->V].mRowInc = stride * 2;
+ mediaImage->mPlane[mediaImage->V].mRowInc = stride;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
if (tryWrapping) {
@@ -533,8 +539,8 @@
mInitCheck = BAD_VALUE;
return;
}
- bufferSize += stride * vStride
- / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
+ // stride is in bytes
+ bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
}
mBackBufferSize = bufferSize;
@@ -787,8 +793,14 @@
ALOGD("format had no width / height");
return nullptr;
}
- // NOTE: we currently only support YUV420 formats for byte-buffer mode.
- sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * 3 / 2));
+ int32_t colorFormat = COLOR_FormatYUV420Flexible;
+ int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
+ if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
+ if (colorFormat == COLOR_FormatYUVP010) {
+ bpp = 24; // 16(Y) + 4(U) + 4(V)
+ }
+ }
+ sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
return new ConstGraphicBlockBuffer(
format,
aBuffer,
@@ -941,4 +953,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/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 67d7ed2..63bd64b 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -54,6 +54,9 @@
using Traits = C2Component::Traits;
+// HAL pixel format -> framework color format
+typedef std::map<uint32_t, int32_t> PixelFormatMap;
+
namespace /* unnamed */ {
bool hasPrefix(const std::string& s, const char* prefix) {
@@ -67,6 +70,26 @@
s.compare(s.size() - suffixLen, suffixLen, suffix) == 0;
}
+std::optional<int32_t> findFrameworkColorFormat(
+ const C2FlexiblePixelFormatDescriptorStruct &desc) {
+ switch (desc.bitDepth) {
+ case 8u:
+ if (desc.layout == C2Color::PLANAR_PACKED
+ || desc.layout == C2Color::SEMIPLANAR_PACKED) {
+ return COLOR_FormatYUV420Flexible;
+ }
+ break;
+ case 10u:
+ if (desc.layout == C2Color::SEMIPLANAR_PACKED) {
+ return COLOR_FormatYUVP010;
+ }
+ break;
+ default:
+ break;
+ }
+ return std::nullopt;
+}
+
// returns true if component advertised supported profile level(s)
bool addSupportedProfileLevels(
std::shared_ptr<Codec2Client::Interface> intf,
@@ -211,27 +234,69 @@
void addSupportedColorFormats(
std::shared_ptr<Codec2Client::Interface> intf,
MediaCodecInfo::CapabilitiesWriter *caps,
- const Traits& trait, const std::string &mediaType) {
- (void)intf;
-
+ const Traits& trait, const std::string &mediaType,
+ const PixelFormatMap &pixelFormatMap) {
// TODO: get this from intf() as well, but how do we map them to
// MediaCodec color formats?
bool encoder = trait.kind == C2Component::KIND_ENCODER;
if (mediaType.find("video") != std::string::npos
|| mediaType.find("image") != std::string::npos) {
+
+ std::vector<C2FieldSupportedValuesQuery> query;
+ if (encoder) {
+ C2StreamPixelFormatInfo::input pixelFormat;
+ query.push_back(C2FieldSupportedValuesQuery::Possible(
+ C2ParamField::Make(pixelFormat, pixelFormat.value)));
+ } else {
+ C2StreamPixelFormatInfo::output pixelFormat;
+ query.push_back(C2FieldSupportedValuesQuery::Possible(
+ C2ParamField::Make(pixelFormat, pixelFormat.value)));
+ }
+ std::list<int32_t> supportedColorFormats;
+ if (intf->querySupportedValues(query, C2_DONT_BLOCK) == C2_OK) {
+ if (query[0].status == C2_OK) {
+ const C2FieldSupportedValues &fsv = query[0].values;
+ if (fsv.type == C2FieldSupportedValues::VALUES) {
+ for (C2Value::Primitive value : fsv.values) {
+ auto it = pixelFormatMap.find(value.u32);
+ if (it != pixelFormatMap.end()) {
+ auto it2 = std::find(
+ supportedColorFormats.begin(),
+ supportedColorFormats.end(),
+ it->second);
+ if (it2 == supportedColorFormats.end()) {
+ supportedColorFormats.push_back(it->second);
+ }
+ }
+ }
+ }
+ }
+ }
+ auto addDefaultColorFormat = [caps, &supportedColorFormats](int32_t colorFormat) {
+ caps->addColorFormat(colorFormat);
+ auto it = std::find(
+ supportedColorFormats.begin(), supportedColorFormats.end(), colorFormat);
+ if (it != supportedColorFormats.end()) {
+ supportedColorFormats.erase(it);
+ }
+ };
+
// vendor video codecs prefer opaque format
if (trait.name.find("android") == std::string::npos) {
- caps->addColorFormat(COLOR_FormatSurface);
+ addDefaultColorFormat(COLOR_FormatSurface);
}
- caps->addColorFormat(COLOR_FormatYUV420Flexible);
- caps->addColorFormat(COLOR_FormatYUV420Planar);
- caps->addColorFormat(COLOR_FormatYUV420SemiPlanar);
- caps->addColorFormat(COLOR_FormatYUV420PackedPlanar);
- caps->addColorFormat(COLOR_FormatYUV420PackedSemiPlanar);
+ addDefaultColorFormat(COLOR_FormatYUV420Flexible);
+ addDefaultColorFormat(COLOR_FormatYUV420Planar);
+ addDefaultColorFormat(COLOR_FormatYUV420SemiPlanar);
+ addDefaultColorFormat(COLOR_FormatYUV420PackedPlanar);
+ addDefaultColorFormat(COLOR_FormatYUV420PackedSemiPlanar);
// framework video encoders must support surface format, though it is unclear
// that they will be able to map it if it is opaque
if (encoder && trait.name.find("android") != std::string::npos) {
- caps->addColorFormat(COLOR_FormatSurface);
+ addDefaultColorFormat(COLOR_FormatSurface);
+ }
+ for (int32_t colorFormat : supportedColorFormats) {
+ caps->addColorFormat(colorFormat);
}
}
}
@@ -423,6 +488,7 @@
}
}
+ std::map<std::string, PixelFormatMap> nameToPixelFormatMap;
for (const Traits& trait : traits) {
C2Component::rank_t rank = trait.rank;
@@ -436,8 +502,9 @@
nameAndAliases.insert(nameAndAliases.begin(), trait.name);
for (const std::string &nameOrAlias : nameAndAliases) {
bool isAlias = trait.name != nameOrAlias;
+ std::shared_ptr<Codec2Client> client;
std::shared_ptr<Codec2Client::Interface> intf =
- Codec2Client::CreateInterfaceByName(nameOrAlias.c_str());
+ Codec2Client::CreateInterfaceByName(nameOrAlias.c_str(), &client);
if (!intf) {
ALOGD("could not create interface for %s'%s'",
isAlias ? "alias " : "",
@@ -631,7 +698,40 @@
caps->addProfileLevel(VP8ProfileMain, VP8Level_Version0);
}
}
- addSupportedColorFormats(intf, caps.get(), trait, mediaType);
+
+ auto it = nameToPixelFormatMap.find(client->getServiceName());
+ if (it == nameToPixelFormatMap.end()) {
+ it = nameToPixelFormatMap.try_emplace(client->getServiceName()).first;
+ PixelFormatMap &pixelFormatMap = it->second;
+ pixelFormatMap[HAL_PIXEL_FORMAT_YCBCR_420_888] = COLOR_FormatYUV420Flexible;
+ pixelFormatMap[HAL_PIXEL_FORMAT_YCBCR_P010] = COLOR_FormatYUVP010;
+ pixelFormatMap[HAL_PIXEL_FORMAT_RGBA_1010102] = COLOR_Format32bitABGR2101010;
+ pixelFormatMap[HAL_PIXEL_FORMAT_RGBA_FP16] = COLOR_Format64bitABGRFloat;
+
+ std::shared_ptr<C2StoreFlexiblePixelFormatDescriptorsInfo> pixelFormatInfo;
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ if (client->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo.reset(C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].release()));
+ }
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ std::optional<int32_t> colorFormat = findFrameworkColorFormat(desc);
+ if (colorFormat) {
+ pixelFormatMap[desc.pixelFormat] = *colorFormat;
+ }
+ }
+ }
+ }
+ addSupportedColorFormats(
+ intf, caps.get(), trait, mediaType, it->second);
}
}
}
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 2213001..b761c35 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -88,7 +88,7 @@
uint32_t planeW = img->mWidth / plane.colSampling;
uint32_t planeH = img->mHeight / plane.rowSampling;
- bool canCopyByRow = (plane.colInc == 1) && (img->mPlane[i].mColInc == 1);
+ bool canCopyByRow = (plane.colInc == bpp) && (img->mPlane[i].mColInc == bpp);
bool canCopyByPlane = canCopyByRow && (plane.rowInc == img->mPlane[i].mRowInc);
if (canCopyByPlane) {
MemCopier<ToMediaImage, 0>::copy(imgRow, viewRow, plane.rowInc * planeH);
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index f557830..93f29ca 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -18,6 +18,9 @@
#define LOG_TAG "Codec2Mapper"
#include <utils/Log.h>
+#include <map>
+#include <optional>
+
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/SurfaceUtils.h>
#include <media/stagefright/foundation/ALookup.h>
@@ -167,6 +170,9 @@
{ C2Config::LEVEL_DV_MAIN_UHD_30, DolbyVisionLevelUhd30 },
{ C2Config::LEVEL_DV_MAIN_UHD_48, DolbyVisionLevelUhd48 },
{ C2Config::LEVEL_DV_MAIN_UHD_60, DolbyVisionLevelUhd60 },
+ { C2Config::LEVEL_DV_MAIN_UHD_120, DolbyVisionLevelUhd120 },
+ { C2Config::LEVEL_DV_MAIN_8K_30, DolbyVisionLevel8k30 },
+ { C2Config::LEVEL_DV_MAIN_8K_60, DolbyVisionLevel8k60 },
// high tiers are not yet supported on android, for now map them to main tier
{ C2Config::LEVEL_DV_HIGH_HD_24, DolbyVisionLevelHd24 },
@@ -178,6 +184,9 @@
{ C2Config::LEVEL_DV_HIGH_UHD_30, DolbyVisionLevelUhd30 },
{ C2Config::LEVEL_DV_HIGH_UHD_48, DolbyVisionLevelUhd48 },
{ C2Config::LEVEL_DV_HIGH_UHD_60, DolbyVisionLevelUhd60 },
+ { C2Config::LEVEL_DV_HIGH_UHD_120, DolbyVisionLevelUhd120 },
+ { C2Config::LEVEL_DV_HIGH_8K_30, DolbyVisionLevel8k30 },
+ { C2Config::LEVEL_DV_HIGH_8K_60, DolbyVisionLevel8k60 },
};
ALookup<C2Config::profile_t, int32_t> sDolbyVisionProfiles = {
@@ -402,6 +411,30 @@
{ C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10Plus },
};
+// HAL_PIXEL_FORMAT_* -> COLOR_Format*
+ALookup<uint32_t, int32_t> sPixelFormats = {
+ { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, COLOR_FormatSurface },
+
+ // YCBCR_420_888 maps to YUV420Flexible and vice versa
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420Flexible },
+
+ // Fallback matches for YCBCR_420_888
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420Planar },
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420SemiPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420PackedPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_420_888, COLOR_FormatYUV420PackedSemiPlanar },
+
+ // Fallback matches for YUV420Flexible
+ { HAL_PIXEL_FORMAT_YCRCB_420_SP, COLOR_FormatYUV420Flexible },
+ { HAL_PIXEL_FORMAT_YV12, COLOR_FormatYUV420Flexible },
+
+ { HAL_PIXEL_FORMAT_YCBCR_422_SP, COLOR_FormatYUV422PackedSemiPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_422_I, COLOR_FormatYUV422PackedPlanar },
+ { HAL_PIXEL_FORMAT_YCBCR_P010, COLOR_FormatYUVP010 },
+ { HAL_PIXEL_FORMAT_RGBA_1010102, COLOR_Format32bitABGR2101010 },
+ { HAL_PIXEL_FORMAT_RGBA_FP16, COLOR_Format64bitABGRFloat },
+};
+
/**
* A helper that passes through vendor extension profile and level values.
*/
@@ -975,41 +1008,19 @@
// static
bool C2Mapper::mapPixelFormatFrameworkToCodec(
int32_t frameworkValue, uint32_t *c2Value) {
- switch (frameworkValue) {
- case COLOR_FormatSurface:
- *c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- return true;
- case COLOR_FormatYUV420Flexible:
- case COLOR_FormatYUV420Planar:
- case COLOR_FormatYUV420SemiPlanar:
- case COLOR_FormatYUV420PackedPlanar:
- case COLOR_FormatYUV420PackedSemiPlanar:
- *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
- return true;
- default:
- // Passthrough
- *c2Value = uint32_t(frameworkValue);
- return true;
+ if (!sPixelFormats.map(frameworkValue, c2Value)) {
+ // passthrough if not mapped
+ *c2Value = uint32_t(frameworkValue);
}
+ return true;
}
// static
bool C2Mapper::mapPixelFormatCodecToFramework(
uint32_t c2Value, int32_t *frameworkValue) {
- switch (c2Value) {
- case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
- *frameworkValue = COLOR_FormatSurface;
- return true;
- case HAL_PIXEL_FORMAT_YCBCR_422_SP:
- case HAL_PIXEL_FORMAT_YCRCB_420_SP:
- case HAL_PIXEL_FORMAT_YCBCR_422_I:
- case HAL_PIXEL_FORMAT_YCBCR_420_888:
- case HAL_PIXEL_FORMAT_YV12:
- *frameworkValue = COLOR_FormatYUV420Flexible;
- return true;
- default:
- // Passthrough
- *frameworkValue = int32_t(c2Value);
- return true;
+ if (!sPixelFormats.map(c2Value, frameworkValue)) {
+ // passthrough if not mapped
+ *frameworkValue = int32_t(c2Value);
}
+ return true;
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 8836c47..fb935b6 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1127,10 +1127,10 @@
void *data;
size_t size;
- if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2,
+ if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0,
&data, &size)
- && size >= 5) {
- const uint8_t *ptr = (const uint8_t *)data;
+ && size >= 24) {
+ const uint8_t *ptr = (const uint8_t *)data + (size - 24);
const uint8_t profile = ptr[2] >> 1;
const uint8_t bl_compatibility_id = (ptr[4]) >> 4;
bool create_two_tracks = false;
@@ -1147,13 +1147,15 @@
track_b->timescale = mLastTrack->timescale;
track_b->sampleTable = mLastTrack->sampleTable;
- track_b->includes_expensive_metadata = mLastTrack->includes_expensive_metadata;
+ track_b->includes_expensive_metadata =
+ mLastTrack->includes_expensive_metadata;
track_b->skipTrack = mLastTrack->skipTrack;
track_b->elst_needs_processing = mLastTrack->elst_needs_processing;
track_b->elst_media_time = mLastTrack->elst_media_time;
track_b->elst_segment_duration = mLastTrack->elst_segment_duration;
track_b->elst_shift_start_ticks = mLastTrack->elst_shift_start_ticks;
- track_b->elst_initial_empty_edit_ticks = mLastTrack->elst_initial_empty_edit_ticks;
+ track_b->elst_initial_empty_edit_ticks =
+ mLastTrack->elst_initial_empty_edit_ticks;
track_b->subsample_encryption = mLastTrack->subsample_encryption;
track_b->mTx3gBuffer = mLastTrack->mTx3gBuffer;
@@ -1166,11 +1168,11 @@
mLastTrack->next = track_b;
track_b->next = NULL;
- // we want to remove the csd-2 key from the metadata, but
+ // we want to remove the csd-0 key from the metadata, but
// don't have an AMediaFormat_* function to do so. Settle
- // for replacing this csd-2 with an empty csd-2.
+ // for replacing this csd-0 with an empty csd-0.
uint8_t emptybuffer[8] = {};
- AMediaFormat_setBuffer(track_b->meta, AMEDIAFORMAT_KEY_CSD_2,
+ AMediaFormat_setBuffer(track_b->meta, AMEDIAFORMAT_KEY_CSD_0,
emptybuffer, 0);
if (4 == profile || 7 == profile || 8 == profile ) {
@@ -1182,6 +1184,8 @@
} else if (10 == profile) {
AMediaFormat_setString(track_b->meta,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
+ AMediaFormat_setBuffer(track_b->meta, AMEDIAFORMAT_KEY_CSD_0,
+ data, size - 24);
} // Should never get to else part
mLastTrack = track_b;
@@ -2591,9 +2595,11 @@
*offset += chunk_size;
break;
}
- case FOURCC("dvcC"):
- case FOURCC("dvvC"): {
+ case FOURCC("dvcC"):
+ case FOURCC("dvvC"):
+ case FOURCC("dvwC"):
+ {
if (chunk_data_size != 24) {
return ERROR_MALFORMED;
}
@@ -2612,14 +2618,29 @@
if (mLastTrack == NULL)
return ERROR_MALFORMED;
- AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_2,
- buffer.get(), chunk_data_size);
+ void *data = nullptr;
+ size_t size = 0;
+ if (AMediaFormat_getBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
+ //if csd-0 is already present, then append dvcc
+ auto csd0_dvcc = heapbuffer<uint8_t>(size + chunk_data_size);
+
+ memcpy(csd0_dvcc.get(), data, size);
+ memcpy(csd0_dvcc.get() + size, buffer.get(), chunk_data_size);
+
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0,
+ csd0_dvcc.get(), size + chunk_data_size);
+ } else {
+ //if not set csd-0 directly
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0,
+ buffer.get(), chunk_data_size);
+ }
AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME,
MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
*offset += chunk_size;
break;
}
+
case FOURCC("d263"):
{
*offset += chunk_size;
@@ -4458,7 +4479,6 @@
if (!AMediaFormat_getString(track->meta, AMEDIAFORMAT_KEY_MIME, &mime)) {
return NULL;
}
-
sp<ItemTable> itemTable;
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
void *data;
@@ -4491,14 +4511,14 @@
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
void *data;
size_t size;
- if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)
+ || size < 24) {
return NULL;
}
- const uint8_t *ptr = (const uint8_t *)data;
-
+ const uint8_t *ptr = (const uint8_t *)data + (size - 24);
// dv_major.dv_minor Should be 1.0 or 2.1
- if (size != 24 || ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1))) {
+ if ((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1)) {
return NULL;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)
@@ -4576,7 +4596,7 @@
return ERROR_MALFORMED;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
- if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_2, &data, &size)) {
+ if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_0, &data, &size)) {
return ERROR_MALFORMED;
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AV1)) {
@@ -5152,11 +5172,11 @@
ALOGV("%s DolbyVision stream detected", __FUNCTION__);
void *data;
size_t size;
- CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_2, &data, &size));
+ CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_0, &data, &size));
- const uint8_t *ptr = (const uint8_t *)data;
+ const uint8_t *ptr = (const uint8_t *)data + (size - 24);
- CHECK(size == 24);
+ CHECK(size >= 24);
// dv_major.dv_minor Should be 1.0 or 2.1
CHECK(!((ptr[0] != 1 || ptr[1] != 0) && (ptr[0] != 2 || ptr[1] != 1)));
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index b3c82787..be81481 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1972,6 +1972,19 @@
return result.value_or(false);
}
+bool AudioSystem::isUltrasoundSupported() {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return false;
+
+ auto result = [&]() -> ConversionResult<bool> {
+ bool retVal;
+ RETURN_IF_ERROR(
+ statusTFromBinderStatus(aps->isUltrasoundSupported(&retVal)));
+ return retVal;
+ }();
+ return result.value_or(false);
+}
+
status_t AudioSystem::getHwOffloadFormatsSupportedForBluetoothMedia(
audio_devices_t device, std::vector<audio_format_t>* formats) {
if (formats == nullptr) {
@@ -2314,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/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 7895ae3..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;
@@ -311,6 +312,8 @@
boolean isHapticPlaybackSupported();
+ boolean isUltrasoundSupported();
+
AudioProductStrategy[] listAudioProductStrategies();
int /* product_strategy_t */ getProductStrategyFromAudioAttributes(in AudioAttributesEx aa,
boolean fallbackOnDefault);
@@ -381,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 11eb070..4280a6a 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -444,6 +444,8 @@
static bool isHapticPlaybackSupported();
+ static bool isUltrasoundSupported();
+
static status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
static status_t getProductStrategyFromAudioAttributes(
const AudioAttributes &aa, product_strategy_t &productStrategy,
@@ -550,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/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/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 67d33fa..85768bd 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -20,12 +20,14 @@
#define LOG_TAG "MediaProfiles"
#include <stdlib.h>
+#include <utils/misc.h>
#include <utils/Log.h>
#include <utils/Vector.h>
#include <cutils/properties.h>
#include <expat.h>
#include <media/MediaProfiles.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <OMX_Video.h>
#include <sys/stat.h>
@@ -86,7 +88,24 @@
{"h263", VIDEO_ENCODER_H263},
{"h264", VIDEO_ENCODER_H264},
{"m4v", VIDEO_ENCODER_MPEG_4_SP},
- {"hevc", VIDEO_ENCODER_HEVC}
+ {"vp8", VIDEO_ENCODER_VP8},
+ {"hevc", VIDEO_ENCODER_HEVC},
+ {"vp9", VIDEO_ENCODER_VP9},
+ {"dolbyvision", VIDEO_ENCODER_DOLBY_VISION},
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sChromaSubsamplingNameMap[] = {
+ {"yuv 4:2:0", CHROMA_SUBSAMPLING_YUV_420},
+ {"yuv 4:2:2", CHROMA_SUBSAMPLING_YUV_422},
+ {"yuv 4:4:4", CHROMA_SUBSAMPLING_YUV_444},
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sHdrFormatNameMap[] = {
+ {"sdr", HDR_FORMAT_NONE},
+ {"hlg", HDR_FORMAT_HLG},
+ {"hdr10", HDR_FORMAT_HDR10},
+ {"hdr10+", HDR_FORMAT_HDR10PLUS},
+ {"dolbyvision", HDR_FORMAT_DOLBY_VISION},
};
const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
@@ -164,12 +183,18 @@
MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec UNUSED)
{
ALOGV("video codec:");
- ALOGV("codec = %d", codec.mCodec);
+ ALOGV("codec = %d (%s)", codec.mCodec,
+ findNameForTag(sVideoEncoderNameMap, NELEM(sVideoEncoderNameMap), codec.mCodec));
ALOGV("bit rate: %d", codec.mBitRate);
ALOGV("frame width: %d", codec.mFrameWidth);
ALOGV("frame height: %d", codec.mFrameHeight);
ALOGV("frame rate: %d", codec.mFrameRate);
ALOGV("profile: %d", codec.mProfile);
+ ALOGV("chroma: %s", findNameForTag(sChromaSubsamplingNameMap, NELEM(sChromaSubsamplingNameMap),
+ codec.mChromaSubsampling));
+ ALOGV("bit depth: %d", codec.mBitDepth);
+ ALOGV("hdr format: %s", findNameForTag(sHdrFormatNameMap, NELEM(sHdrFormatNameMap),
+ codec.mHdrFormat));
}
/*static*/ void
@@ -232,6 +257,155 @@
return tag;
}
+/*static*/ const char *
+MediaProfiles::findNameForTag(
+ const MediaProfiles::NameToTagMap *map, size_t nMappings, int tag, const char *def_)
+{
+ for (size_t i = 0; i < nMappings; ++i) {
+ if (map[i].tag == tag) {
+ return map[i].name;
+ }
+ }
+ return def_;
+}
+
+/*static*/ bool
+MediaProfiles::detectAdvancedVideoProfile(
+ video_encoder codec, int profile,
+ chroma_subsampling *chroma, int *bitDepth, hdr_format *hdr)
+{
+ // default values
+ *chroma = CHROMA_SUBSAMPLING_YUV_420;
+ *bitDepth = 8;
+ *hdr = HDR_FORMAT_NONE;
+
+ switch (codec) {
+ case VIDEO_ENCODER_H263:
+ case VIDEO_ENCODER_MPEG_4_SP:
+ case VIDEO_ENCODER_VP8:
+ // these are always 4:2:0 SDR 8-bit
+ return true;
+
+ case VIDEO_ENCODER_H264:
+ switch (profile) {
+ case AVCProfileBaseline:
+ case AVCProfileConstrainedBaseline:
+ case AVCProfileMain:
+ case AVCProfileExtended:
+ case AVCProfileHigh:
+ case AVCProfileConstrainedHigh:
+ return true;
+ case AVCProfileHigh10:
+ // returning false here as this could be an HLG stream
+ *bitDepth = 10;
+ return false;
+ case AVCProfileHigh422:
+ *chroma = CHROMA_SUBSAMPLING_YUV_422;
+ // returning false here as bit-depth could be 8 or 10
+ return false;
+ case AVCProfileHigh444:
+ *chroma = CHROMA_SUBSAMPLING_YUV_444;
+ // returning false here as bit-depth could be 8 or 10
+ return false;
+ default:
+ return false;
+ }
+ // flow does not get here
+
+ case VIDEO_ENCODER_HEVC:
+ switch (profile) {
+ case HEVCProfileMain:
+ return true;
+ case HEVCProfileMain10:
+ *bitDepth = 10;
+ // returning false here as this could be an HLG stream
+ return false;
+ case HEVCProfileMain10HDR10:
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_HDR10;
+ return true;
+ case HEVCProfileMain10HDR10Plus:
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_HDR10PLUS;
+ return true;
+ default:
+ return false;
+ }
+ // flow does not get here
+
+ case VIDEO_ENCODER_VP9:
+ switch (profile) {
+ case VP9Profile0:
+ return true;
+ case VP9Profile2:
+ // this is always 10-bit on Android */
+ *bitDepth = 10;
+ // returning false here as this could be an HLG stream
+ return false;
+ case VP9Profile2HDR:
+ // this is always 10-bit on Android */
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_HDR10;
+ return true;
+ case VP9Profile2HDR10Plus:
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_HDR10PLUS;
+ return true;
+ default:
+ return false;
+ }
+ // flow does not get here
+
+ case VIDEO_ENCODER_DOLBY_VISION:
+ {
+ // for Dolby Vision codec we always assume 10-bit DV
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_DOLBY_VISION;
+
+ switch (profile) {
+ case DolbyVisionProfileDvheDer /* profile 2 deprecated */:
+ case DolbyVisionProfileDvheDen /* profile 3 deprecated */:
+ case DolbyVisionProfileDvavPer /* profile 0 deprecated */:
+ case DolbyVisionProfileDvavPen /* profile 1 deprecated */:
+ case DolbyVisionProfileDvheDtr /* dvhe.04 */:
+ case DolbyVisionProfileDvheStn /* dvhe.05 */:
+ case DolbyVisionProfileDvheDth /* profile 6 deprecated */:
+ case DolbyVisionProfileDvheDtb /* dvhe.07 */:
+ case DolbyVisionProfileDvheSt /* dvhe.08 */:
+ case DolbyVisionProfileDvavSe /* dvav.09 */:
+ case DolbyVisionProfileDvav110 /* dvav1.10 */:
+ return true;
+ default:
+ return false;
+ }
+ // flow does not get here
+ }
+
+ case VIDEO_ENCODER_AV1:
+ switch (profile) {
+ case AV1ProfileMain10:
+ *bitDepth = 10;
+ // returning false here as this could be an HLG stream
+ return false;
+ case AV1ProfileMain10HDR10:
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_HDR10;
+ return true;
+ case AV1ProfileMain10HDR10Plus:
+ *bitDepth = 10;
+ *hdr = HDR_FORMAT_HDR10PLUS;
+ return true;
+ default:
+ return false;
+ }
+ // flow does not get here
+
+ default:
+ return false;
+ }
+ // flow does not get here
+}
+
/*static*/ void
MediaProfiles::createVideoCodec(const char **atts, size_t natts, MediaProfiles *profiles)
{
@@ -250,13 +424,56 @@
}
int profile = -1;
- if (natts >= 12 && !strcmp("profile", atts[10])) {
- profile = atoi(atts[11]);
+ chroma_subsampling chroma = CHROMA_SUBSAMPLING_YUV_420;
+ int bitDepth = 8;
+ hdr_format hdr = HDR_FORMAT_NONE;
+ if (codec == VIDEO_ENCODER_DOLBY_VISION) {
+ bitDepth = 10;
+ hdr = HDR_FORMAT_DOLBY_VISION;
}
- VideoCodec videoCodec {
+ if (natts >= 12 && !strcmp("profile", atts[10])) {
+ profile = atoi(atts[11]);
+ if (!detectAdvancedVideoProfile(
+ (video_encoder)codec, profile, &chroma, &bitDepth, &hdr)) {
+ // if not detected read values from the attributes
+ for (size_t ix = 12; natts >= ix + 2; ix += 2) {
+ if (!strcmp("chroma", atts[ix])) {
+ int chromaTag = findTagForName(sChromaSubsamplingNameMap,
+ NELEM(sChromaSubsamplingNameMap), atts[ix + 1]);
+ if (chromaTag == -1) {
+ ALOGE("MediaProfiles::createVideoCodec invalid chroma %s", atts[ix + 1]);
+ return;
+ } else {
+ chroma = (chroma_subsampling)chromaTag;
+ }
+ } else if (!strcmp("bitDepth", atts[ix])) {
+ bitDepth = atoi(atts[ix + 1]);
+ if (bitDepth < 8 || bitDepth > 16) {
+ ALOGE("MediaProfiles::createVideoCodec invalid bidDepth %s", atts[ix + 1]);
+ return;
+ }
+ } else if (!strcmp("hdr", atts[ix])) {
+ int hdrTag = findTagForName(sHdrFormatNameMap,
+ NELEM(sHdrFormatNameMap), atts[ix + 1]);
+ if (hdrTag == -1) {
+ ALOGE("MediaProfiles::createVideoCodec invalid hdr %s", atts[ix + 1]);
+ return;
+ } else {
+ hdr = (hdr_format)hdrTag;
+ }
+ } else {
+ // ignoring here. TODO: rewrite this whole file to ignore invalid attrs
+ ALOGD("MediaProfiles::createVideoCodec ignoring invalid attr %s", atts[ix]);
+ }
+ }
+ }
+ }
+
+ VideoCodec videoCodec{
static_cast<video_encoder>(codec),
- atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), profile };
+ atoi(atts[3]) /* bitRate */, atoi(atts[5]) /* width */, atoi(atts[7]) /* height */,
+ atoi(atts[9]) /* frameRate */, profile, chroma, bitDepth, hdr };
logVideoCodec(videoCodec);
size_t nCamcorderProfiles;
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index 4a898e2..e75b694 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -81,6 +81,19 @@
AUDIO_DECODER_WMA,
};
+enum chroma_subsampling {
+ CHROMA_SUBSAMPLING_YUV_420,
+ CHROMA_SUBSAMPLING_YUV_422,
+ CHROMA_SUBSAMPLING_YUV_444,
+};
+
+enum hdr_format {
+ HDR_FORMAT_NONE,
+ HDR_FORMAT_HLG,
+ HDR_FORMAT_HDR10,
+ HDR_FORMAT_HDR10PLUS,
+ HDR_FORMAT_DOLBY_VISION,
+};
class MediaProfiles
{
@@ -117,13 +130,19 @@
* @param profile codec profile (for MediaCodec) or -1 for none
*/
VideoCodec(video_encoder codec, int bitrate, int frameWidth, int frameHeight, int frameRate,
- int profile = -1)
+ int profile = -1,
+ chroma_subsampling chroma = CHROMA_SUBSAMPLING_YUV_420,
+ int bitDepth = 8,
+ hdr_format hdr = HDR_FORMAT_NONE)
: mCodec(codec),
mBitRate(bitrate),
mFrameWidth(frameWidth),
mFrameHeight(frameHeight),
mFrameRate(frameRate),
- mProfile(profile) {
+ mProfile(profile),
+ mChromaSubsampling(chroma),
+ mBitDepth(bitDepth),
+ mHdrFormat(hdr) {
}
VideoCodec(const VideoCodec&) = default;
@@ -160,6 +179,21 @@
return mProfile;
}
+ /** Returns the chroma subsampling. */
+ chroma_subsampling getChromaSubsampling() const {
+ return mChromaSubsampling;
+ }
+
+ /** Returns the bit depth. */
+ int getBitDepth() const {
+ return mBitDepth;
+ }
+
+ /** Returns the chroma subsampling. */
+ hdr_format getHdrFormat() const {
+ return mHdrFormat;
+ }
+
private:
video_encoder mCodec;
int mBitRate;
@@ -167,6 +201,9 @@
int mFrameHeight;
int mFrameRate;
int mProfile;
+ chroma_subsampling mChromaSubsampling;
+ int mBitDepth;
+ hdr_format mHdrFormat;
friend class MediaProfiles;
};
@@ -533,6 +570,39 @@
static int findTagForName(const NameToTagMap *map, size_t nMappings, const char *name);
/**
+ * Finds the string representation for an integer enum tag.
+ *
+ * This is the reverse for findTagForName
+ *
+ * @param map the name-to-tag map to search
+ * @param nMappings the number of mappings in |map|
+ * @param tag the enum value to find
+ * @param def_ the return value if the enum is not found
+ *
+ * @return the string name corresponding to |tag| or |def_| if not found.
+ */
+ static const char *findNameForTag(
+ const NameToTagMap *map, size_t nMappings,
+ int tag, const char *def_ = "(unknown)");
+
+ /**
+ * Updates the chroma subsampling, bit-depth and hdr-format for
+ * advanced codec profiles.
+ *
+ * @param codec the video codec type
+ * @param profile the MediaCodec profile
+ * @param chroma pointer to the chroma subsampling output
+ * @param bitDepth pointer to the bit depth output
+ * @param hdr pointer to the hdr format output
+ *
+ * @return true, if the profile fully determined chroma, bit-depth and hdr-format, false
+ * otherwise.
+ */
+ static bool detectAdvancedVideoProfile(
+ video_encoder codec, int profile,
+ chroma_subsampling *chroma, int *bitDepth, hdr_format *hdr);
+
+ /**
* Check on existing profiles with the following criteria:
* 1. Low quality profile must have the lowest video
* resolution product (width x height)
@@ -549,6 +619,8 @@
// Mappings from name (for instance, codec name) to enum value
static const NameToTagMap sVideoEncoderNameMap[];
+ static const NameToTagMap sChromaSubsamplingNameMap[];
+ static const NameToTagMap sHdrFormatNameMap[];
static const NameToTagMap sAudioEncoderNameMap[];
static const NameToTagMap sFileFormatMap[];
static const NameToTagMap sVideoDecoderNameMap[];
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index d54ff32..dd18144 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -108,7 +108,9 @@
VIDEO_ENCODER_MPEG_4_SP = 3,
VIDEO_ENCODER_VP8 = 4,
VIDEO_ENCODER_HEVC = 5,
-
+ VIDEO_ENCODER_VP9 = 6,
+ VIDEO_ENCODER_DOLBY_VISION = 7,
+ VIDEO_ENCODER_AV1 = 8,
VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
};
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..71a3168 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",
@@ -68,6 +76,7 @@
"libmedia",
"libmediadrm",
"libpowermanager",
+ "android.hardware.drm-V1-ndk",
],
static_libs: [
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/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 01cb9b3..5da32c9 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -35,6 +35,7 @@
#include <media/stagefright/FrameCaptureProcessor.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
@@ -192,6 +193,13 @@
*dstBpp = 4;
return true;
}
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ {
+ *dstFormat = (OMX_COLOR_FORMATTYPE)COLOR_Format32bitABGR2101010;
+ *captureFormat = ui::PixelFormat::RGBA_1010102;
+ *dstBpp = 4;
+ return true;
+ }
default:
{
ALOGE("Unsupported color format: %d", colorFormat);
@@ -523,8 +531,12 @@
return NULL;
}
- // TODO: Use Flexible color instead
- videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
+ if (dstFormat() == COLOR_Format32bitABGR2101010) {
+ videoFormat->setInt32("color-format", COLOR_FormatYUVP010);
+ } else {
+ // TODO: Use Flexible color instead
+ videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
+ }
// For the thumbnail extraction case, try to allocate single buffer in both
// input and output ports, if seeking to a sync frame. NOTE: This request may
@@ -632,6 +644,11 @@
crop_bottom = height - 1;
}
+ int32_t slice_height;
+ if (outputFormat->findInt32("slice-height", &slice_height) && slice_height > 0) {
+ height = slice_height;
+ }
+
if (mFrame == NULL) {
sp<IMemory> frameMem = allocVideoFrame(
trackMeta(),
@@ -831,8 +848,12 @@
return NULL;
}
- // TODO: Use Flexible color instead
- videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
+ if (dstFormat() == COLOR_Format32bitABGR2101010) {
+ videoFormat->setInt32("color-format", COLOR_FormatYUVP010);
+ } else {
+ // TODO: Use Flexible color instead
+ videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
+ }
if ((mGridRows == 1) && (mGridCols == 1)) {
videoFormat->setInt32("android._num-input-buffers", 1);
@@ -938,6 +959,11 @@
crop_bottom = height - 1;
}
+ int32_t slice_height;
+ if (outputFormat->findInt32("slice-height", &slice_height) && slice_height > 0) {
+ height = slice_height;
+ }
+
int32_t crop_width, crop_height;
crop_width = crop_right - crop_left + 1;
crop_height = crop_bottom - crop_top + 1;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 3784dde..a0c8f8a 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -156,7 +156,7 @@
bool isHeic() const { return mIsHeic; }
bool isAudio() const { return mIsAudio; }
bool isMPEG4() const { return mIsMPEG4; }
- bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic; }
+ bool usePrefix() const { return mIsAvc || mIsHevc || mIsHeic || mIsDovi; }
bool isExifData(MediaBufferBase *buffer, uint32_t *tiffHdrOffset) const;
void addChunkOffset(off64_t offset);
void addItemOffsetAndSize(off64_t offset, size_t size, bool isExif);
@@ -164,6 +164,7 @@
TrackId& getTrackId() { return mTrackId; }
status_t dump(int fd, const Vector<String16>& args) const;
static const char *getFourCCForMime(const char *mime);
+ const char *getDoviFourCC() const;
const char *getTrackType() const;
void resetInternal();
int64_t trackMetaDataSize();
@@ -316,6 +317,7 @@
volatile bool mStarted;
bool mIsAvc;
bool mIsHevc;
+ bool mIsDovi;
bool mIsAudio;
bool mIsVideo;
bool mIsHeic;
@@ -370,6 +372,10 @@
uint8_t mProfileCompatible;
uint8_t mLevelIdc;
+ uint8_t mDoviProfile;
+ void *mDoviConfigData;
+ size_t mDoviConfigDataSize;
+
void *mCodecSpecificData;
size_t mCodecSpecificDataSize;
bool mGotAllCodecSpecificData;
@@ -422,6 +428,8 @@
status_t parseHEVCCodecSpecificData(
const uint8_t *data, size_t size, HevcParameterSets ¶mSets);
+ status_t makeDoviCodecSpecificData();
+
// Track authoring progress status
void trackProgressStatus(int64_t timeUs, status_t err = OK);
void initTrackingProgressStatus(MetaData *params);
@@ -459,6 +467,7 @@
void writePaspBox();
void writeAvccBox();
void writeHvccBox();
+ void writeDoviConfigBox();
void writeUrlBox();
void writeDrefBox();
void writeDinfBox();
@@ -618,6 +627,17 @@
return OK;
}
+const char *MPEG4Writer::Track::getDoviFourCC() const {
+ if (mDoviProfile == 5) {
+ return "dvh1";
+ } else if (mDoviProfile == 8) {
+ return "hvc1";
+ } else if (mDoviProfile == 9 || mDoviProfile == 32) {
+ return "avc1";
+ }
+ return (const char*)NULL;
+}
+
// static
const char *MPEG4Writer::Track::getFourCCForMime(const char *mime) {
if (mime == NULL) {
@@ -672,7 +692,9 @@
mIsBackgroundMode |= isBackgroundMode;
}
- if (Track::getFourCCForMime(mime) == NULL) {
+ if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ ALOGV("Add source mime '%s'", mime);
+ } else if (Track::getFourCCForMime(mime) == NULL) {
ALOGE("Unsupported mime '%s'", mime);
return ERROR_UNSUPPORTED;
}
@@ -2151,6 +2173,8 @@
mMinCttsOffsetTimeUs(0),
mMinCttsOffsetTicks(0),
mMaxCttsOffsetTicks(0),
+ mDoviConfigData(NULL),
+ mDoviConfigDataSize(0),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false),
@@ -2177,6 +2201,7 @@
mMeta->findCString(kKeyMIMEType, &mime);
mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
mIsHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
+ mIsDovi = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION);
mIsAudio = !strncasecmp(mime, "audio/", 6);
mIsVideo = !strncasecmp(mime, "video/", 6);
mIsHeic = !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
@@ -2611,7 +2636,12 @@
!strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
mMeta->findData(kKeyHVCC, &type, &data, &size);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
- mMeta->findData(kKeyDVCC, &type, &data, &size);
+ makeDoviCodecSpecificData();
+ if (!mMeta->findData(kKeyAVCC, &type, &data, &size) &&
+ !mMeta->findData(kKeyHVCC, &type, &data, &size)) {
+ ALOGE("Failed: No HVCC/AVCC for Dolby Vision ..\n");
+ return;
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
@@ -2652,6 +2682,11 @@
free(mCodecSpecificData);
mCodecSpecificData = NULL;
}
+
+ if (mDoviConfigData != NULL) {
+ free(mDoviConfigData);
+ mDoviConfigData = NULL;
+ }
}
void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
@@ -3330,6 +3365,37 @@
return OK;
}
+status_t MPEG4Writer::Track::makeDoviCodecSpecificData() {
+ uint32_t type;
+ const void *data = NULL;
+ size_t size = 0;
+
+ if (mDoviConfigData != NULL) {
+ ALOGE("Already have Dolby Vision codec specific data");
+ return OK;
+ }
+
+ if (!mMeta->findData(kKeyDVCC, &type, &data, &size)
+ && !mMeta->findData(kKeyDVVC, &type, &data, &size)
+ && !mMeta->findData(kKeyDVWC, &type, &data, &size)) {
+ ALOGE("Failed getting Dovi config for Dolby Vision %d", (int)size);
+ return ERROR_MALFORMED;
+ }
+
+ mDoviConfigData = malloc(size);
+ if (mDoviConfigData == NULL) {
+ ALOGE("Failed allocating Dolby Vision config data");
+ return ERROR_MALFORMED;
+ }
+
+ mDoviConfigDataSize = size;
+ memcpy(mDoviConfigData, data, size);
+
+ mDoviProfile = (((char *)data)[2] >> 1) & 0x7f; //getting profile info
+
+ return OK;
+}
+
/*
* Updates the drift time from the audio track so that
* the video track can get the updated drift time information
@@ -3475,6 +3541,23 @@
err = copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
buffer->range_length());
}
+ if (mIsDovi) {
+ err = makeDoviCodecSpecificData();
+
+ const void *data = NULL;
+ size_t size = 0;
+
+ uint32_t type = 0;
+ if (mDoviProfile == 9){
+ mMeta->findData(kKeyAVCC, &type, &data, &size);
+ } else if (mDoviProfile < 9) {
+ mMeta->findData(kKeyHVCC, &type, &data, &size);
+ }
+
+ if (data != NULL && copyCodecSpecificData((uint8_t *)data, size) == OK) {
+ mGotAllCodecSpecificData = true;
+ }
+ }
}
buffer->release();
@@ -4174,6 +4257,7 @@
!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, mime) ||
!strcasecmp(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, mime)) {
if (!mCodecSpecificData ||
mCodecSpecificDataSize <= 0) {
@@ -4298,7 +4382,13 @@
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
CHECK(success);
- const char *fourcc = getFourCCForMime(mime);
+ const char *fourcc;
+ if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION)) {
+ fourcc = getDoviFourCC();
+ } else {
+ fourcc = getFourCCForMime(mime);
+ }
+
if (fourcc == NULL) {
ALOGE("Unknown mime type '%s'.", mime);
TRESPASS();
@@ -4338,6 +4428,13 @@
writeAvccBox();
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_HEVC, mime)) {
writeHvccBox();
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, mime)) {
+ if (mDoviProfile <= 8) {
+ writeHvccBox();
+ } else if (mDoviProfile == 9 || mDoviProfile == 32) {
+ writeAvccBox();
+ }
+ writeDoviConfigBox();
}
writePaspBox();
@@ -4879,12 +4976,11 @@
mOwner->endBox(); // avcC
}
-
void MPEG4Writer::Track::writeHvccBox() {
CHECK(mCodecSpecificData);
CHECK_GE(mCodecSpecificDataSize, 5u);
- // Patch avcc's lengthSize field to match the number
+ // Patch hvcc's lengthSize field to match the number
// of bytes we use to indicate the size of a nal unit.
uint8_t *ptr = (uint8_t *)mCodecSpecificData;
ptr[21] = (ptr[21] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
@@ -4893,6 +4989,24 @@
mOwner->endBox(); // hvcC
}
+void MPEG4Writer::Track::writeDoviConfigBox() {
+ CHECK(mDoviConfigData);
+ CHECK_EQ(mDoviConfigDataSize, 24u);
+
+ uint8_t *ptr = (uint8_t *)mDoviConfigData;
+ uint8_t profile = (ptr[2] >> 1) & 0x7f;
+
+ if (profile > 10) {
+ mOwner->beginBox("dvwC");
+ } else if (profile > 7) {
+ mOwner->beginBox("dvvC");
+ } else {
+ mOwner->beginBox("dvcC");
+ }
+ mOwner->write(mDoviConfigData, mDoviConfigDataSize);
+ mOwner->endBox(); // dvwC/dvvC/dvcC
+}
+
void MPEG4Writer::Track::writeD263Box() {
mOwner->beginBox("d263");
mOwner->writeInt32(0); // vendor
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index a6df5bb..1854588 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -28,9 +28,6 @@
#include "include/HevcUtils.h"
#include <cutils/properties.h>
-#include <media/openmax/OMX_Audio.h>
-#include <media/openmax/OMX_Video.h>
-#include <media/openmax/OMX_VideoExt.h>
#include <media/stagefright/CodecBase.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -57,6 +54,14 @@
#define AMEDIAFORMAT_KEY_MPEGH_COMPATIBLE_SETS \
"mpegh-compatible-sets"
+namespace {
+ // TODO: this should possibly be handled in an else
+ constexpr static int32_t AACObjectNull = 0;
+
+ // TODO: decide if we should just not transmit the level in this case
+ constexpr static int32_t DolbyVisionLevelUnknown = 0;
+}
+
namespace android {
static status_t copyNALUToABuffer(sp<ABuffer> *buffer, const uint8_t *ptr, size_t length) {
@@ -156,21 +161,22 @@
audioObjectType >>= 11;
}
- const static ALookup<uint16_t, OMX_AUDIO_AACPROFILETYPE> profiles {
- { 1, OMX_AUDIO_AACObjectMain },
- { 2, OMX_AUDIO_AACObjectLC },
- { 3, OMX_AUDIO_AACObjectSSR },
- { 4, OMX_AUDIO_AACObjectLTP },
- { 5, OMX_AUDIO_AACObjectHE },
- { 6, OMX_AUDIO_AACObjectScalable },
- { 17, OMX_AUDIO_AACObjectERLC },
- { 23, OMX_AUDIO_AACObjectLD },
- { 29, OMX_AUDIO_AACObjectHE_PS },
- { 39, OMX_AUDIO_AACObjectELD },
- { 42, OMX_AUDIO_AACObjectXHE },
+
+ const static ALookup<uint16_t, int32_t> profiles {
+ { 1, AACObjectMain },
+ { 2, AACObjectLC },
+ { 3, AACObjectSSR },
+ { 4, AACObjectLTP },
+ { 5, AACObjectHE },
+ { 6, AACObjectScalable },
+ { 17, AACObjectERLC },
+ { 23, AACObjectLD },
+ { 29, AACObjectHE_PS },
+ { 39, AACObjectELD },
+ { 42, AACObjectXHE },
};
- OMX_AUDIO_AACPROFILETYPE profile;
+ int32_t profile;
if (profiles.map(audioObjectType, &profile)) {
format->setInt32("profile", profile);
}
@@ -184,53 +190,53 @@
const uint8_t constraints = ptr[2];
const uint8_t level = ptr[3];
- const static ALookup<uint8_t, OMX_VIDEO_AVCLEVELTYPE> levels {
- { 9, OMX_VIDEO_AVCLevel1b }, // technically, 9 is only used for High+ profiles
- { 10, OMX_VIDEO_AVCLevel1 },
- { 11, OMX_VIDEO_AVCLevel11 }, // prefer level 1.1 for the value 11
- { 11, OMX_VIDEO_AVCLevel1b },
- { 12, OMX_VIDEO_AVCLevel12 },
- { 13, OMX_VIDEO_AVCLevel13 },
- { 20, OMX_VIDEO_AVCLevel2 },
- { 21, OMX_VIDEO_AVCLevel21 },
- { 22, OMX_VIDEO_AVCLevel22 },
- { 30, OMX_VIDEO_AVCLevel3 },
- { 31, OMX_VIDEO_AVCLevel31 },
- { 32, OMX_VIDEO_AVCLevel32 },
- { 40, OMX_VIDEO_AVCLevel4 },
- { 41, OMX_VIDEO_AVCLevel41 },
- { 42, OMX_VIDEO_AVCLevel42 },
- { 50, OMX_VIDEO_AVCLevel5 },
- { 51, OMX_VIDEO_AVCLevel51 },
- { 52, OMX_VIDEO_AVCLevel52 },
- { 60, OMX_VIDEO_AVCLevel6 },
- { 61, OMX_VIDEO_AVCLevel61 },
- { 62, OMX_VIDEO_AVCLevel62 },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 9, AVCLevel1b }, // technically, 9 is only used for High+ profiles
+ { 10, AVCLevel1 },
+ { 11, AVCLevel11 }, // prefer level 1.1 for the value 11
+ { 11, AVCLevel1b },
+ { 12, AVCLevel12 },
+ { 13, AVCLevel13 },
+ { 20, AVCLevel2 },
+ { 21, AVCLevel21 },
+ { 22, AVCLevel22 },
+ { 30, AVCLevel3 },
+ { 31, AVCLevel31 },
+ { 32, AVCLevel32 },
+ { 40, AVCLevel4 },
+ { 41, AVCLevel41 },
+ { 42, AVCLevel42 },
+ { 50, AVCLevel5 },
+ { 51, AVCLevel51 },
+ { 52, AVCLevel52 },
+ { 60, AVCLevel6 },
+ { 61, AVCLevel61 },
+ { 62, AVCLevel62 },
};
- const static ALookup<uint8_t, OMX_VIDEO_AVCPROFILETYPE> profiles {
- { 66, OMX_VIDEO_AVCProfileBaseline },
- { 77, OMX_VIDEO_AVCProfileMain },
- { 88, OMX_VIDEO_AVCProfileExtended },
- { 100, OMX_VIDEO_AVCProfileHigh },
- { 110, OMX_VIDEO_AVCProfileHigh10 },
- { 122, OMX_VIDEO_AVCProfileHigh422 },
- { 244, OMX_VIDEO_AVCProfileHigh444 },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 66, AVCProfileBaseline },
+ { 77, AVCProfileMain },
+ { 88, AVCProfileExtended },
+ { 100, AVCProfileHigh },
+ { 110, AVCProfileHigh10 },
+ { 122, AVCProfileHigh422 },
+ { 244, AVCProfileHigh444 },
};
// set profile & level if they are recognized
- OMX_VIDEO_AVCPROFILETYPE codecProfile;
- OMX_VIDEO_AVCLEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (profiles.map(profile, &codecProfile)) {
if (profile == 66 && (constraints & 0x40)) {
- codecProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline;
+ codecProfile = AVCProfileConstrainedBaseline;
} else if (profile == 100 && (constraints & 0x0C) == 0x0C) {
- codecProfile = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedHigh;
+ codecProfile = AVCProfileConstrainedHigh;
}
format->setInt32("profile", codecProfile);
if (levels.map(level, &codecLevel)) {
// for 9 && 11 decide level based on profile and constraint_set3 flag
if (level == 11 && (profile == 66 || profile == 77 || profile == 88)) {
- codecLevel = (constraints & 0x10) ? OMX_VIDEO_AVCLevel1b : OMX_VIDEO_AVCLevel11;
+ codecLevel = (constraints & 0x10) ? AVCLevel1b : AVCLevel11;
}
format->setInt32("level", codecLevel);
}
@@ -256,41 +262,44 @@
// All Dolby Profiles will have profile and level info in MediaFormat
// Profile 8 and 9 will have bl_compatibility_id too.
- const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONPROFILETYPE> profiles{
- {1, OMX_VIDEO_DolbyVisionProfileDvavPen},
- {3, OMX_VIDEO_DolbyVisionProfileDvheDen},
- {4, OMX_VIDEO_DolbyVisionProfileDvheDtr},
- {5, OMX_VIDEO_DolbyVisionProfileDvheStn},
- {6, OMX_VIDEO_DolbyVisionProfileDvheDth},
- {7, OMX_VIDEO_DolbyVisionProfileDvheDtb},
- {8, OMX_VIDEO_DolbyVisionProfileDvheSt},
- {9, OMX_VIDEO_DolbyVisionProfileDvavSe},
- {10, OMX_VIDEO_DolbyVisionProfileDvav110},
+ const static ALookup<uint8_t, int32_t> profiles{
+ {1, DolbyVisionProfileDvavPen},
+ {3, DolbyVisionProfileDvheDen},
+ {4, DolbyVisionProfileDvheDtr},
+ {5, DolbyVisionProfileDvheStn},
+ {6, DolbyVisionProfileDvheDth},
+ {7, DolbyVisionProfileDvheDtb},
+ {8, DolbyVisionProfileDvheSt},
+ {9, DolbyVisionProfileDvavSe},
+ {10, DolbyVisionProfileDvav110},
};
- const static ALookup<uint8_t, OMX_VIDEO_DOLBYVISIONLEVELTYPE> levels{
- {0, OMX_VIDEO_DolbyVisionLevelUnknown},
- {1, OMX_VIDEO_DolbyVisionLevelHd24},
- {2, OMX_VIDEO_DolbyVisionLevelHd30},
- {3, OMX_VIDEO_DolbyVisionLevelFhd24},
- {4, OMX_VIDEO_DolbyVisionLevelFhd30},
- {5, OMX_VIDEO_DolbyVisionLevelFhd60},
- {6, OMX_VIDEO_DolbyVisionLevelUhd24},
- {7, OMX_VIDEO_DolbyVisionLevelUhd30},
- {8, OMX_VIDEO_DolbyVisionLevelUhd48},
- {9, OMX_VIDEO_DolbyVisionLevelUhd60},
+ const static ALookup<uint8_t, int32_t> levels{
+ {0, DolbyVisionLevelUnknown},
+ {1, DolbyVisionLevelHd24},
+ {2, DolbyVisionLevelHd30},
+ {3, DolbyVisionLevelFhd24},
+ {4, DolbyVisionLevelFhd30},
+ {5, DolbyVisionLevelFhd60},
+ {6, DolbyVisionLevelUhd24},
+ {7, DolbyVisionLevelUhd30},
+ {8, DolbyVisionLevelUhd48},
+ {9, DolbyVisionLevelUhd60},
+ {10, DolbyVisionLevelUhd120},
+ {11, DolbyVisionLevel8k30},
+ {12, DolbyVisionLevel8k60},
};
// set rpuAssoc
if (rpu_present_flag && el_present_flag && !bl_present_flag) {
format->setInt32("rpuAssoc", 1);
}
// set profile & level if they are recognized
- OMX_VIDEO_DOLBYVISIONPROFILETYPE codecProfile;
- OMX_VIDEO_DOLBYVISIONLEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (profiles.map(profile, &codecProfile)) {
format->setInt32("profile", codecProfile);
- if (codecProfile == OMX_VIDEO_DolbyVisionProfileDvheSt ||
- codecProfile == OMX_VIDEO_DolbyVisionProfileDvavSe) {
+ if (codecProfile == DolbyVisionProfileDvheSt ||
+ codecProfile == DolbyVisionProfileDvavSe) {
format->setInt32("bl_compatibility_id", bl_compatibility_id);
}
if (levels.map(level, &codecLevel)) {
@@ -307,32 +316,32 @@
const uint8_t profile = ptr[6];
const uint8_t level = ptr[5];
- const static ALookup<uint8_t, OMX_VIDEO_H263PROFILETYPE> profiles {
- { 0, OMX_VIDEO_H263ProfileBaseline },
- { 1, OMX_VIDEO_H263ProfileH320Coding },
- { 2, OMX_VIDEO_H263ProfileBackwardCompatible },
- { 3, OMX_VIDEO_H263ProfileISWV2 },
- { 4, OMX_VIDEO_H263ProfileISWV3 },
- { 5, OMX_VIDEO_H263ProfileHighCompression },
- { 6, OMX_VIDEO_H263ProfileInternet },
- { 7, OMX_VIDEO_H263ProfileInterlace },
- { 8, OMX_VIDEO_H263ProfileHighLatency },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 0, H263ProfileBaseline },
+ { 1, H263ProfileH320Coding },
+ { 2, H263ProfileBackwardCompatible },
+ { 3, H263ProfileISWV2 },
+ { 4, H263ProfileISWV3 },
+ { 5, H263ProfileHighCompression },
+ { 6, H263ProfileInternet },
+ { 7, H263ProfileInterlace },
+ { 8, H263ProfileHighLatency },
};
- const static ALookup<uint8_t, OMX_VIDEO_H263LEVELTYPE> levels {
- { 10, OMX_VIDEO_H263Level10 },
- { 20, OMX_VIDEO_H263Level20 },
- { 30, OMX_VIDEO_H263Level30 },
- { 40, OMX_VIDEO_H263Level40 },
- { 45, OMX_VIDEO_H263Level45 },
- { 50, OMX_VIDEO_H263Level50 },
- { 60, OMX_VIDEO_H263Level60 },
- { 70, OMX_VIDEO_H263Level70 },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 10, H263Level10 },
+ { 20, H263Level20 },
+ { 30, H263Level30 },
+ { 40, H263Level40 },
+ { 45, H263Level45 },
+ { 50, H263Level50 },
+ { 60, H263Level60 },
+ { 70, H263Level70 },
};
// set profile & level if they are recognized
- OMX_VIDEO_H263PROFILETYPE codecProfile;
- OMX_VIDEO_H263LEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (profiles.map(profile, &codecProfile)) {
format->setInt32("profile", codecProfile);
if (levels.map(level, &codecLevel)) {
@@ -350,59 +359,59 @@
const uint8_t tier = (ptr[1] & 0x20) >> 5;
const uint8_t level = ptr[12];
- const static ALookup<std::pair<uint8_t, uint8_t>, OMX_VIDEO_HEVCLEVELTYPE> levels {
- { { 0, 30 }, OMX_VIDEO_HEVCMainTierLevel1 },
- { { 0, 60 }, OMX_VIDEO_HEVCMainTierLevel2 },
- { { 0, 63 }, OMX_VIDEO_HEVCMainTierLevel21 },
- { { 0, 90 }, OMX_VIDEO_HEVCMainTierLevel3 },
- { { 0, 93 }, OMX_VIDEO_HEVCMainTierLevel31 },
- { { 0, 120 }, OMX_VIDEO_HEVCMainTierLevel4 },
- { { 0, 123 }, OMX_VIDEO_HEVCMainTierLevel41 },
- { { 0, 150 }, OMX_VIDEO_HEVCMainTierLevel5 },
- { { 0, 153 }, OMX_VIDEO_HEVCMainTierLevel51 },
- { { 0, 156 }, OMX_VIDEO_HEVCMainTierLevel52 },
- { { 0, 180 }, OMX_VIDEO_HEVCMainTierLevel6 },
- { { 0, 183 }, OMX_VIDEO_HEVCMainTierLevel61 },
- { { 0, 186 }, OMX_VIDEO_HEVCMainTierLevel62 },
- { { 1, 30 }, OMX_VIDEO_HEVCHighTierLevel1 },
- { { 1, 60 }, OMX_VIDEO_HEVCHighTierLevel2 },
- { { 1, 63 }, OMX_VIDEO_HEVCHighTierLevel21 },
- { { 1, 90 }, OMX_VIDEO_HEVCHighTierLevel3 },
- { { 1, 93 }, OMX_VIDEO_HEVCHighTierLevel31 },
- { { 1, 120 }, OMX_VIDEO_HEVCHighTierLevel4 },
- { { 1, 123 }, OMX_VIDEO_HEVCHighTierLevel41 },
- { { 1, 150 }, OMX_VIDEO_HEVCHighTierLevel5 },
- { { 1, 153 }, OMX_VIDEO_HEVCHighTierLevel51 },
- { { 1, 156 }, OMX_VIDEO_HEVCHighTierLevel52 },
- { { 1, 180 }, OMX_VIDEO_HEVCHighTierLevel6 },
- { { 1, 183 }, OMX_VIDEO_HEVCHighTierLevel61 },
- { { 1, 186 }, OMX_VIDEO_HEVCHighTierLevel62 },
+ const static ALookup<std::pair<uint8_t, uint8_t>, int32_t> levels {
+ { { 0, 30 }, HEVCMainTierLevel1 },
+ { { 0, 60 }, HEVCMainTierLevel2 },
+ { { 0, 63 }, HEVCMainTierLevel21 },
+ { { 0, 90 }, HEVCMainTierLevel3 },
+ { { 0, 93 }, HEVCMainTierLevel31 },
+ { { 0, 120 }, HEVCMainTierLevel4 },
+ { { 0, 123 }, HEVCMainTierLevel41 },
+ { { 0, 150 }, HEVCMainTierLevel5 },
+ { { 0, 153 }, HEVCMainTierLevel51 },
+ { { 0, 156 }, HEVCMainTierLevel52 },
+ { { 0, 180 }, HEVCMainTierLevel6 },
+ { { 0, 183 }, HEVCMainTierLevel61 },
+ { { 0, 186 }, HEVCMainTierLevel62 },
+ { { 1, 30 }, HEVCHighTierLevel1 },
+ { { 1, 60 }, HEVCHighTierLevel2 },
+ { { 1, 63 }, HEVCHighTierLevel21 },
+ { { 1, 90 }, HEVCHighTierLevel3 },
+ { { 1, 93 }, HEVCHighTierLevel31 },
+ { { 1, 120 }, HEVCHighTierLevel4 },
+ { { 1, 123 }, HEVCHighTierLevel41 },
+ { { 1, 150 }, HEVCHighTierLevel5 },
+ { { 1, 153 }, HEVCHighTierLevel51 },
+ { { 1, 156 }, HEVCHighTierLevel52 },
+ { { 1, 180 }, HEVCHighTierLevel6 },
+ { { 1, 183 }, HEVCHighTierLevel61 },
+ { { 1, 186 }, HEVCHighTierLevel62 },
};
- const static ALookup<uint8_t, OMX_VIDEO_HEVCPROFILETYPE> profiles {
- { 1, OMX_VIDEO_HEVCProfileMain },
- { 2, OMX_VIDEO_HEVCProfileMain10 },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 1, HEVCProfileMain },
+ { 2, HEVCProfileMain10 },
// use Main for Main Still Picture decoding
- { 3, OMX_VIDEO_HEVCProfileMain },
+ { 3, HEVCProfileMain },
};
// set profile & level if they are recognized
- OMX_VIDEO_HEVCPROFILETYPE codecProfile;
- OMX_VIDEO_HEVCLEVELTYPE codecLevel;
+ int32_t codecProfile;
+ int32_t codecLevel;
if (!profiles.map(profile, &codecProfile)) {
if (ptr[2] & 0x40 /* general compatibility flag 1 */) {
// Note that this case covers Main Still Picture too
- codecProfile = OMX_VIDEO_HEVCProfileMain;
+ codecProfile = HEVCProfileMain;
} else if (ptr[2] & 0x20 /* general compatibility flag 2 */) {
- codecProfile = OMX_VIDEO_HEVCProfileMain10;
+ codecProfile = HEVCProfileMain10;
} else {
return;
}
}
// bump to HDR profile
- if (isHdr(format) && codecProfile == OMX_VIDEO_HEVCProfileMain10) {
- codecProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
+ if (isHdr(format) && codecProfile == HEVCProfileMain10) {
+ codecProfile = HEVCProfileMain10HDR10;
}
format->setInt32("profile", codecProfile);
@@ -422,36 +431,36 @@
}
const uint8_t indication = ((seq[4] & 0xF) << 4) | ((seq[5] & 0xF0) >> 4);
- const static ALookup<uint8_t, OMX_VIDEO_MPEG2PROFILETYPE> profiles {
- { 0x50, OMX_VIDEO_MPEG2ProfileSimple },
- { 0x40, OMX_VIDEO_MPEG2ProfileMain },
- { 0x30, OMX_VIDEO_MPEG2ProfileSNR },
- { 0x20, OMX_VIDEO_MPEG2ProfileSpatial },
- { 0x10, OMX_VIDEO_MPEG2ProfileHigh },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 0x50, MPEG2ProfileSimple },
+ { 0x40, MPEG2ProfileMain },
+ { 0x30, MPEG2ProfileSNR },
+ { 0x20, MPEG2ProfileSpatial },
+ { 0x10, MPEG2ProfileHigh },
};
- const static ALookup<uint8_t, OMX_VIDEO_MPEG2LEVELTYPE> levels {
- { 0x0A, OMX_VIDEO_MPEG2LevelLL },
- { 0x08, OMX_VIDEO_MPEG2LevelML },
- { 0x06, OMX_VIDEO_MPEG2LevelH14 },
- { 0x04, OMX_VIDEO_MPEG2LevelHL },
- { 0x02, OMX_VIDEO_MPEG2LevelHP },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 0x0A, MPEG2LevelLL },
+ { 0x08, MPEG2LevelML },
+ { 0x06, MPEG2LevelH14 },
+ { 0x04, MPEG2LevelHL },
+ { 0x02, MPEG2LevelHP },
};
const static ALookup<uint8_t,
- std::pair<OMX_VIDEO_MPEG2PROFILETYPE, OMX_VIDEO_MPEG2LEVELTYPE>> escapes {
+ std::pair<int32_t, int32_t>> escapes {
/* unsupported
- { 0x8E, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelLL } },
- { 0x8D, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelML } },
- { 0x8B, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelH14 } },
- { 0x8A, { XXX_MPEG2ProfileMultiView, OMX_VIDEO_MPEG2LevelHL } }, */
- { 0x85, { OMX_VIDEO_MPEG2Profile422, OMX_VIDEO_MPEG2LevelML } },
- { 0x82, { OMX_VIDEO_MPEG2Profile422, OMX_VIDEO_MPEG2LevelHL } },
+ { 0x8E, { XXX_MPEG2ProfileMultiView, MPEG2LevelLL } },
+ { 0x8D, { XXX_MPEG2ProfileMultiView, MPEG2LevelML } },
+ { 0x8B, { XXX_MPEG2ProfileMultiView, MPEG2LevelH14 } },
+ { 0x8A, { XXX_MPEG2ProfileMultiView, MPEG2LevelHL } }, */
+ { 0x85, { MPEG2Profile422, MPEG2LevelML } },
+ { 0x82, { MPEG2Profile422, MPEG2LevelHL } },
};
- OMX_VIDEO_MPEG2PROFILETYPE profile;
- OMX_VIDEO_MPEG2LEVELTYPE level;
- std::pair<OMX_VIDEO_MPEG2PROFILETYPE, OMX_VIDEO_MPEG2LEVELTYPE> profileLevel;
+ int32_t profile;
+ int32_t level;
+ std::pair<int32_t, int32_t> profileLevel;
if (escapes.map(indication, &profileLevel)) {
format->setInt32("profile", profileLevel.first);
format->setInt32("level", profileLevel.second);
@@ -468,16 +477,16 @@
// esds seems to only contain the profile for MPEG-2
uint8_t objType;
if (esds.getObjectTypeIndication(&objType) == OK) {
- const static ALookup<uint8_t, OMX_VIDEO_MPEG2PROFILETYPE> profiles{
- { 0x60, OMX_VIDEO_MPEG2ProfileSimple },
- { 0x61, OMX_VIDEO_MPEG2ProfileMain },
- { 0x62, OMX_VIDEO_MPEG2ProfileSNR },
- { 0x63, OMX_VIDEO_MPEG2ProfileSpatial },
- { 0x64, OMX_VIDEO_MPEG2ProfileHigh },
- { 0x65, OMX_VIDEO_MPEG2Profile422 },
+ const static ALookup<uint8_t, int32_t> profiles{
+ { 0x60, MPEG2ProfileSimple },
+ { 0x61, MPEG2ProfileMain },
+ { 0x62, MPEG2ProfileSNR },
+ { 0x63, MPEG2ProfileSpatial },
+ { 0x64, MPEG2ProfileHigh },
+ { 0x65, MPEG2Profile422 },
};
- OMX_VIDEO_MPEG2PROFILETYPE profile;
+ int32_t profile;
if (profiles.map(objType, &profile)) {
format->setInt32("profile", profile);
}
@@ -492,82 +501,82 @@
const uint8_t indication = seq[4];
const static ALookup<uint8_t,
- std::pair<OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_MPEG4LEVELTYPE>> table {
- { 0b00000001, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 } },
- { 0b00000010, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 } },
- { 0b00000011, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 } },
- { 0b00000100, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level4a } },
- { 0b00000101, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level5 } },
- { 0b00000110, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level6 } },
- { 0b00001000, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 } },
- { 0b00001001, { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b } },
- { 0b00010000, { OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_MPEG4Level0 } },
- { 0b00010001, { OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b00010010, { OMX_VIDEO_MPEG4ProfileSimpleScalable, OMX_VIDEO_MPEG4Level2 } },
+ std::pair<int32_t, int32_t>> table {
+ { 0b00000001, { MPEG4ProfileSimple, MPEG4Level1 } },
+ { 0b00000010, { MPEG4ProfileSimple, MPEG4Level2 } },
+ { 0b00000011, { MPEG4ProfileSimple, MPEG4Level3 } },
+ { 0b00000100, { MPEG4ProfileSimple, MPEG4Level4a } },
+ { 0b00000101, { MPEG4ProfileSimple, MPEG4Level5 } },
+ { 0b00000110, { MPEG4ProfileSimple, MPEG4Level6 } },
+ { 0b00001000, { MPEG4ProfileSimple, MPEG4Level0 } },
+ { 0b00001001, { MPEG4ProfileSimple, MPEG4Level0b } },
+ { 0b00010000, { MPEG4ProfileSimpleScalable, MPEG4Level0 } },
+ { 0b00010001, { MPEG4ProfileSimpleScalable, MPEG4Level1 } },
+ { 0b00010010, { MPEG4ProfileSimpleScalable, MPEG4Level2 } },
/* unsupported
- { 0b00011101, { XXX_MPEG4ProfileSimpleScalableER, OMX_VIDEO_MPEG4Level0 } },
- { 0b00011110, { XXX_MPEG4ProfileSimpleScalableER, OMX_VIDEO_MPEG4Level1 } },
- { 0b00011111, { XXX_MPEG4ProfileSimpleScalableER, OMX_VIDEO_MPEG4Level2 } }, */
- { 0b00100001, { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level1 } },
- { 0b00100010, { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 } },
- { 0b00110010, { OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_MPEG4Level2 } },
- { 0b00110011, { OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_MPEG4Level3 } },
- { 0b00110100, { OMX_VIDEO_MPEG4ProfileMain, OMX_VIDEO_MPEG4Level4 } },
+ { 0b00011101, { XXX_MPEG4ProfileSimpleScalableER, MPEG4Level0 } },
+ { 0b00011110, { XXX_MPEG4ProfileSimpleScalableER, MPEG4Level1 } },
+ { 0b00011111, { XXX_MPEG4ProfileSimpleScalableER, MPEG4Level2 } }, */
+ { 0b00100001, { MPEG4ProfileCore, MPEG4Level1 } },
+ { 0b00100010, { MPEG4ProfileCore, MPEG4Level2 } },
+ { 0b00110010, { MPEG4ProfileMain, MPEG4Level2 } },
+ { 0b00110011, { MPEG4ProfileMain, MPEG4Level3 } },
+ { 0b00110100, { MPEG4ProfileMain, MPEG4Level4 } },
/* deprecated
- { 0b01000010, { OMX_VIDEO_MPEG4ProfileNbit, OMX_VIDEO_MPEG4Level2 } }, */
- { 0b01010001, { OMX_VIDEO_MPEG4ProfileScalableTexture, OMX_VIDEO_MPEG4Level1 } },
- { 0b01100001, { OMX_VIDEO_MPEG4ProfileSimpleFace, OMX_VIDEO_MPEG4Level1 } },
- { 0b01100010, { OMX_VIDEO_MPEG4ProfileSimpleFace, OMX_VIDEO_MPEG4Level2 } },
- { 0b01100011, { OMX_VIDEO_MPEG4ProfileSimpleFBA, OMX_VIDEO_MPEG4Level1 } },
- { 0b01100100, { OMX_VIDEO_MPEG4ProfileSimpleFBA, OMX_VIDEO_MPEG4Level2 } },
- { 0b01110001, { OMX_VIDEO_MPEG4ProfileBasicAnimated, OMX_VIDEO_MPEG4Level1 } },
- { 0b01110010, { OMX_VIDEO_MPEG4ProfileBasicAnimated, OMX_VIDEO_MPEG4Level2 } },
- { 0b10000001, { OMX_VIDEO_MPEG4ProfileHybrid, OMX_VIDEO_MPEG4Level1 } },
- { 0b10000010, { OMX_VIDEO_MPEG4ProfileHybrid, OMX_VIDEO_MPEG4Level2 } },
- { 0b10010001, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level1 } },
- { 0b10010010, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level2 } },
- { 0b10010011, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level3 } },
- { 0b10010100, { OMX_VIDEO_MPEG4ProfileAdvancedRealTime, OMX_VIDEO_MPEG4Level4 } },
- { 0b10100001, { OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b10100010, { OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_MPEG4Level2 } },
- { 0b10100011, { OMX_VIDEO_MPEG4ProfileCoreScalable, OMX_VIDEO_MPEG4Level3 } },
- { 0b10110001, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level1 } },
- { 0b10110010, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level2 } },
- { 0b10110011, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level3 } },
- { 0b10110100, { OMX_VIDEO_MPEG4ProfileAdvancedCoding, OMX_VIDEO_MPEG4Level4 } },
- { 0b11000001, { OMX_VIDEO_MPEG4ProfileAdvancedCore, OMX_VIDEO_MPEG4Level1 } },
- { 0b11000010, { OMX_VIDEO_MPEG4ProfileAdvancedCore, OMX_VIDEO_MPEG4Level2 } },
- { 0b11010001, { OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b11010010, { OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_MPEG4Level2 } },
- { 0b11010011, { OMX_VIDEO_MPEG4ProfileAdvancedScalable, OMX_VIDEO_MPEG4Level3 } },
+ { 0b01000010, { MPEG4ProfileNbit, MPEG4Level2 } }, */
+ { 0b01010001, { MPEG4ProfileScalableTexture, MPEG4Level1 } },
+ { 0b01100001, { MPEG4ProfileSimpleFace, MPEG4Level1 } },
+ { 0b01100010, { MPEG4ProfileSimpleFace, MPEG4Level2 } },
+ { 0b01100011, { MPEG4ProfileSimpleFBA, MPEG4Level1 } },
+ { 0b01100100, { MPEG4ProfileSimpleFBA, MPEG4Level2 } },
+ { 0b01110001, { MPEG4ProfileBasicAnimated, MPEG4Level1 } },
+ { 0b01110010, { MPEG4ProfileBasicAnimated, MPEG4Level2 } },
+ { 0b10000001, { MPEG4ProfileHybrid, MPEG4Level1 } },
+ { 0b10000010, { MPEG4ProfileHybrid, MPEG4Level2 } },
+ { 0b10010001, { MPEG4ProfileAdvancedRealTime, MPEG4Level1 } },
+ { 0b10010010, { MPEG4ProfileAdvancedRealTime, MPEG4Level2 } },
+ { 0b10010011, { MPEG4ProfileAdvancedRealTime, MPEG4Level3 } },
+ { 0b10010100, { MPEG4ProfileAdvancedRealTime, MPEG4Level4 } },
+ { 0b10100001, { MPEG4ProfileCoreScalable, MPEG4Level1 } },
+ { 0b10100010, { MPEG4ProfileCoreScalable, MPEG4Level2 } },
+ { 0b10100011, { MPEG4ProfileCoreScalable, MPEG4Level3 } },
+ { 0b10110001, { MPEG4ProfileAdvancedCoding, MPEG4Level1 } },
+ { 0b10110010, { MPEG4ProfileAdvancedCoding, MPEG4Level2 } },
+ { 0b10110011, { MPEG4ProfileAdvancedCoding, MPEG4Level3 } },
+ { 0b10110100, { MPEG4ProfileAdvancedCoding, MPEG4Level4 } },
+ { 0b11000001, { MPEG4ProfileAdvancedCore, MPEG4Level1 } },
+ { 0b11000010, { MPEG4ProfileAdvancedCore, MPEG4Level2 } },
+ { 0b11010001, { MPEG4ProfileAdvancedScalable, MPEG4Level1 } },
+ { 0b11010010, { MPEG4ProfileAdvancedScalable, MPEG4Level2 } },
+ { 0b11010011, { MPEG4ProfileAdvancedScalable, MPEG4Level3 } },
/* unsupported
- { 0b11100001, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level1 } },
- { 0b11100010, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level2 } },
- { 0b11100011, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level3 } },
- { 0b11100100, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level4 } },
- { 0b11100101, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level1 } },
- { 0b11100110, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level2 } },
- { 0b11100111, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level3 } },
- { 0b11101000, { XXX_MPEG4ProfileCoreStudio, OMX_VIDEO_MPEG4Level4 } },
- { 0b11101011, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level5 } },
- { 0b11101100, { XXX_MPEG4ProfileSimpleStudio, OMX_VIDEO_MPEG4Level6 } }, */
- { 0b11110000, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level0 } },
- { 0b11110001, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level1 } },
- { 0b11110010, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level2 } },
- { 0b11110011, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level3 } },
- { 0b11110100, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level4 } },
- { 0b11110101, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level5 } },
- { 0b11110111, { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level3b } },
+ { 0b11100001, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level1 } },
+ { 0b11100010, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level2 } },
+ { 0b11100011, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level3 } },
+ { 0b11100100, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level4 } },
+ { 0b11100101, { XXX_MPEG4ProfileCoreStudio, MPEG4Level1 } },
+ { 0b11100110, { XXX_MPEG4ProfileCoreStudio, MPEG4Level2 } },
+ { 0b11100111, { XXX_MPEG4ProfileCoreStudio, MPEG4Level3 } },
+ { 0b11101000, { XXX_MPEG4ProfileCoreStudio, MPEG4Level4 } },
+ { 0b11101011, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level5 } },
+ { 0b11101100, { XXX_MPEG4ProfileSimpleStudio, MPEG4Level6 } }, */
+ { 0b11110000, { MPEG4ProfileAdvancedSimple, MPEG4Level0 } },
+ { 0b11110001, { MPEG4ProfileAdvancedSimple, MPEG4Level1 } },
+ { 0b11110010, { MPEG4ProfileAdvancedSimple, MPEG4Level2 } },
+ { 0b11110011, { MPEG4ProfileAdvancedSimple, MPEG4Level3 } },
+ { 0b11110100, { MPEG4ProfileAdvancedSimple, MPEG4Level4 } },
+ { 0b11110101, { MPEG4ProfileAdvancedSimple, MPEG4Level5 } },
+ { 0b11110111, { MPEG4ProfileAdvancedSimple, MPEG4Level3b } },
/* deprecated
- { 0b11111000, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level0 } },
- { 0b11111001, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level1 } },
- { 0b11111010, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level2 } },
- { 0b11111011, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level3 } },
- { 0b11111100, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level4 } },
- { 0b11111101, { XXX_MPEG4ProfileFineGranularityScalable, OMX_VIDEO_MPEG4Level5 } }, */
+ { 0b11111000, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level0 } },
+ { 0b11111001, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level1 } },
+ { 0b11111010, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level2 } },
+ { 0b11111011, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level3 } },
+ { 0b11111100, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level4 } },
+ { 0b11111101, { XXX_MPEG4ProfileFineGranularityScalable, MPEG4Level5 } }, */
};
- std::pair<OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_MPEG4LEVELTYPE> profileLevel;
+ std::pair<int32_t, int32_t> profileLevel;
if (table.map(indication, &profileLevel)) {
format->setInt32("profile", profileLevel.first);
format->setInt32("level", profileLevel.second);
@@ -590,19 +599,19 @@
switch (id) {
case 1 /* profileId */:
if (length >= 1) {
- const static ALookup<uint8_t, OMX_VIDEO_VP9PROFILETYPE> profiles {
- { 0, OMX_VIDEO_VP9Profile0 },
- { 1, OMX_VIDEO_VP9Profile1 },
- { 2, OMX_VIDEO_VP9Profile2 },
- { 3, OMX_VIDEO_VP9Profile3 },
+ const static ALookup<uint8_t, int32_t> profiles {
+ { 0, VP9Profile0 },
+ { 1, VP9Profile1 },
+ { 2, VP9Profile2 },
+ { 3, VP9Profile3 },
};
- const static ALookup<OMX_VIDEO_VP9PROFILETYPE, OMX_VIDEO_VP9PROFILETYPE> toHdr {
- { OMX_VIDEO_VP9Profile2, OMX_VIDEO_VP9Profile2HDR },
- { OMX_VIDEO_VP9Profile3, OMX_VIDEO_VP9Profile3HDR },
+ const static ALookup<int32_t, int32_t> toHdr {
+ { VP9Profile2, VP9Profile2HDR },
+ { VP9Profile3, VP9Profile3HDR },
};
- OMX_VIDEO_VP9PROFILETYPE profile;
+ int32_t profile;
if (profiles.map(data[0], &profile)) {
// convert to HDR profile
if (isHdr(format)) {
@@ -615,24 +624,24 @@
break;
case 2 /* levelId */:
if (length >= 1) {
- const static ALookup<uint8_t, OMX_VIDEO_VP9LEVELTYPE> levels {
- { 10, OMX_VIDEO_VP9Level1 },
- { 11, OMX_VIDEO_VP9Level11 },
- { 20, OMX_VIDEO_VP9Level2 },
- { 21, OMX_VIDEO_VP9Level21 },
- { 30, OMX_VIDEO_VP9Level3 },
- { 31, OMX_VIDEO_VP9Level31 },
- { 40, OMX_VIDEO_VP9Level4 },
- { 41, OMX_VIDEO_VP9Level41 },
- { 50, OMX_VIDEO_VP9Level5 },
- { 51, OMX_VIDEO_VP9Level51 },
- { 52, OMX_VIDEO_VP9Level52 },
- { 60, OMX_VIDEO_VP9Level6 },
- { 61, OMX_VIDEO_VP9Level61 },
- { 62, OMX_VIDEO_VP9Level62 },
+ const static ALookup<uint8_t, int32_t> levels {
+ { 10, VP9Level1 },
+ { 11, VP9Level11 },
+ { 20, VP9Level2 },
+ { 21, VP9Level21 },
+ { 30, VP9Level3 },
+ { 31, VP9Level31 },
+ { 40, VP9Level4 },
+ { 41, VP9Level41 },
+ { 50, VP9Level5 },
+ { 51, VP9Level51 },
+ { 52, VP9Level52 },
+ { 60, VP9Level6 },
+ { 61, VP9Level61 },
+ { 62, VP9Level62 },
};
- OMX_VIDEO_VP9LEVELTYPE level;
+ int32_t level;
if (levels.map(data[0], &level)) {
format->setInt32("level", level);
}
@@ -1504,7 +1513,30 @@
msg->setBuffer("csd-0", buffer);
}
- if (meta->findData(kKeyDVCC, &type, &data, &size)) {
+ if (meta->findData(kKeyDVCC, &type, &data, &size)
+ || meta->findData(kKeyDVVC, &type, &data, &size)
+ || meta->findData(kKeyDVWC, &type, &data, &size)) {
+ sp<ABuffer> buffer, csdOrg;
+ if (msg->findBuffer("csd-0", &csdOrg)) {
+ buffer = new (std::nothrow) ABuffer(size + csdOrg->size());
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
+
+ memcpy(buffer->data(), csdOrg->data(), csdOrg->size());
+ memcpy(buffer->data() + csdOrg->size(), data, size);
+ } else {
+ buffer = new (std::nothrow) ABuffer(size);
+ if (buffer.get() == NULL || buffer->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(buffer->data(), data, size);
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ msg->setBuffer("csd-0", buffer);
+
const uint8_t *ptr = (const uint8_t *)data;
ALOGV("DV: calling parseDolbyVisionProfileLevelFromDvcc with data size %zu", size);
parseDolbyVisionProfileLevelFromDvcc(ptr, size, msg);
@@ -2009,30 +2041,134 @@
mime == MEDIA_MIMETYPE_IMAGE_AVIF) {
meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
} else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION) {
- if (msg->findBuffer("csd-2", &csd2)) {
- //dvcc should be 24
- if (csd2->size() == 24) {
- meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
- uint8_t *dvcc = csd2->data();
- const uint8_t profile = dvcc[2] >> 1;
- if (profile > 1 && profile < 9) {
+ int32_t needCreateDoviCSD = 0;
+ int32_t profile = 0;
+ uint8_t bl_compatibility = 0;
+ if (msg->findInt32("profile", &profile)) {
+ if (profile == DolbyVisionProfileDvheSt) {
+ profile = 8;
+ bl_compatibility = 4;
+ } else if (profile == DolbyVisionProfileDvavSe) {
+ profile = 9;
+ bl_compatibility = 2;
+ }
+ if (profile == 8 || profile == 9) {
+ needCreateDoviCSD = 1;
+ }
+ } else {
+ ALOGW("did not find dolby vision profile");
+ }
+ // No dovi csd data, need to create it
+ if (needCreateDoviCSD) {
+ uint8_t dvcc[24];
+ int32_t level = 0;
+ uint8_t level_val = 0;
+
+ if (msg->findInt32("level", &level)) {
+ const static ALookup<int32_t, uint8_t> levels {
+ {DolbyVisionLevelUnknown, 0},
+ {DolbyVisionLevelHd24, 1},
+ {DolbyVisionLevelHd30, 2},
+ {DolbyVisionLevelFhd24, 3},
+ {DolbyVisionLevelFhd30, 4},
+ {DolbyVisionLevelFhd60, 5},
+ {DolbyVisionLevelUhd24, 6},
+ {DolbyVisionLevelUhd30, 7},
+ {DolbyVisionLevelUhd48, 8},
+ {DolbyVisionLevelUhd60, 9},
+ {DolbyVisionLevelUhd120, 10},
+ {DolbyVisionLevel8k30, 11},
+ {DolbyVisionLevel8k60, 12},
+ };
+ levels.map(level, &level_val);
+ ALOGV("found dolby vision level: %d, value: %d", level, level_val);
+ }
+
+ dvcc[0] = 1; // major version
+ dvcc[1] = 0; // minor version
+ dvcc[2] = (uint8_t)((profile & 0x7f) << 1);// dolby vision profile
+ dvcc[2] = (uint8_t)((dvcc[2] | (uint8_t)((level_val >> 5) & 0x1)) & 0xff);
+ dvcc[3] = (uint8_t)((level_val & 0x1f) << 3); // dolby vision level
+ dvcc[3] = (uint8_t)(dvcc[3] | (1 << 2)); // rpu_present_flag
+ dvcc[3] = (uint8_t)(dvcc[3] | (1)); // bl_present_flag
+ dvcc[4] = (uint8_t)(bl_compatibility << 4);// bl_compatibility id
+
+ std::vector<uint8_t> dvcc_data(24);
+ memcpy(dvcc_data.data(), dvcc, 24);
+ if (profile > 10) {
+ meta->setData(kKeyDVWC, kTypeDVWC, dvcc_data.data(), 24);
+ } else if (profile > 7) {
+ meta->setData(kKeyDVVC, kTypeDVVC, dvcc_data.data(), 24);
+ } else {
+ meta->setData(kKeyDVCC, kTypeDVCC, dvcc_data.data(), 24);
+ }
+ } else if (csd0size >= 24) { // have dovi csd, just send it out...
+ uint8_t *dvconfig = csd0->data() + (csd0size -24);
+ profile = dvconfig[2] >> 1;
+ if (profile > 10) {
+ meta->setData(kKeyDVWC, kTypeDVWC, dvconfig, 24);
+ } else if (profile > 7) {
+ meta->setData(kKeyDVVC, kTypeDVVC, dvconfig, 24);
+ } else {
+ meta->setData(kKeyDVCC, kTypeDVCC, dvconfig, 24);
+ }
+ } else {
+ return BAD_VALUE;
+ }
+
+ // Send the avc/hevc/av1 csd data...
+ if (csd0size >= 24) {
+ sp<ABuffer> csd;
+ if ( profile > 1 && profile < 9) {
+ if (msg->findBuffer("csd-hevc", &csd)) {
+ meta->setData(kKeyHVCC, kTypeHVCC, csd->data(), csd->size());
+ } else if (csd0size > 24) {
std::vector<uint8_t> hvcc(csd0size + 1024);
size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
- } else if (DolbyVisionProfileDvav110 == profile) {
- meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
- } else {
- sp<ABuffer> csd1;
- if (msg->findBuffer("csd-1", &csd1)) {
- std::vector<char> avcc(csd0size + csd1->size() + 1024);
- size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
- meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
- }
}
+ } else if (profile == 9) {
+ sp<ABuffer> csd1;
+ if (msg->findBuffer("csd-avc", &csd)) {
+ meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
+ } else if (msg->findBuffer("csd-1", &csd1)) {
+ std::vector<char> avcc(csd0size + csd1->size() + 1024);
+ size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ } else { // for dolby vision avc, csd0 also holds csd1
+ size_t i = 0;
+ int csd0realsize = 0;
+ do {
+ i = findNextNalStartCode(csd0->data() + i,
+ csd0->size() - i) - csd0->data();
+ if (i > 0) {
+ csd0realsize = i;
+ break;
+ }
+ i += 4;
+ } while(i < csd0->size());
+ // buffer0 -> csd0
+ sp<ABuffer> buffer0 = new (std::nothrow) ABuffer(csd0realsize);
+ if (buffer0.get() == NULL || buffer0->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(buffer0->data(), csd0->data(), csd0realsize);
+ // buffer1 -> csd1
+ sp<ABuffer> buffer1 = new (std::nothrow)
+ ABuffer(csd0->size() - csd0realsize);
+ if (buffer1.get() == NULL || buffer1->base() == NULL) {
+ return NO_MEMORY;
+ }
+ memcpy(buffer1->data(), csd0->data()+csd0realsize,
+ csd0->size() - csd0realsize);
+
+ std::vector<char> avcc(csd0->size() + 1024);
+ size_t outsize = reassembleAVCC(buffer0, buffer1, avcc.data());
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ }
+ } else if (profile == 10) {
+ meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size() - 24);
}
- } else {
- ALOGE("We need csd-2!!. %s", msg->debugString().c_str());
- return BAD_VALUE;
}
} else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
@@ -2080,17 +2216,6 @@
meta->setData(kKeyStreamHeader, 'mdat', csd0->data(), csd0->size());
} else if (msg->findBuffer("d263", &csd0)) {
meta->setData(kKeyD263, kTypeD263, csd0->data(), csd0->size());
- } else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION && msg->findBuffer("csd-2", &csd2)) {
- meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
-
- // Remove CSD-2 from the data here to avoid duplicate data in meta
- meta->remove(kKeyOpaqueCSD2);
-
- if (msg->findBuffer("csd-avc", &csd0)) {
- meta->setData(kKeyAVCC, kTypeAVCC, csd0->data(), csd0->size());
- } else if (msg->findBuffer("csd-hevc", &csd0)) {
- meta->setData(kKeyHVCC, kTypeHVCC, csd0->data(), csd0->size());
- }
}
// XXX TODO add whatever other keys there are
@@ -2173,29 +2298,29 @@
}
struct aac_format_conv_t {
- OMX_AUDIO_AACPROFILETYPE eAacProfileType;
+ int32_t eAacProfileType;
audio_format_t format;
};
static const struct aac_format_conv_t profileLookup[] = {
- { OMX_AUDIO_AACObjectMain, AUDIO_FORMAT_AAC_MAIN},
- { OMX_AUDIO_AACObjectLC, AUDIO_FORMAT_AAC_LC},
- { OMX_AUDIO_AACObjectSSR, AUDIO_FORMAT_AAC_SSR},
- { OMX_AUDIO_AACObjectLTP, AUDIO_FORMAT_AAC_LTP},
- { OMX_AUDIO_AACObjectHE, AUDIO_FORMAT_AAC_HE_V1},
- { OMX_AUDIO_AACObjectScalable, AUDIO_FORMAT_AAC_SCALABLE},
- { OMX_AUDIO_AACObjectERLC, AUDIO_FORMAT_AAC_ERLC},
- { OMX_AUDIO_AACObjectLD, AUDIO_FORMAT_AAC_LD},
- { OMX_AUDIO_AACObjectHE_PS, AUDIO_FORMAT_AAC_HE_V2},
- { OMX_AUDIO_AACObjectELD, AUDIO_FORMAT_AAC_ELD},
- { OMX_AUDIO_AACObjectXHE, AUDIO_FORMAT_AAC_XHE},
- { OMX_AUDIO_AACObjectNull, AUDIO_FORMAT_AAC},
+ { AACObjectMain, AUDIO_FORMAT_AAC_MAIN},
+ { AACObjectLC, AUDIO_FORMAT_AAC_LC},
+ { AACObjectSSR, AUDIO_FORMAT_AAC_SSR},
+ { AACObjectLTP, AUDIO_FORMAT_AAC_LTP},
+ { AACObjectHE, AUDIO_FORMAT_AAC_HE_V1},
+ { AACObjectScalable, AUDIO_FORMAT_AAC_SCALABLE},
+ { AACObjectERLC, AUDIO_FORMAT_AAC_ERLC},
+ { AACObjectLD, AUDIO_FORMAT_AAC_LD},
+ { AACObjectHE_PS, AUDIO_FORMAT_AAC_HE_V2},
+ { AACObjectELD, AUDIO_FORMAT_AAC_ELD},
+ { AACObjectXHE, AUDIO_FORMAT_AAC_XHE},
+ { AACObjectNull, AUDIO_FORMAT_AAC},
};
void mapAACProfileToAudioFormat( audio_format_t& format, uint64_t eAacProfile)
{
-const struct aac_format_conv_t* p = &profileLookup[0];
- while (p->eAacProfileType != OMX_AUDIO_AACObjectNull) {
+ const struct aac_format_conv_t* p = &profileLookup[0];
+ while (p->eAacProfileType != AACObjectNull) {
if (eAacProfile == p->eAacProfileType) {
format = p->format;
return;
@@ -2235,7 +2360,7 @@
// Offloading depends on audio DSP capabilities.
int32_t aacaot = -1;
if (meta->findInt32(kKeyAACAOT, &aacaot)) {
- mapAACProfileToAudioFormat(info->format,(OMX_AUDIO_AACPROFILETYPE) aacaot);
+ mapAACProfileToAudioFormat(info->format, aacaot);
}
int32_t srate = -1;
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index c7dc415..6004cf8 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/ColorConverter.h>
+#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaErrors.h>
#include "libyuv/convert_from.h"
@@ -51,13 +52,17 @@
static bool isRGB(OMX_COLOR_FORMATTYPE colorFormat) {
return colorFormat == OMX_COLOR_Format16bitRGB565
|| colorFormat == OMX_COLOR_Format32BitRGBA8888
- || colorFormat == OMX_COLOR_Format32bitBGRA8888;
+ || colorFormat == OMX_COLOR_Format32bitBGRA8888
+ || colorFormat == COLOR_Format32bitABGR2101010;
}
bool ColorConverter::ColorSpace::isBt709() {
return (mStandard == ColorUtils::kColorStandardBT709);
}
+bool ColorConverter::ColorSpace::isBt2020() {
+ return (mStandard == ColorUtils::kColorStandardBT2020);
+}
bool ColorConverter::ColorSpace::isJpeg() {
return ((mStandard == ColorUtils::kColorStandardBT601_625)
@@ -70,16 +75,19 @@
: mSrcFormat(from),
mDstFormat(to),
mSrcColorSpace({0, 0, 0}),
- mClip(NULL) {
+ mClip(NULL),
+ mClip10Bit(NULL) {
}
ColorConverter::~ColorConverter() {
delete[] mClip;
mClip = NULL;
+ delete[] mClip10Bit;
+ mClip10Bit = NULL;
}
bool ColorConverter::isValid() const {
- switch (mSrcFormat) {
+ switch ((int32_t)mSrcFormat) {
case OMX_COLOR_FormatYUV420Planar16:
if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
return true;
@@ -102,6 +110,8 @@
#else
return mDstFormat == OMX_COLOR_Format16bitRGB565;
#endif
+ case COLOR_FormatYUVP010:
+ return mDstFormat == COLOR_Format32bitABGR2101010;
default:
return false;
@@ -143,9 +153,10 @@
mCropTop(cropTop),
mCropRight(cropRight),
mCropBottom(cropBottom) {
- switch(mColorFormat) {
+ switch((int32_t)mColorFormat) {
case OMX_COLOR_Format16bitRGB565:
case OMX_COLOR_FormatYUV420Planar16:
+ case COLOR_FormatYUVP010:
case OMX_COLOR_FormatCbYCrY:
mBpp = 2;
mStride = 2 * mWidth;
@@ -153,6 +164,7 @@
case OMX_COLOR_Format32bitBGRA8888:
case OMX_COLOR_Format32BitRGBA8888:
+ case COLOR_Format32bitABGR2101010:
case OMX_COLOR_FormatYUV444Y410:
mBpp = 4;
mStride = 4 * mWidth;
@@ -213,7 +225,7 @@
status_t err;
- switch (mSrcFormat) {
+ switch ((int32_t)mSrcFormat) {
case OMX_COLOR_FormatYUV420Planar:
#ifdef USE_LIBYUV
err = convertYUV420PlanarUseLibYUV(src, dst);
@@ -235,6 +247,19 @@
break;
}
+ case COLOR_FormatYUVP010:
+ {
+#if PERF_PROFILING
+ int64_t startTimeUs = ALooper::GetNowUs();
+#endif
+ err = convertYUVP010(src, dst);
+#if PERF_PROFILING
+ int64_t endTimeUs = ALooper::GetNowUs();
+ ALOGD("convertYUVP010 took %lld us", (long long) (endTimeUs - startTimeUs));
+#endif
+ break;
+ }
+
case OMX_COLOR_FormatCbYCrY:
err = convertCbYCrY(src, dst);
break;
@@ -439,23 +464,23 @@
}
std::function<void (void *, bool, signed, signed, signed, signed, signed, signed)>
-getWriteToDst(OMX_COLOR_FORMATTYPE dstFormat, uint8_t *kAdjustedClip) {
- switch (dstFormat) {
+getWriteToDst(OMX_COLOR_FORMATTYPE dstFormat, void *kAdjustedClip) {
+ switch ((int)dstFormat) {
case OMX_COLOR_Format16bitRGB565:
{
return [kAdjustedClip](void *dst_ptr, bool uncropped,
signed r1, signed g1, signed b1,
signed r2, signed g2, signed b2) {
uint32_t rgb1 =
- ((kAdjustedClip[r1] >> 3) << 11)
- | ((kAdjustedClip[g1] >> 2) << 5)
- | (kAdjustedClip[b1] >> 3);
+ ((((uint8_t *)kAdjustedClip)[r1] >> 3) << 11)
+ | ((((uint8_t *)kAdjustedClip)[g1] >> 2) << 5)
+ | (((uint8_t *)kAdjustedClip)[b1] >> 3);
if (uncropped) {
uint32_t rgb2 =
- ((kAdjustedClip[r2] >> 3) << 11)
- | ((kAdjustedClip[g2] >> 2) << 5)
- | (kAdjustedClip[b2] >> 3);
+ ((((uint8_t *)kAdjustedClip)[r2] >> 3) << 11)
+ | ((((uint8_t *)kAdjustedClip)[g2] >> 2) << 5)
+ | (((uint8_t *)kAdjustedClip)[b2] >> 3);
*(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
} else {
@@ -469,16 +494,16 @@
signed r1, signed g1, signed b1,
signed r2, signed g2, signed b2) {
((uint32_t *)dst_ptr)[0] =
- (kAdjustedClip[r1])
- | (kAdjustedClip[g1] << 8)
- | (kAdjustedClip[b1] << 16)
+ (((uint8_t *)kAdjustedClip)[r1])
+ | (((uint8_t *)kAdjustedClip)[g1] << 8)
+ | (((uint8_t *)kAdjustedClip)[b1] << 16)
| (0xFF << 24);
if (uncropped) {
((uint32_t *)dst_ptr)[1] =
- (kAdjustedClip[r2])
- | (kAdjustedClip[g2] << 8)
- | (kAdjustedClip[b2] << 16)
+ (((uint8_t *)kAdjustedClip)[r2])
+ | (((uint8_t *)kAdjustedClip)[g2] << 8)
+ | (((uint8_t *)kAdjustedClip)[b2] << 16)
| (0xFF << 24);
}
};
@@ -489,20 +514,41 @@
signed r1, signed g1, signed b1,
signed r2, signed g2, signed b2) {
((uint32_t *)dst_ptr)[0] =
- (kAdjustedClip[b1])
- | (kAdjustedClip[g1] << 8)
- | (kAdjustedClip[r1] << 16)
+ (((uint8_t *)kAdjustedClip)[b1])
+ | (((uint8_t *)kAdjustedClip)[g1] << 8)
+ | (((uint8_t *)kAdjustedClip)[r1] << 16)
| (0xFF << 24);
if (uncropped) {
((uint32_t *)dst_ptr)[1] =
- (kAdjustedClip[b2])
- | (kAdjustedClip[g2] << 8)
- | (kAdjustedClip[r2] << 16)
+ (((uint8_t *)kAdjustedClip)[b2])
+ | (((uint8_t *)kAdjustedClip)[g2] << 8)
+ | (((uint8_t *)kAdjustedClip)[r2] << 16)
| (0xFF << 24);
}
};
}
+ case COLOR_Format32bitABGR2101010:
+ {
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ ((uint32_t *)dst_ptr)[0] =
+ (((uint16_t *)kAdjustedClip)[r1])
+ | (((uint16_t *)kAdjustedClip)[g1] << 10)
+ | (((uint16_t *)kAdjustedClip)[b1] << 20)
+ | (3 << 30);
+
+ if (uncropped) {
+ ((uint32_t *)dst_ptr)[1] =
+ (((uint16_t *)kAdjustedClip)[r2])
+ | (((uint16_t *)kAdjustedClip)[g2] << 10)
+ | (((uint16_t *)kAdjustedClip)[b2] << 20)
+ | (3 << 30);
+ }
+ };
+ }
+
default:
TRESPASS();
}
@@ -514,7 +560,7 @@
uint8_t *kAdjustedClip = initClip();
auto readFromSrc = getReadFromSrc(mSrcFormat);
- auto writeToDst = getWriteToDst(mDstFormat, kAdjustedClip);
+ auto writeToDst = getWriteToDst(mDstFormat, (void *)kAdjustedClip);
uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -591,34 +637,116 @@
return convertYUV420Planar(src, dst);
}
-/*
- * Pack 10-bit YUV into RGBA_1010102.
- *
- * Media sends 10-bit YUV in a RGBA_1010102 format buffer. SF will handle
- * the conversion to RGB using RenderEngine fallback.
- *
- * We do not perform a YUV->RGB conversion here, however the conversion with
- * BT2020 to Full range is below for reference:
- *
- * B = 1.168 *(Y - 64) + 2.148 *(U - 512)
- * G = 1.168 *(Y - 64) - 0.652 *(V - 512) - 0.188 *(U - 512)
- * R = 1.168 *(Y - 64) + 1.683 *(V - 512)
- *
- * B = 1196/1024 *(Y - 64) + 2200/1024 *(U - 512)
- * G = .................... - 668/1024 *(V - 512) - 192/1024 *(U - 512)
- * R = .................... + 1723/1024 *(V - 512)
- *
- * min_B = (1196 *(- 64) + 2200 *(- 512)) / 1024 = -1175
- * min_G = (1196 *(- 64) - 668 *(1023 - 512) - 192 *(1023 - 512)) / 1024 = -504
- * min_R = (1196 *(- 64) + 1723 *(- 512)) / 1024 = -937
- *
- * max_B = (1196 *(1023 - 64) + 2200 *(1023 - 512)) / 1024 = 2218
- * max_G = (1196 *(1023 - 64) - 668 *(- 512) - 192 *(- 512)) / 1024 = 1551
- * max_R = (1196 *(1023 - 64) + 1723 *(1023 - 512)) / 1024 = 1980
- *
- * clip range -1175 .. 2218
- *
- */
+status_t ColorConverter::convertYUVP010(
+ const BitmapParams &src, const BitmapParams &dst) {
+ if (mDstFormat == COLOR_Format32bitABGR2101010) {
+ return convertYUVP010ToRGBA1010102(src, dst);
+ }
+
+ return ERROR_UNSUPPORTED;
+}
+
+status_t ColorConverter::convertYUVP010ToRGBA1010102(
+ const BitmapParams &src, const BitmapParams &dst) {
+ uint16_t *kAdjustedClip10bit = initClip10Bit();
+
+// auto readFromSrc = getReadFromSrc(mSrcFormat);
+ auto writeToDst = getWriteToDst(mDstFormat, (void *)kAdjustedClip10bit);
+
+ uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+
+ uint16_t *src_y = (uint16_t *)((uint8_t *)src.mBits
+ + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp);
+
+ uint16_t *src_uv = (uint16_t *)((uint8_t *)src.mBits
+ + src.mStride * src.mHeight
+ + (src.mCropTop / 2) * src.mStride + src.mCropLeft * src.mBpp);
+
+ // BT.2020 Limited Range conversion
+
+ // B = 1.168 *(Y - 64) + 2.148 *(U - 512)
+ // G = 1.168 *(Y - 64) - 0.652 *(V - 512) - 0.188 *(U - 512)
+ // R = 1.168 *(Y - 64) + 1.683 *(V - 512)
+
+ // B = 1196/1024 *(Y - 64) + 2200/1024 *(U - 512)
+ // G = .................... - 668/1024 *(V - 512) - 192/1024 *(U - 512)
+ // R = .................... + 1723/1024 *(V - 512)
+
+ // min_B = (1196 *(- 64) + 2200 *(- 512)) / 1024 = -1175
+ // min_G = (1196 *(- 64) - 668 *(1023 - 512) - 192 *(1023 - 512)) / 1024 = -504
+ // min_R = (1196 *(- 64) + 1723 *(- 512)) / 1024 = -937
+
+ // max_B = (1196 *(1023 - 64) + 2200 *(1023 - 512)) / 1024 = 2218
+ // max_G = (1196 *(1023 - 64) - 668 *(- 512) - 192 *(- 512)) / 1024 = 1551
+ // max_R = (1196 *(1023 - 64) + 1723 *(1023 - 512)) / 1024 = 1980
+
+ // clip range -1175 .. 2218
+
+ // BT.709 Limited Range conversion
+
+ // B = 1.164 * (Y - 64) + 2.018 * (U - 512)
+ // G = 1.164 * (Y - 64) - 0.813 * (V - 512) - 0.391 * (U - 512)
+ // R = 1.164 * (Y - 64) + 1.596 * (V - 512)
+
+ // B = 1192/1024 * (Y - 64) + 2068/1024 * (U - 512)
+ // G = .................... - 832/1024 * (V - 512) - 400/1024 * (U - 512)
+ // R = .................... + 1636/1024 * (V - 512)
+
+ // min_B = (1192 * (- 64) + 2068 * (- 512)) / 1024 = -1108
+
+ // max_B = (1192 * (1023 - 64) + 517 * (1023 - 512)) / 1024 = 2148
+
+ // clip range -1108 .. 2148
+
+ signed mY = 1196, mU_B = 2200, mV_G = -668, mV_R = 1723, mU_G = -192;
+ if (!mSrcColorSpace.isBt2020()) {
+ mY = 1192;
+ mU_B = 2068;
+ mV_G = -832;
+ mV_R = 1636;
+ mU_G = -400;
+ }
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1, y2, u, v;
+ y1 = (src_y[x] >> 6) - 64;
+ y2 = (src_y[x + 1] >> 6) - 64;
+ u = int(src_uv[x] >> 6) - 512;
+ v = int(src_uv[x + 1] >> 6) - 512;
+
+ signed u_b = u * mU_B;
+ signed u_g = u * mU_G;
+ signed v_g = v * mV_G;
+ signed v_r = v * mV_R;
+
+ signed tmp1 = y1 * mY;
+ signed b1 = (tmp1 + u_b) / 1024;
+ signed g1 = (tmp1 + v_g + u_g) / 1024;
+ signed r1 = (tmp1 + v_r) / 1024;
+
+ signed tmp2 = y2 * mY;
+ signed b2 = (tmp2 + u_b) / 1024;
+ signed g2 = (tmp2 + v_g + u_g) / 1024;
+ signed r2 = (tmp2 + v_r) / 1024;
+
+ bool uncropped = x + 1 < src.cropWidth();
+
+ writeToDst(dst_ptr + x * dst.mBpp, uncropped, r1, g1, b1, r2, g2, b2);
+ }
+
+ src_y += src.mStride / 2;
+
+ if (y & 1) {
+ src_uv += src.mStride / 2;
+ }
+
+ dst_ptr += dst.mStride;
+ }
+
+ return OK;
+}
+
#if !USE_NEON_Y410
@@ -1033,4 +1161,19 @@
return &mClip[-kClipMin];
}
+uint16_t *ColorConverter::initClip10Bit() {
+ static const signed kClipMin = -1176;
+ static const signed kClipMax = 2219;
+
+ if (mClip10Bit == NULL) {
+ mClip10Bit = new uint16_t[kClipMax - kClipMin + 1];
+
+ for (signed i = kClipMin; i <= kClipMax; ++i) {
+ mClip10Bit[i - kClipMin] = (i < 0) ? 0 : (i > 1023) ? 1023 : (uint16_t)i;
+ }
+ }
+
+ return &mClip10Bit[-kClipMin];
+}
+
} // namespace android
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 75b0d8e..1d86a22 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -54,6 +54,7 @@
uint32_t mTransfer;
bool isBt709();
+ bool isBt2020();
bool isJpeg();
};
@@ -78,8 +79,10 @@
OMX_COLOR_FORMATTYPE mSrcFormat, mDstFormat;
ColorSpace mSrcColorSpace;
uint8_t *mClip;
+ uint16_t *mClip10Bit;
uint8_t *initClip();
+ uint16_t *initClip10Bit();
status_t convertCbYCrY(
const BitmapParams &src, const BitmapParams &dst);
@@ -111,6 +114,12 @@
status_t convertTIYUV420PackedSemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertYUVP010(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertYUVP010ToRGBA1010102(
+ const BitmapParams &src, const BitmapParams &dst);
+
ColorConverter(const ColorConverter &);
ColorConverter &operator=(const ColorConverter &);
};
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 656267c..fa9dc8b 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -540,6 +540,9 @@
constexpr int32_t DolbyVisionLevelUhd30 = 0x40;
constexpr int32_t DolbyVisionLevelUhd48 = 0x80;
constexpr int32_t DolbyVisionLevelUhd60 = 0x100;
+constexpr int32_t DolbyVisionLevelUhd120 = 0x200;
+constexpr int32_t DolbyVisionLevel8k30 = 0x400;
+constexpr int32_t DolbyVisionLevel8k60 = 0x800;
inline static const char *asString_DolbyVisionLevel(int32_t i, const char *def = "??") {
switch (i) {
@@ -552,6 +555,9 @@
case DolbyVisionLevelUhd30: return "Uhd30";
case DolbyVisionLevelUhd48: return "Uhd48";
case DolbyVisionLevelUhd60: return "Uhd60";
+ case DolbyVisionLevelUhd120: return "Uhd120";
+ case DolbyVisionLevel8k30: return "8k30";
+ case DolbyVisionLevel8k60: return "8k60";
default: return def;
}
}
@@ -586,9 +592,11 @@
constexpr int32_t COLOR_Format24bitBGR888 = 12;
constexpr int32_t COLOR_Format24bitRGB888 = 11;
constexpr int32_t COLOR_Format25bitARGB1888 = 14;
+constexpr int32_t COLOR_Format32bitABGR2101010 = 0x7F00AAA2;
constexpr int32_t COLOR_Format32bitABGR8888 = 0x7F00A000;
constexpr int32_t COLOR_Format32bitARGB8888 = 16;
constexpr int32_t COLOR_Format32bitBGRA8888 = 15;
+constexpr int32_t COLOR_Format64bitABGRFloat = 0x7F000F16;
constexpr int32_t COLOR_Format8bitRGB332 = 2;
constexpr int32_t COLOR_FormatCbYCrY = 27;
constexpr int32_t COLOR_FormatCrYCbY = 28;
@@ -642,9 +650,11 @@
case COLOR_Format24bitBGR888: return "24bitBGR888";
case COLOR_Format24bitRGB888: return "24bitRGB888";
case COLOR_Format25bitARGB1888: return "25bitARGB1888";
+ case COLOR_Format32bitABGR2101010: return "32bitABGR2101010";
case COLOR_Format32bitABGR8888: return "32bitABGR8888";
case COLOR_Format32bitARGB8888: return "32bitARGB8888";
case COLOR_Format32bitBGRA8888: return "32bitBGRA8888";
+ case COLOR_Format64bitABGRFloat: return "64bitABGRFloat";
case COLOR_Format8bitRGB332: return "8bitRGB332";
case COLOR_FormatCbYCrY: return "CbYCrY";
case COLOR_FormatCrYCbY: return "CrYCbY";
@@ -677,6 +687,7 @@
case COLOR_FormatYUV422SemiPlanar: return "YUV422SemiPlanar";
case COLOR_FormatYUV444Flexible: return "YUV444Flexible";
case COLOR_FormatYUV444Interleaved: return "YUV444Interleaved";
+ case COLOR_FormatYUVP010: return "YUVP010";
case COLOR_QCOM_FormatYUV420SemiPlanar: return "QCOM_YUV420SemiPlanar";
case COLOR_TI_FormatYUV420PackedSemiPlanar: return "TI_YUV420PackedSemiPlanar";
default: return def;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index c80012e..88c1f3f 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -60,6 +60,8 @@
kKeyAVCC = 'avcc', // raw data
kKeyHVCC = 'hvcc', // raw data
kKeyDVCC = 'dvcc', // raw data
+ kKeyDVVC = 'dvvc', // raw data
+ kKeyDVWC = 'dvwc', // raw data
kKeyAV1C = 'av1c', // raw data
kKeyThumbnailHVCC = 'thvc', // raw data
kKeyThumbnailAV1C = 'tav1', // raw data
@@ -283,6 +285,8 @@
kTypeHVCC = 'hvcc',
kTypeAV1C = 'av1c',
kTypeDVCC = 'dvcc',
+ kTypeDVVC = 'dvvc',
+ kTypeDVWC = 'dvwc',
kTypeD263 = 'd263',
kTypeHCOS = 'hcos',
};
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 6c5e6cb..f50acae 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -145,6 +145,7 @@
"libgui",
"libui",
"libmediandk_utils",
+ "android.hardware.drm-V1-ndk",
],
export_header_lib_headers: ["jni_headers"],
diff --git a/services/audioflinger/OWNERS b/services/audioflinger/OWNERS
index 034d161..17d4c37 100644
--- a/services/audioflinger/OWNERS
+++ b/services/audioflinger/OWNERS
@@ -1,4 +1,4 @@
-gkasten@google.com
hunga@google.com
jmtrivi@google.com
mnaganov@google.com
+philburk@google.com
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index f6f3b9a..e8e478b 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -300,6 +300,8 @@
virtual bool isHapticPlaybackSupported() = 0;
+ virtual bool isUltrasoundSupported() = 0;
+
virtual status_t getHwOffloadFormatsSupportedForBluetoothMedia(
audio_devices_t device, std::vector<audio_format_t> *formats) = 0;
@@ -404,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/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 ee2c0f7..bd295ce 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3833,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,
@@ -4892,6 +4933,37 @@
return false;
}
+bool AudioPolicyManager::isUltrasoundSupported()
+{
+ bool hasUltrasoundOutput = false;
+ bool hasUltrasoundInput = false;
+ for (const auto& hwModule : mHwModules) {
+ const OutputProfileCollection &outputProfiles = hwModule->getOutputProfiles();
+ if (!hasUltrasoundOutput) {
+ for (const auto &outProfile : outputProfiles) {
+ if (outProfile->getFlags() & AUDIO_OUTPUT_FLAG_ULTRASOUND) {
+ hasUltrasoundOutput = true;
+ break;
+ }
+ }
+ }
+
+ const InputProfileCollection &inputProfiles = hwModule->getInputProfiles();
+ if (!hasUltrasoundInput) {
+ for (const auto &inputProfile : inputProfiles) {
+ if (inputProfile->getFlags() & AUDIO_INPUT_FLAG_ULTRASOUND) {
+ hasUltrasoundInput = true;
+ break;
+ }
+ }
+ }
+
+ if (hasUltrasoundOutput && hasUltrasoundInput)
+ return true;
+ }
+ return false;
+}
+
bool AudioPolicyManager::isCallScreenModeSupported()
{
return getConfig().isCallScreenModeSupported();
@@ -6305,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) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index dd69295..165ac13 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -327,6 +327,8 @@
virtual bool isHapticPlaybackSupported();
+ virtual bool isUltrasoundSupported();
+
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies)
{
return mEngine->listAudioProductStrategies(strategies);
@@ -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;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index a30768a..aba8884 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -2058,6 +2058,17 @@
return Status::ok();
}
+Status AudioPolicyService::isUltrasoundSupported(bool* _aidl_return)
+{
+ if (mAudioPolicyManager == NULL) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ *_aidl_return = mAudioPolicyManager->isUltrasoundSupported();
+ return Status::ok();
+}
+
Status AudioPolicyService::listAudioProductStrategies(
std::vector<media::AudioProductStrategy>* _aidl_return) {
AudioProductStrategyVector strategies;
@@ -2372,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.h b/services/audiopolicy/service/AudioPolicyService.h
index 84b1e50..ac5af6b 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -224,6 +224,7 @@
binder::Status setA11yServicesUids(const std::vector<int32_t>& uids) override;
binder::Status setCurrentImeUid(int32_t uid) override;
binder::Status isHapticPlaybackSupported(bool* _aidl_return) override;
+ binder::Status isUltrasoundSupported(bool* _aidl_return) override;
binder::Status listAudioProductStrategies(
std::vector<media::AudioProductStrategy>* _aidl_return) override;
binder::Status getProductStrategyFromAudioAttributes(const media::AudioAttributesEx& aa,
@@ -276,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/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/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/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 100%
rename from services/mediametrics/AudioPowerUsage.h
rename to services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
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) {