C2VDAComponent: Add secure components to enable ARC++ DRM L1 for Codec 2.0

Bug: 73870167
Test: Play secure videos with ExoPlayer.app

Change-Id: I72c9652932fa3cf200191f2a459142aaffd01956
diff --git a/C2VDAComponent.cpp b/C2VDAComponent.cpp
index 6839130..dd48d33 100644
--- a/C2VDAComponent.cpp
+++ b/C2VDAComponent.cpp
@@ -34,6 +34,7 @@
 #include <inttypes.h>
 #include <string.h>
 #include <algorithm>
+#include <string>
 
 #define UNUSED(expr)  \
     do {              \
@@ -55,6 +56,9 @@
 const C2String kH264DecoderName = "c2.vda.avc.decoder";
 const C2String kVP8DecoderName = "c2.vda.vp8.decoder";
 const C2String kVP9DecoderName = "c2.vda.vp9.decoder";
+const C2String kH264SecureDecoderName = "c2.vda.avc.decoder.secure";
+const C2String kVP8SecureDecoderName = "c2.vda.vp8.decoder.secure";
+const C2String kVP9SecureDecoderName = "c2.vda.vp9.decoder.secure";
 
 const uint32_t kDpbOutputBufferExtraCount = 3;  // Use the same number as ACodec.
 const int kDequeueRetryDelayUs = 10000;  // Wait time of dequeue buffer retry in microseconds.
@@ -67,13 +71,13 @@
     // TODO(johnylin): use factory function to determine whether V4L2 stream or slice API is.
     uint32_t inputFormatFourcc;
     char inputMime[128];
-    if (name == kH264DecoderName) {
+    if (name == kH264DecoderName || name == kH264SecureDecoderName) {
         strcpy(inputMime, MEDIA_MIMETYPE_VIDEO_AVC);
         inputFormatFourcc = V4L2_PIX_FMT_H264_SLICE;
-    } else if (name == kVP8DecoderName) {
+    } else if (name == kVP8DecoderName || name == kVP8SecureDecoderName) {
         strcpy(inputMime, MEDIA_MIMETYPE_VIDEO_VP8);
         inputFormatFourcc = V4L2_PIX_FMT_VP8_FRAME;
-    } else if (name == kVP9DecoderName) {
+    } else if (name == kVP9DecoderName || name == kVP9SecureDecoderName) {
         strcpy(inputMime, MEDIA_MIMETYPE_VIDEO_VP9);
         inputFormatFourcc = V4L2_PIX_FMT_VP9_FRAME;
     } else {
@@ -139,8 +143,13 @@
                          .withSetter(LocalSetter::SizeSetter)
                          .build());
 
-    C2Allocator::id_t inputAllocators[] = {C2PlatformAllocatorStore::ION};
-    C2Allocator::id_t outputAllocators[] = {C2VDAAllocatorStore::V4L2_BUFFERPOOL};
+    bool secureMode = name.find(".secure") != std::string::npos;
+    C2Allocator::id_t inputAllocators[] = {secureMode ? C2VDAAllocatorStore::SECURE_LINEAR
+                                                      : C2PlatformAllocatorStore::ION};
+    C2Allocator::id_t outputAllocators[] = {secureMode ? C2VDAAllocatorStore::SECURE_GRAPHIC
+                                                       : C2VDAAllocatorStore::V4L2_BUFFERQUEUE};
+    // TODO: change as below after ag/4660016 is landed.
+    // C2Allocator::id_t outputAllocators[] = {C2VDAAllocatorStore::V4L2_BUFFERPOOL};
 
     addParameter(
             DefineParam(mInputAllocatorIds, C2_PARAMKEY_INPUT_ALLOCATORS)
@@ -201,6 +210,8 @@
         ALOGE("Component interface init failed (err code = %d)", mIntfImpl->status());
         return;
     }
+
+    mSecureMode = name.find(".secure") != std::string::npos;
     if (!mThread.Start()) {
         ALOGE("Component thread failed to start.");
         return;
@@ -240,9 +251,7 @@
     mVDAAdaptor.reset(new C2VDAAdaptor());
 #endif
 
-    // TODO: Set secureMode value dynamically.
-    bool secureMode = false;
-    mVDAInitResult = mVDAAdaptor->initialize(profile, secureMode, this);
+    mVDAInitResult = mVDAAdaptor->initialize(profile, mSecureMode, this);
     if (mVDAInitResult == VideoDecodeAcceleratorAdaptor::Result::SUCCESS) {
         mComponentState = ComponentState::STARTED;
     }
@@ -732,7 +741,8 @@
 
     for (size_t i = 0; i < bufferCount; ++i) {
         std::shared_ptr<C2GraphicBlock> block;
-        C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, 0};
+        C2MemoryUsage usage = {
+                mSecureMode ? C2MemoryUsage::READ_PROTECTED : C2MemoryUsage::CPU_READ, 0};
         err = blockPool->fetchGraphicBlock(size.width(), size.height(), pixelFormat, usage, &block);
         if (err != C2_OK) {
             mGraphicBlocks.clear();
@@ -752,7 +762,11 @@
             reportError(err);
             return err;
         }
-        appendOutputBuffer(std::move(block), poolId);
+        if (mSecureMode) {
+            appendSecureOutputBuffer(std::move(block), poolId);
+        } else {
+            appendOutputBuffer(std::move(block), poolId);
+        }
     }
     mOutputFormat.mMinNumBuffers = bufferCount;
 
@@ -831,6 +845,37 @@
     mGraphicBlocks.push_back(std::move(info));
 }
 
+void C2VDAComponent::appendSecureOutputBuffer(std::shared_ptr<C2GraphicBlock> block,
+                                              uint32_t poolId) {
+#ifdef V4L2_CODEC2_ARC
+    const C2Handle* const handle = block->handle();
+    const int handleFd = handle->data[0];
+    ::base::ScopedFD passedHandle(dup(handleFd));
+    if (!passedHandle.is_valid()) {
+        ALOGE("Failed to dup(%d), errno=%d", handleFd, errno);
+        reportError(C2_CORRUPTED);
+        return;
+    }
+
+    // TODO(hiroh): resolve pixel format here.
+    android::HalPixelFormat pixelFormat = pixelFormat == android::HalPixelFormat::NV12;
+    ALOGV("HAL pixel format: 0x%x", static_cast<uint32_t>(pixelFormat));
+
+    GraphicBlockInfo info;
+    info.mBlockId = static_cast<int32_t>(mGraphicBlocks.size());
+    info.mGraphicBlock = std::move(block);
+    info.mPoolId = poolId;
+    info.mHandle = std::move(passedHandle);
+    info.mPixelFormat = pixelFormat;
+    // In secure mode, since planes are not referred in Chrome side, empty plane is valid.
+    info.mPlanes.clear();
+    mGraphicBlocks.push_back(std::move(info));
+#else
+    ALOGE("appendSecureOutputBuffer() is not supported...");
+    reportError(C2_OMITTED);
+#endif // V4L2_CODEC2_ARC
+}
+
 void C2VDAComponent::sendOutputBufferToAccelerator(GraphicBlockInfo* info) {
     ALOGV("sendOutputBufferToAccelerator index=%d", info->mBlockId);
     CHECK_EQ(info->mState, GraphicBlockInfo::State::OWNED_BY_COMPONENT);
@@ -1190,7 +1235,8 @@
             continue;
         }
         std::shared_ptr<C2GraphicBlock> block;
-        C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, 0};
+        C2MemoryUsage usage = {
+                mSecureMode ? C2MemoryUsage::READ_PROTECTED : C2MemoryUsage::CPU_READ, 0};
         auto err = blockPool->fetchGraphicBlock(size.width(), size.height(), pixelFormat, usage,
                                                 &block);
         if (err == C2_TIMED_OUT) {
@@ -1251,9 +1297,10 @@
 };
 }  // namespace android
 
-extern "C" ::C2ComponentFactory* CreateC2VDAH264Factory() {
-    ALOGV("in %s", __func__);
-    return new ::android::C2VDAComponentFactory(android::kH264DecoderName);
+extern "C" ::C2ComponentFactory* CreateC2VDAH264Factory(bool secureMode) {
+    ALOGV("in %s (secureMode=%d)", __func__, secureMode);
+    return secureMode ? new ::android::C2VDAComponentFactory(android::kH264SecureDecoderName)
+                      : new ::android::C2VDAComponentFactory(android::kH264DecoderName);
 }
 
 extern "C" void DestroyC2VDAH264Factory(::C2ComponentFactory* factory) {
@@ -1261,9 +1308,10 @@
     delete factory;
 }
 
-extern "C" ::C2ComponentFactory* CreateC2VDAVP8Factory() {
-    ALOGV("in %s", __func__);
-    return new ::android::C2VDAComponentFactory(android::kVP8DecoderName);
+extern "C" ::C2ComponentFactory* CreateC2VDAVP8Factory(bool secureMode) {
+    ALOGV("in %s (secureMode=%d)", __func__, secureMode);
+    return secureMode ? new ::android::C2VDAComponentFactory(android::kVP8SecureDecoderName)
+                      : new ::android::C2VDAComponentFactory(android::kVP8DecoderName);
 }
 
 extern "C" void DestroyC2VDAVP8Factory(::C2ComponentFactory* factory) {
@@ -1271,9 +1319,10 @@
     delete factory;
 }
 
-extern "C" ::C2ComponentFactory* CreateC2VDAVP9Factory() {
-    ALOGV("in %s", __func__);
-    return new ::android::C2VDAComponentFactory(android::kVP9DecoderName);
+extern "C" ::C2ComponentFactory* CreateC2VDAVP9Factory(bool secureMode) {
+    ALOGV("in %s (secureMode=%d)", __func__, secureMode);
+    return secureMode ? new ::android::C2VDAComponentFactory(android::kVP9SecureDecoderName)
+                      : new ::android::C2VDAComponentFactory(android::kVP9DecoderName);
 }
 
 extern "C" void DestroyC2VDAVP9Factory(::C2ComponentFactory* factory) {