stagefright: ICrypto: enable passing secure buffers in native_handle

Previously secure buffers were passed as opaque
void * values, which no longer works since
mediadrmserver is now a separate process from
mediaserver.

Bug: 22990512
Change-Id: I5c458ba19e78e20d1bd5a5899df0bce16f71bfd8
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index 5e324ad..a4bfaf8 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -46,8 +46,14 @@
 
     virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
 
+    enum DestinationType {
+        kDestinationTypeVmPointer,    // non-secure
+        kDestinationTypeOpaqueHandle, // secure
+        kDestinationTypeNativeHandle  // secure
+    };
+
     virtual ssize_t decrypt(
-            bool secure,
+            DestinationType dstType,
             const uint8_t key[16],
             const uint8_t iv[16],
             CryptoPlugin::Mode mode,
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 79059c6..26dd2c9 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -95,7 +95,7 @@
     }
 
     virtual ssize_t decrypt(
-            bool secure,
+            DestinationType dstType,
             const uint8_t key[16],
             const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
@@ -105,7 +105,7 @@
             AString *errorDetailMsg) {
         Parcel data, reply;
         data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-        data.writeInt32(secure);
+        data.writeInt32((int32_t)dstType);
         data.writeInt32(mode);
         data.writeInt32(pattern.mEncryptBlocks);
         data.writeInt32(pattern.mSkipBlocks);
@@ -136,8 +136,12 @@
         data.writeInt32(numSubSamples);
         data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
 
-        if (secure) {
+        if (dstType == kDestinationTypeNativeHandle) {
+            data.writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
+        } else if (dstType == kDestinationTypeOpaqueHandle) {
             data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
+        } else {
+            dstType = kDestinationTypeVmPointer;
         }
 
         remote()->transact(DECRYPT, data, &reply);
@@ -148,7 +152,7 @@
             errorDetailMsg->setTo(reply.readCString());
         }
 
-        if (!secure && result >= 0) {
+        if (dstType == kDestinationTypeVmPointer && result >= 0) {
             reply.read(dstPtr, result);
         }
 
@@ -276,7 +280,7 @@
         {
             CHECK_INTERFACE(ICrypto, data, reply);
 
-            bool secure = data.readInt32() != 0;
+            DestinationType dstType = (DestinationType)data.readInt32();
             CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
             CryptoPlugin::Pattern pattern;
             pattern.mEncryptBlocks = data.readInt32();
@@ -306,10 +310,16 @@
                     subSamples,
                     sizeof(CryptoPlugin::SubSample) * numSubSamples);
 
-            void *secureBufferId, *dstPtr;
-            if (secure) {
+            native_handle_t *nativeHandle = NULL;
+            void *secureBufferId = NULL, *dstPtr;
+            if (dstType == kDestinationTypeNativeHandle) {
+                nativeHandle = data.readNativeHandle();
+                dstPtr = static_cast<void *>(nativeHandle);
+            } else if (dstType == kDestinationTypeOpaqueHandle) {
                 secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
+                dstPtr = secureBufferId;
             } else {
+                dstType = kDestinationTypeVmPointer;
                 dstPtr = malloc(totalSize);
             }
 
@@ -340,13 +350,13 @@
                 result = -EINVAL;
             } else {
                 result = decrypt(
-                    secure,
+                    dstType,
                     key,
                     iv,
                     mode, pattern,
                     sharedBuffer, offset,
                     subSamples, numSubSamples,
-                    secure ? secureBufferId : dstPtr,
+                    dstPtr,
                     &errorDetailMsg);
             }
 
@@ -356,13 +366,21 @@
                 reply->writeCString(errorDetailMsg.c_str());
             }
 
-            if (!secure) {
+            if (dstType == kDestinationTypeVmPointer) {
                 if (result >= 0) {
                     CHECK_LE(result, static_cast<ssize_t>(totalSize));
                     reply->write(dstPtr, result);
                 }
                 free(dstPtr);
                 dstPtr = NULL;
+            } else if (dstType == kDestinationTypeNativeHandle) {
+                int err;
+                if ((err = native_handle_close(nativeHandle)) < 0) {
+                    ALOGW("secure buffer native_handle_close failed: %d", err);
+                }
+                if ((err = native_handle_delete(nativeHandle)) < 0) {
+                    ALOGW("secure buffer native_handle_delete failed: %d", err);
+                }
             }
 
             delete[] subSamples;
diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp
index b57f6ef..9165b9d 100644
--- a/media/libmediaplayerservice/Crypto.cpp
+++ b/media/libmediaplayerservice/Crypto.cpp
@@ -235,7 +235,7 @@
 }
 
 ssize_t Crypto::decrypt(
-        bool secure,
+        DestinationType dstType,
         const uint8_t key[16],
         const uint8_t iv[16],
         CryptoPlugin::Mode mode,
@@ -257,7 +257,8 @@
     const void *srcPtr = static_cast<uint8_t *>(sharedBuffer->pointer()) + offset;
 
     return mPlugin->decrypt(
-            secure, key, iv, mode, pattern, srcPtr, subSamples, numSubSamples, dstPtr,
+            dstType != kDestinationTypeVmPointer,
+            key, iv, mode, pattern, srcPtr, subSamples, numSubSamples, dstPtr,
             errorDetailMsg);
 }
 
diff --git a/media/libmediaplayerservice/Crypto.h b/media/libmediaplayerservice/Crypto.h
index 7705f30..7d181d3 100644
--- a/media/libmediaplayerservice/Crypto.h
+++ b/media/libmediaplayerservice/Crypto.h
@@ -50,7 +50,7 @@
     virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
 
     virtual ssize_t decrypt(
-            bool secure,
+            DestinationType dstType,
             const uint8_t key[16],
             const uint8_t iv[16],
             CryptoPlugin::Mode mode,
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 1be9a3e..fb1f401 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2494,11 +2494,18 @@
         AString *errorDetailMsg;
         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
 
-        // TODO: use different decrypt based on native handle or not
-        // use native handle if we have it; otherwise, use opaque handle
-        void *dst_pointer = (void *)info->mNativeHandle.get() ? : info->mData->base();
+        void *dst_pointer = info->mData->base();
+        ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
+
+        if (info->mNativeHandle != NULL) {
+            dst_pointer = (void *)info->mNativeHandle.get();
+            dst_type = ICrypto::kDestinationTypeNativeHandle;
+        } else if ((mFlags & kFlagIsSecure) == 0) {
+            dst_type = ICrypto::kDestinationTypeVmPointer;
+        }
+
         ssize_t result = mCrypto->decrypt(
-                (mFlags & kFlagIsSecure) != 0,
+                dst_type,
                 key,
                 iv,
                 mode,