Modular DRM for MediaPlayer

Bug:  34559906
Test: Manual through the test app

Change-Id: I286f9ff199c34563b7b8643de725f8d1534ea06c
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 0a0a8aa..5689e95 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -23,6 +23,7 @@
 
 #include "NuPlayerCCDecoder.h"
 #include "NuPlayerDecoder.h"
+#include "NuPlayerDrm.h"
 #include "NuPlayerRenderer.h"
 #include "NuPlayerSource.h"
 
@@ -255,6 +256,13 @@
             break;
         }
 
+        case kWhatDrmReleaseCrypto:
+        {
+            ALOGV("kWhatDrmReleaseCrypto");
+            onReleaseCrypto(msg);
+            break;
+        }
+
         default:
             DecoderBase::onMessageReceived(msg);
             break;
@@ -312,8 +320,19 @@
         // any error signaling will occur.
         ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
     }
+
+    // Modular DRM
+    void *pCrypto;
+    if (!format->findPointer("crypto", &pCrypto)) {
+        pCrypto = NULL;
+    }
+    sp<ICrypto> crypto = (ICrypto*)pCrypto;
+    ALOGV("onConfigure mCrypto: %p (%d)  mIsSecure: %d",
+            crypto.get(), (crypto != NULL ? crypto->getStrongCount() : 0), mIsSecure);
+
     err = mCodec->configure(
-            format, mSurface, NULL /* crypto */, 0 /* flags */);
+            format, mSurface, crypto, 0 /* flags */);
+
     if (err != OK) {
         ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
         mCodec->release();
@@ -559,6 +578,43 @@
     notify->post();
 }
 
+status_t NuPlayer::Decoder::releaseCrypto()
+{
+    ALOGV("releaseCrypto");
+
+    sp<AMessage> msg = new AMessage(kWhatDrmReleaseCrypto, this);
+
+    sp<AMessage> response;
+    status_t status = msg->postAndAwaitResponse(&response);
+    if (status == OK && response != NULL) {
+        CHECK(response->findInt32("status", &status));
+        ALOGV("releaseCrypto ret: %d ", status);
+    } else {
+        ALOGE("releaseCrypto err: %d", status);
+    }
+
+    return status;
+}
+
+void NuPlayer::Decoder::onReleaseCrypto(const sp<AMessage>& msg)
+{
+    status_t status = INVALID_OPERATION;
+    if (mCodec != NULL) {
+        status = mCodec->releaseCrypto();
+    } else {
+        // returning OK if the codec has been already released
+        status = OK;
+        ALOGE("onReleaseCrypto No mCodec. err: %d", status);
+    }
+
+    sp<AMessage> response = new AMessage;
+    response->setInt32("status", status);
+
+    sp<AReplyToken> replyID;
+    CHECK(msg->senderAwaitsResponse(&replyID));
+    response->postReply(replyID);
+}
+
 bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) {
     if (isDiscontinuityPending()) {
         return false;
@@ -929,6 +985,10 @@
             flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
         }
 
+        // Modular DRM
+        MediaBuffer *mediaBuf = NULL;
+        NuPlayerDrm::CryptoInfo *cryptInfo = NULL;
+
         // copy into codec buffer
         if (needsCopy) {
             if (buffer->size() > codecBuffer->capacity()) {
@@ -936,24 +996,68 @@
                 mDequeuedInputBuffers.push_back(bufferIx);
                 return false;
             }
-            codecBuffer->setRange(0, buffer->size());
-            memcpy(codecBuffer->data(), buffer->data(), buffer->size());
-        }
 
-        status_t err = mCodec->queueInputBuffer(
-                        bufferIx,
-                        codecBuffer->offset(),
-                        codecBuffer->size(),
-                        timeUs,
-                        flags);
+            if (buffer->data() != NULL) {
+                codecBuffer->setRange(0, buffer->size());
+                memcpy(codecBuffer->data(), buffer->data(), buffer->size());
+            } else { // No buffer->data()
+                //Modular DRM
+                mediaBuf = (MediaBuffer*)buffer->getMediaBufferBase();
+                if (mediaBuf != NULL) {
+                    codecBuffer->setRange(0, mediaBuf->size());
+                    memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
+
+                    sp<MetaData> meta_data = mediaBuf->meta_data();
+                    cryptInfo = NuPlayerDrm::getSampleCryptoInfo(meta_data);
+
+                    // since getMediaBuffer() has incremented the refCount
+                    mediaBuf->release();
+                } else { // No mediaBuf
+                    ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
+                            buffer.get());
+                    handleError(UNKNOWN_ERROR);
+                    return false;
+                }
+            } // buffer->data()
+        } // needsCopy
+
+        status_t err;
+        AString errorDetailMsg;
+        if (cryptInfo != NULL) {
+            err = mCodec->queueSecureInputBuffer(
+                    bufferIx,
+                    codecBuffer->offset(),
+                    cryptInfo->subSamples,
+                    cryptInfo->numSubSamples,
+                    cryptInfo->key,
+                    cryptInfo->iv,
+                    cryptInfo->mode,
+                    cryptInfo->pattern,
+                    timeUs,
+                    flags,
+                    &errorDetailMsg);
+            // synchronous call so done with cryptInfo here
+            free(cryptInfo);
+        } else {
+            err = mCodec->queueInputBuffer(
+                    bufferIx,
+                    codecBuffer->offset(),
+                    codecBuffer->size(),
+                    timeUs,
+                    flags,
+                    &errorDetailMsg);
+        } // no cryptInfo
+
         if (err != OK) {
-            ALOGE("Failed to queue input buffer for %s (err=%d)",
-                    mComponentName.c_str(), err);
+            ALOGE("onInputBufferFetched: queue%sInputBuffer failed for %s (err=%d, %s)",
+                    (cryptInfo != NULL ? "Secure" : ""),
+                    mComponentName.c_str(), err, errorDetailMsg.c_str());
             handleError(err);
         } else {
             mInputBufferIsDequeued.editItemAt(bufferIx) = false;
         }
-    }
+
+    }   // buffer != NULL
     return true;
 }