MediaDrm API update

Clarify offline usage of sessions and keys and implement
implement CryptoSession to support additional crypto use
cases.

Change-Id: I5d8000ce7e1dd7eba08969fc50296c9e1456c4fc
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index 3b13ec6..1641b56 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -33,10 +33,11 @@
     DESTROY_PLUGIN,
     OPEN_SESSION,
     CLOSE_SESSION,
-    GET_LICENSE_REQUEST,
-    PROVIDE_LICENSE_RESPONSE,
-    REMOVE_LICENSE,
-    QUERY_LICENSE_STATUS,
+    GET_KEY_REQUEST,
+    PROVIDE_KEY_RESPONSE,
+    REMOVE_KEYS,
+    RESTORE_KEYS,
+    QUERY_KEY_STATUS,
     GET_PROVISION_REQUEST,
     PROVIDE_PROVISION_RESPONSE,
     GET_SECURE_STOPS,
@@ -44,7 +45,13 @@
     GET_PROPERTY_STRING,
     GET_PROPERTY_BYTE_ARRAY,
     SET_PROPERTY_STRING,
-    SET_PROPERTY_BYTE_ARRAY
+    SET_PROPERTY_BYTE_ARRAY,
+    SET_CIPHER_ALGORITHM,
+    SET_MAC_ALGORITHM,
+    ENCRYPT,
+    DECRYPT,
+    SIGN,
+    VERIFY
 };
 
 struct BpDrm : public BpInterface<IDrm> {
@@ -92,9 +99,7 @@
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
         remote()->transact(OPEN_SESSION, data, &reply);
-        uint32_t size = reply.readInt32();
-        sessionId.insertAt((size_t)0, size);
-        reply.read(sessionId.editArray(), size);
+        readVector(reply, sessionId);
 
         return reply.readInt32();
     }
@@ -103,80 +108,81 @@
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        data.writeInt32(sessionId.size());
-        data.write(sessionId.array(), sessionId.size());
+        writeVector(data, sessionId);
         remote()->transact(CLOSE_SESSION, data, &reply);
 
         return reply.readInt32();
     }
 
     virtual status_t
-        getLicenseRequest(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &initData,
-                          String8 const &mimeType, DrmPlugin::LicenseType licenseType,
-                          KeyedVector<String8, String8> const &optionalParameters,
-                          Vector<uint8_t> &request, String8 &defaultUrl) {
+        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) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        data.writeInt32(sessionId.size());
-        data.write(sessionId.array(), sessionId.size());
-
-        data.writeInt32(initData.size());
-        data.write(initData.array(), initData.size());
-
+        writeVector(data, sessionId);
+        writeVector(data, initData);
         data.writeString8(mimeType);
-        data.writeInt32((uint32_t)licenseType);
+        data.writeInt32((uint32_t)keyType);
 
         data.writeInt32(optionalParameters.size());
         for (size_t i = 0; i < optionalParameters.size(); ++i) {
             data.writeString8(optionalParameters.keyAt(i));
             data.writeString8(optionalParameters.valueAt(i));
         }
-        remote()->transact(GET_LICENSE_REQUEST, data, &reply);
+        remote()->transact(GET_KEY_REQUEST, data, &reply);
 
-        uint32_t len = reply.readInt32();
-        request.insertAt((size_t)0, len);
-        reply.read(request.editArray(), len);
+        readVector(reply, request);
         defaultUrl = reply.readString8();
 
         return reply.readInt32();
     }
 
-    virtual status_t provideLicenseResponse(Vector<uint8_t> const &sessionId,
-                                            Vector<uint8_t> const &response) {
+    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                        Vector<uint8_t> const &response,
+                                        Vector<uint8_t> &keySetId) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
-        data.writeInt32(sessionId.size());
-        data.write(sessionId.array(), sessionId.size());
-        data.writeInt32(response.size());
-        data.write(response.array(), response.size());
-        remote()->transact(PROVIDE_LICENSE_RESPONSE, data, &reply);
+        writeVector(data, sessionId);
+        writeVector(data, response);
+        remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
+        readVector(reply, keySetId);
 
         return reply.readInt32();
     }
 
-    virtual status_t removeLicense(Vector<uint8_t> const &sessionId) {
+    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        data.writeInt32(sessionId.size());
-        data.write(sessionId.array(), sessionId.size());
-        remote()->transact(REMOVE_LICENSE, data, &reply);
+        writeVector(data, keySetId);
+        remote()->transact(REMOVE_KEYS, data, &reply);
 
         return reply.readInt32();
     }
 
-    virtual status_t queryLicenseStatus(Vector<uint8_t> const &sessionId,
+    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+                                 Vector<uint8_t> const &keySetId) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        writeVector(data, keySetId);
+        remote()->transact(RESTORE_KEYS, data, &reply);
+
+        return reply.readInt32();
+    }
+
+    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
                                         KeyedVector<String8, String8> &infoMap) const {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        data.writeInt32(sessionId.size());
-        data.write(sessionId.array(), sessionId.size());
-
-        remote()->transact(QUERY_LICENSE_STATUS, data, &reply);
+        writeVector(data, sessionId);
+        remote()->transact(QUERY_KEY_STATUS, data, &reply);
 
         infoMap.clear();
         size_t count = reply.readInt32();
@@ -195,9 +201,7 @@
 
         remote()->transact(GET_PROVISION_REQUEST, data, &reply);
 
-        uint32_t len = reply.readInt32();
-        request.insertAt((size_t)0, len);
-        reply.read(request.editArray(), len);
+        readVector(reply, request);
         defaultUrl = reply.readString8();
 
         return reply.readInt32();
@@ -207,8 +211,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        data.writeInt32(response.size());
-        data.write(response.array(), response.size());
+        writeVector(data, response);
         remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
 
         return reply.readInt32();
@@ -224,9 +227,7 @@
         uint32_t count = reply.readInt32();
         for (size_t i = 0; i < count; i++) {
             Vector<uint8_t> secureStop;
-            uint32_t len = reply.readInt32();
-            secureStop.insertAt((size_t)0, len);
-            reply.read(secureStop.editArray(), len);
+            readVector(reply, secureStop);
             secureStops.push_back(secureStop);
         }
         return reply.readInt32();
@@ -236,8 +237,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        data.writeInt32(ssRelease.size());
-        data.write(ssRelease.array(), ssRelease.size());
+        writeVector(data, ssRelease);
         remote()->transact(RELEASE_SECURE_STOPS, data, &reply);
 
         return reply.readInt32();
@@ -261,10 +261,7 @@
         data.writeString8(name);
         remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply);
 
-        uint32_t len = reply.readInt32();
-        value.insertAt((size_t)0, len);
-        reply.read(value.editArray(), len);
-
+        readVector(reply, value);
         return reply.readInt32();
     }
 
@@ -285,15 +282,120 @@
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
         data.writeString8(name);
-        data.writeInt32(value.size());
-        data.write(value.array(), value.size());
+        writeVector(data, value);
         remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply);
 
         return reply.readInt32();
     }
 
 
+    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                        String8 const &algorithm) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        data.writeString8(algorithm);
+        remote()->transact(SET_CIPHER_ALGORITHM, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                     String8 const &algorithm) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        data.writeString8(algorithm);
+        remote()->transact(SET_MAC_ALGORITHM, data, &reply);
+        return reply.readInt32();
+    }
+
+    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) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        writeVector(data, keyId);
+        writeVector(data, input);
+        writeVector(data, iv);
+
+        remote()->transact(ENCRYPT, data, &reply);
+        readVector(reply, output);
+
+        return reply.readInt32();
+    }
+
+    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) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        writeVector(data, keyId);
+        writeVector(data, input);
+        writeVector(data, iv);
+
+        remote()->transact(DECRYPT, data, &reply);
+        readVector(reply, output);
+
+        return reply.readInt32();
+    }
+
+    virtual status_t sign(Vector<uint8_t> const &sessionId,
+                          Vector<uint8_t> const &keyId,
+                          Vector<uint8_t> const &message,
+                          Vector<uint8_t> &signature) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        writeVector(data, keyId);
+        writeVector(data, message);
+
+        remote()->transact(SIGN, data, &reply);
+        readVector(reply, signature);
+
+        return reply.readInt32();
+    }
+
+    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) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        writeVector(data, sessionId);
+        writeVector(data, keyId);
+        writeVector(data, message);
+        writeVector(data, signature);
+
+        remote()->transact(VERIFY, data, &reply);
+        match = (bool)reply.readInt32();
+        return reply.readInt32();
+    }
+
 private:
+    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
+        uint32_t size = reply.readInt32();
+        vector.insertAt((size_t)0, size);
+        reply.read(vector.editArray(), size);
+    }
+
+    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
+        data.writeInt32(vector.size());
+        data.write(vector.array(), vector.size());
+    }
+
     DISALLOW_EVIL_CONSTRUCTORS(BpDrm);
 };
 
@@ -301,6 +403,17 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
+    uint32_t size = data.readInt32();
+    vector.insertAt((size_t)0, size);
+    data.read(vector.editArray(), size);
+}
+
+void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
+    reply->writeInt32(vector.size());
+    reply->write(vector.array(), vector.size());
+}
+
 status_t BnDrm::onTransact(
     uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
     switch (code) {
@@ -341,8 +454,7 @@
             CHECK_INTERFACE(IDrm, data, reply);
             Vector<uint8_t> sessionId;
             status_t result = openSession(sessionId);
-            reply->writeInt32(sessionId.size());
-            reply->write(sessionId.array(), sessionId.size());
+            writeVector(reply, sessionId);
             reply->writeInt32(result);
             return OK;
         }
@@ -351,28 +463,20 @@
         {
             CHECK_INTERFACE(IDrm, data, reply);
             Vector<uint8_t> sessionId;
-            uint32_t size = data.readInt32();
-            sessionId.insertAt((size_t)0, size);
-            data.read(sessionId.editArray(), size);
+            readVector(data, sessionId);
             reply->writeInt32(closeSession(sessionId));
             return OK;
         }
 
-        case GET_LICENSE_REQUEST:
+        case GET_KEY_REQUEST:
         {
             CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            uint32_t size = data.readInt32();
-            sessionId.insertAt((size_t)0, size);
-            data.read(sessionId.editArray(), size);
+            Vector<uint8_t> sessionId, initData;
 
-            Vector<uint8_t> initData;
-            size = data.readInt32();
-            initData.insertAt((size_t)0, size);
-            data.read(initData.editArray(), size);
-
+            readVector(data, sessionId);
+            readVector(data, initData);
             String8 mimeType = data.readString8();
-            DrmPlugin::LicenseType licenseType = (DrmPlugin::LicenseType)data.readInt32();
+            DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
 
             KeyedVector<String8, String8> optionalParameters;
             uint32_t count = data.readInt32();
@@ -386,55 +490,54 @@
             Vector<uint8_t> request;
             String8 defaultUrl;
 
-            status_t result = getLicenseRequest(sessionId, initData,
-                                                mimeType, licenseType,
-                                                optionalParameters,
-                                                request, defaultUrl);
-            reply->writeInt32(request.size());
-            reply->write(request.array(), request.size());
+            status_t result = getKeyRequest(sessionId, initData,
+                                            mimeType, keyType,
+                                            optionalParameters,
+                                            request, defaultUrl);
+            writeVector(reply, request);
             reply->writeString8(defaultUrl);
             reply->writeInt32(result);
             return OK;
         }
 
-        case PROVIDE_LICENSE_RESPONSE:
+        case PROVIDE_KEY_RESPONSE:
         {
             CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            uint32_t size = data.readInt32();
-            sessionId.insertAt((size_t)0, size);
-            data.read(sessionId.editArray(), size);
-            Vector<uint8_t> response;
-            size = data.readInt32();
-            response.insertAt((size_t)0, size);
-            data.read(response.editArray(), size);
-
-            reply->writeInt32(provideLicenseResponse(sessionId, response));
+            Vector<uint8_t> sessionId, response, keySetId;
+            readVector(data, sessionId);
+            readVector(data, response);
+            uint32_t result = provideKeyResponse(sessionId, response, keySetId);
+            writeVector(reply, keySetId);
+            reply->writeInt32(result);
             return OK;
         }
 
-        case REMOVE_LICENSE:
+        case REMOVE_KEYS:
         {
             CHECK_INTERFACE(IDrm, data, reply);
-            Vector<uint8_t> sessionId;
-            uint32_t size = data.readInt32();
-            sessionId.insertAt((size_t)0, size);
-            data.read(sessionId.editArray(), size);
-            reply->writeInt32(removeLicense(sessionId));
+            Vector<uint8_t> keySetId;
+            readVector(data, keySetId);
+            reply->writeInt32(removeKeys(keySetId));
             return OK;
         }
 
-        case QUERY_LICENSE_STATUS:
+        case RESTORE_KEYS:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId, keySetId;
+            readVector(data, sessionId);
+            readVector(data, keySetId);
+            reply->writeInt32(restoreKeys(sessionId, keySetId));
+            return OK;
+        }
+
+        case QUERY_KEY_STATUS:
         {
             CHECK_INTERFACE(IDrm, data, reply);
             Vector<uint8_t> sessionId;
-            uint32_t size = data.readInt32();
-            sessionId.insertAt((size_t)0, size);
-            data.read(sessionId.editArray(), size);
+            readVector(data, sessionId);
             KeyedVector<String8, String8> infoMap;
-
-            status_t result = queryLicenseStatus(sessionId, infoMap);
-
+            status_t result = queryKeyStatus(sessionId, infoMap);
             size_t count = infoMap.size();
             reply->writeInt32(count);
             for (size_t i = 0; i < count; ++i) {
@@ -451,8 +554,7 @@
             Vector<uint8_t> request;
             String8 defaultUrl;
             status_t result = getProvisionRequest(request, defaultUrl);
-            reply->writeInt32(request.size());
-            reply->write(request.array(), request.size());
+            writeVector(reply, request);
             reply->writeString8(defaultUrl);
             reply->writeInt32(result);
             return OK;
@@ -462,11 +564,8 @@
         {
             CHECK_INTERFACE(IDrm, data, reply);
             Vector<uint8_t> response;
-            uint32_t size = data.readInt32();
-            response.insertAt((size_t)0, size);
-            data.read(response.editArray(), size);
+            readVector(data, response);
             reply->writeInt32(provideProvisionResponse(response));
-
             return OK;
         }
 
@@ -491,9 +590,7 @@
         {
             CHECK_INTERFACE(IDrm, data, reply);
             Vector<uint8_t> ssRelease;
-            uint32_t size = data.readInt32();
-            ssRelease.insertAt((size_t)0, size);
-            data.read(ssRelease.editArray(), size);
+            readVector(data, ssRelease);
             reply->writeInt32(releaseSecureStops(ssRelease));
             return OK;
         }
@@ -515,8 +612,7 @@
             String8 name = data.readString8();
             Vector<uint8_t> value;
             status_t result = getPropertyByteArray(name, value);
-            reply->writeInt32(value.size());
-            reply->write(value.array(), value.size());
+            writeVector(reply, value);
             reply->writeInt32(result);
             return OK;
         }
@@ -535,15 +631,89 @@
             CHECK_INTERFACE(IDrm, data, reply);
             String8 name = data.readString8();
             Vector<uint8_t> value;
-            size_t count = data.readInt32();
-            value.insertAt((size_t)0, count);
-            data.read(value.editArray(), count);
+            readVector(data, value);
             reply->writeInt32(setPropertyByteArray(name, value));
             return OK;
         }
 
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
+        case SET_CIPHER_ALGORITHM:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId;
+            readVector(data, sessionId);
+            String8 algorithm = data.readString8();
+            reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
+            return OK;
+        }
+
+        case SET_MAC_ALGORITHM:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId;
+            readVector(data, sessionId);
+            String8 algorithm = data.readString8();
+            reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
+            return OK;
+        }
+
+        case ENCRYPT:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId, keyId, input, iv, output;
+            readVector(data, sessionId);
+            readVector(data, keyId);
+            readVector(data, input);
+            readVector(data, iv);
+            uint32_t result = encrypt(sessionId, keyId, input, iv, output);
+            writeVector(reply, output);
+            reply->writeInt32(result);
+            return OK;
+        }
+
+        case DECRYPT:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId, keyId, input, iv, output;
+            readVector(data, sessionId);
+            readVector(data, keyId);
+            readVector(data, input);
+            readVector(data, iv);
+            uint32_t result = decrypt(sessionId, keyId, input, iv, output);
+            writeVector(reply, output);
+            reply->writeInt32(result);
+            return OK;
+        }
+
+        case SIGN:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId, keyId, message, signature;
+            readVector(data, sessionId);
+            readVector(data, keyId);
+            readVector(data, message);
+            uint32_t result = sign(sessionId, keyId, message, signature);
+            writeVector(reply, signature);
+            reply->writeInt32(result);
+            return OK;
+        }
+
+        case VERIFY:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            Vector<uint8_t> sessionId, keyId, message, signature;
+            readVector(data, sessionId);
+            readVector(data, keyId);
+            readVector(data, message);
+            readVector(data, signature);
+            bool match;
+            uint32_t result = verify(sessionId, keyId, message, signature, match);
+            reply->writeInt32(match);
+            reply->writeInt32(result);
+            return OK;
+        }
+
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
     }
 }