Plumbing to reflect minor changes in the HDCP module API that allow for

support of _decryption_ modules in addition to what we already supported.

Change-Id: Ic37b87dc170ba8def3817991d25df798f21e950b
diff --git a/include/media/IHDCP.h b/include/media/IHDCP.h
index a0613c7..6d27b18 100644
--- a/include/media/IHDCP.h
+++ b/include/media/IHDCP.h
@@ -45,18 +45,34 @@
     // Request to shutdown the active HDCP session.
     virtual status_t shutdownAsync() = 0;
 
-    // Encrypt a data according to the HDCP spec. The data is to be
-    // encrypted in-place, only size bytes of data should be read/write,
-    // even if the size is not a multiple of 128 bit (16 bytes).
+    // ENCRYPTION only:
+    // Encrypt data according to the HDCP spec. "size" bytes of data are
+    // available at "inData" (virtual address), "size" may not be a multiple
+    // of 128 bits (16 bytes). An equal number of encrypted bytes should be
+    // written to the buffer at "outData" (virtual address).
     // This operation is to be synchronous, i.e. this call does not return
     // until outData contains size bytes of encrypted data.
     // streamCTR will be assigned by the caller (to 0 for the first PES stream,
     // 1 for the second and so on)
-    // inputCTR will be maintained by the callee for each PES stream.
+    // inputCTR _will_be_maintained_by_the_callee_ for each PES stream.
     virtual status_t encrypt(
             const void *inData, size_t size, uint32_t streamCTR,
             uint64_t *outInputCTR, void *outData) = 0;
 
+    // DECRYPTION only:
+    // Decrypt data according to the HDCP spec.
+    // "size" bytes of encrypted data are available at "inData"
+    // (virtual address), "size" may not be a multiple of 128 bits (16 bytes).
+    // An equal number of decrypted bytes should be written to the buffer
+    // at "outData" (virtual address).
+    // This operation is to be synchronous, i.e. this call does not return
+    // until outData contains size bytes of decrypted data.
+    // Both streamCTR and inputCTR will be provided by the caller.
+    virtual status_t decrypt(
+            const void *inData, size_t size,
+            uint32_t streamCTR, uint64_t inputCTR,
+            void *outData) = 0;
+
 private:
     DISALLOW_EVIL_CONSTRUCTORS(IHDCP);
 };
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 44db5bc..b29d3c7 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -52,7 +52,7 @@
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0;
     virtual sp<IOMX>            getOMX() = 0;
     virtual sp<ICrypto>         makeCrypto() = 0;
-    virtual sp<IHDCP>           makeHDCP() = 0;
+    virtual sp<IHDCP>           makeHDCP(bool createEncryptionModule) = 0;
 
     // Connects to a remote display.
     // 'iface' specifies the address of the local interface on which to listen for
diff --git a/media/libmedia/IHDCP.cpp b/media/libmedia/IHDCP.cpp
index 493f5a4..f13addc 100644
--- a/media/libmedia/IHDCP.cpp
+++ b/media/libmedia/IHDCP.cpp
@@ -31,6 +31,7 @@
     HDCP_INIT_ASYNC,
     HDCP_SHUTDOWN_ASYNC,
     HDCP_ENCRYPT,
+    HDCP_DECRYPT,
 };
 
 struct BpHDCPObserver : public BpInterface<IHDCPObserver> {
@@ -106,6 +107,29 @@
 
         return err;
     }
+
+    virtual status_t decrypt(
+            const void *inData, size_t size,
+            uint32_t streamCTR, uint64_t inputCTR,
+            void *outData) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
+        data.writeInt32(size);
+        data.write(inData, size);
+        data.writeInt32(streamCTR);
+        data.writeInt64(inputCTR);
+        remote()->transact(HDCP_DECRYPT, data, &reply);
+
+        status_t err = reply.readInt32();
+
+        if (err != OK) {
+            return err;
+        }
+
+        reply.read(outData, size);
+
+        return err;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(HDCP, "android.hardware.IHDCP");
@@ -198,6 +222,31 @@
             return OK;
         }
 
+        case HDCP_DECRYPT:
+        {
+            size_t size = data.readInt32();
+
+            void *inData = malloc(2 * size);
+            void *outData = (uint8_t *)inData + size;
+
+            data.read(inData, size);
+
+            uint32_t streamCTR = data.readInt32();
+            uint64_t inputCTR = data.readInt64();
+            status_t err = decrypt(inData, size, streamCTR, inputCTR, outData);
+
+            reply->writeInt32(err);
+
+            if (err == OK) {
+                reply->write(outData, size);
+            }
+
+            free(inData);
+            inData = outData = NULL;
+
+            return OK;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index ae76c10..a95f4c9 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -123,9 +123,10 @@
         return interface_cast<ICrypto>(reply.readStrongBinder());
     }
 
-    virtual sp<IHDCP> makeHDCP() {
+    virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeInt32(createEncryptionModule);
         remote()->transact(MAKE_HDCP, data, &reply);
         return interface_cast<IHDCP>(reply.readStrongBinder());
     }
@@ -226,7 +227,8 @@
         } break;
         case MAKE_HDCP: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            sp<IHDCP> hdcp = makeHDCP();
+            bool createEncryptionModule = data.readInt32();
+            sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);
             reply->writeStrongBinder(hdcp->asBinder());
             return NO_ERROR;
         } break;
diff --git a/media/libmediaplayerservice/HDCP.cpp b/media/libmediaplayerservice/HDCP.cpp
index 09b9719..469a02e 100644
--- a/media/libmediaplayerservice/HDCP.cpp
+++ b/media/libmediaplayerservice/HDCP.cpp
@@ -26,8 +26,9 @@
 
 namespace android {
 
-HDCP::HDCP()
-    : mLibHandle(NULL),
+HDCP::HDCP(bool createEncryptionModule)
+    : mIsEncryptionModule(createEncryptionModule),
+      mLibHandle(NULL),
       mHDCPModule(NULL) {
     mLibHandle = dlopen("libstagefright_hdcp.so", RTLD_NOW);
 
@@ -40,7 +41,10 @@
             void *, HDCPModule::ObserverFunc);
 
     CreateHDCPModuleFunc createHDCPModule =
-        (CreateHDCPModuleFunc)dlsym(mLibHandle, "createHDCPModule");
+        mIsEncryptionModule
+            ? (CreateHDCPModuleFunc)dlsym(mLibHandle, "createHDCPModule")
+            : (CreateHDCPModuleFunc)dlsym(
+                    mLibHandle, "createHDCPModuleForDecryption");
 
     if (createHDCPModule == NULL) {
         ALOGE("Unable to find symbol 'createHDCPModule'.");
@@ -101,6 +105,8 @@
         uint64_t *outInputCTR, void *outData) {
     Mutex::Autolock autoLock(mLock);
 
+    CHECK(mIsEncryptionModule);
+
     if (mHDCPModule == NULL) {
         *outInputCTR = 0;
 
@@ -110,6 +116,20 @@
     return mHDCPModule->encrypt(inData, size, streamCTR, outInputCTR, outData);
 }
 
+status_t HDCP::decrypt(
+        const void *inData, size_t size,
+        uint32_t streamCTR, uint64_t outInputCTR, void *outData) {
+    Mutex::Autolock autoLock(mLock);
+
+    CHECK(!mIsEncryptionModule);
+
+    if (mHDCPModule == NULL) {
+        return NO_INIT;
+    }
+
+    return mHDCPModule->decrypt(inData, size, streamCTR, outInputCTR, outData);
+}
+
 // static
 void HDCP::ObserveWrapper(void *me, int msg, int ext1, int ext2) {
     static_cast<HDCP *>(me)->observe(msg, ext1, ext2);
diff --git a/media/libmediaplayerservice/HDCP.h b/media/libmediaplayerservice/HDCP.h
index b2fc457..42e6467 100644
--- a/media/libmediaplayerservice/HDCP.h
+++ b/media/libmediaplayerservice/HDCP.h
@@ -24,7 +24,7 @@
 namespace android {
 
 struct HDCP : public BnHDCP {
-    HDCP();
+    HDCP(bool createEncryptionModule);
     virtual ~HDCP();
 
     virtual status_t setObserver(const sp<IHDCPObserver> &observer);
@@ -35,9 +35,15 @@
             const void *inData, size_t size, uint32_t streamCTR,
             uint64_t *outInputCTR, void *outData);
 
+    virtual status_t decrypt(
+            const void *inData, size_t size,
+            uint32_t streamCTR, uint64_t outInputCTR, void *outData);
+
 private:
     Mutex mLock;
 
+    bool mIsEncryptionModule;
+
     void *mLibHandle;
     HDCPModule *mHDCPModule;
     sp<IHDCPObserver> mObserver;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 749f48c..f932131 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -285,8 +285,8 @@
     return new Crypto;
 }
 
-sp<IHDCP> MediaPlayerService::makeHDCP() {
-    return new HDCP;
+sp<IHDCP> MediaPlayerService::makeHDCP(bool createEncryptionModule) {
+    return new HDCP(createEncryptionModule);
 }
 
 sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index d2d8939..2d2a09d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -249,7 +249,7 @@
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
     virtual sp<IOMX>            getOMX();
     virtual sp<ICrypto>         makeCrypto();
-    virtual sp<IHDCP>           makeHDCP();
+    virtual sp<IHDCP>           makeHDCP(bool createEncryptionModule);
 
     virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
             const String8& iface);
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 0fed19b..981d5f9 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -1637,7 +1637,7 @@
     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
     CHECK(service != NULL);
 
-    mHDCP = service->makeHDCP();
+    mHDCP = service->makeHDCP(true /* createEncryptionModule */);
 
     if (mHDCP == NULL) {
         return ERROR_UNSUPPORTED;