/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "IDrm" #include <utils/Log.h> #include <binder/Parcel.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AString.h> #include <mediadrm/IDrm.h> namespace android { enum { INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, IS_CRYPTO_SUPPORTED, CREATE_PLUGIN, DESTROY_PLUGIN, OPEN_SESSION, CLOSE_SESSION, GET_KEY_REQUEST, PROVIDE_KEY_RESPONSE, REMOVE_KEYS, RESTORE_KEYS, QUERY_KEY_STATUS, GET_PROVISION_REQUEST, PROVIDE_PROVISION_RESPONSE, GET_SECURE_STOPS, RELEASE_SECURE_STOPS, GET_PROPERTY_STRING, GET_PROPERTY_BYTE_ARRAY, SET_PROPERTY_STRING, SET_PROPERTY_BYTE_ARRAY, GET_METRICS, SET_CIPHER_ALGORITHM, SET_MAC_ALGORITHM, ENCRYPT, DECRYPT, SIGN, SIGN_RSA, VERIFY, SET_LISTENER, GET_SECURE_STOP, REMOVE_ALL_SECURE_STOPS, GET_HDCP_LEVELS, GET_NUMBER_OF_SESSIONS, GET_SECURITY_LEVEL, REMOVE_SECURE_STOP, GET_SECURE_STOP_IDS }; struct BpDrm : public BpInterface<IDrm> { explicit BpDrm(const sp<IBinder> &impl) : BpInterface<IDrm>(impl) { } virtual status_t initCheck() const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(INIT_CHECK, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.write(uuid, 16); data.writeString8(mimeType); status_t status = remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); if (status != OK) { ALOGE("isCryptoSchemeSupported: binder call failed: %d", status); return false; } return reply.readInt32() != 0; } virtual status_t createPlugin(const uint8_t uuid[16], const String8& appPackageName) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.write(uuid, 16); data.writeString8(appPackageName); status_t status = remote()->transact(CREATE_PLUGIN, data, &reply); if (status != OK) { ALOGE("createPlugin: binder call failed: %d", status); return status; } return reply.readInt32(); } virtual status_t destroyPlugin() { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(DESTROY_PLUGIN, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t> &sessionId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeInt32(securityLevel); status_t status = remote()->transact(OPEN_SESSION, data, &reply); if (status != OK) { return status; } readVector(reply, sessionId); return reply.readInt32(); } virtual status_t closeSession(Vector<uint8_t> const &sessionId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, sessionId); status_t status = remote()->transact(CLOSE_SESSION, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t 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, DrmPlugin::KeyRequestType *keyRequestType) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, sessionId); writeVector(data, initData); data.writeString8(mimeType); 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)); } status_t status = remote()->transact(GET_KEY_REQUEST, data, &reply); if (status != OK) { return status; } readVector(reply, request); defaultUrl = reply.readString8(); *keyRequestType = static_cast<DrmPlugin::KeyRequestType>(reply.readInt32()); return reply.readInt32(); } 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()); writeVector(data, sessionId); writeVector(data, response); status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply); if (status != OK) { return status; } readVector(reply, keySetId); return reply.readInt32(); } virtual status_t removeKeys(Vector<uint8_t> const &keySetId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, keySetId); status_t status = remote()->transact(REMOVE_KEYS, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } 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); status_t status = remote()->transact(RESTORE_KEYS, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId, KeyedVector<String8, String8> &infoMap) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, sessionId); status_t status = remote()->transact(QUERY_KEY_STATUS, data, &reply); if (status != OK) { return status; } infoMap.clear(); size_t count = reply.readInt32(); for (size_t i = 0; i < count; i++) { String8 key = reply.readString8(); String8 value = reply.readString8(); infoMap.add(key, value); } return reply.readInt32(); } virtual status_t getProvisionRequest(String8 const &certType, String8 const &certAuthority, Vector<uint8_t> &request, String8 &defaultUrl) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(certType); data.writeString8(certAuthority); status_t status = remote()->transact(GET_PROVISION_REQUEST, data, &reply); if (status != OK) { return status; } readVector(reply, request); defaultUrl = reply.readString8(); return reply.readInt32(); } virtual status_t provideProvisionResponse(Vector<uint8_t> const &response, Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, response); status_t status = remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply); if (status != OK) { return status; } readVector(reply, certificate); readVector(reply, wrappedKey); return reply.readInt32(); } virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(GET_SECURE_STOPS, data, &reply); if (status != OK) { return status; } secureStops.clear(); uint32_t count = reply.readInt32(); for (size_t i = 0; i < count; i++) { Vector<uint8_t> secureStop; readVector(reply, secureStop); secureStops.push_back(secureStop); } return reply.readInt32(); } virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(GET_SECURE_STOP_IDS, data, &reply); if (status != OK) { return status; } secureStopIds.clear(); uint32_t count = reply.readInt32(); for (size_t i = 0; i < count; i++) { Vector<uint8_t> secureStopId; readVector(reply, secureStopId); secureStopIds.push_back(secureStopId); } return reply.readInt32(); } virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, ssid); status_t status = remote()->transact(GET_SECURE_STOP, data, &reply); if (status != OK) { return status; } readVector(reply, secureStop); return reply.readInt32(); } virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, ssRelease); status_t status = remote()->transact(RELEASE_SECURE_STOPS, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, ssid); status_t status = remote()->transact(REMOVE_SECURE_STOP, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t removeAllSecureStops() { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(REMOVE_ALL_SECURE_STOPS, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t getPropertyString(String8 const &name, String8 &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); status_t status = remote()->transact(GET_PROPERTY_STRING, data, &reply); if (status != OK) { return status; } value = reply.readString8(); return reply.readInt32(); } virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connected, DrmPlugin::HdcpLevel *max) const { Parcel data, reply; if (connected == NULL || max == NULL) { return BAD_VALUE; } data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(GET_HDCP_LEVELS, data, &reply); if (status != OK) { return status; } *connected = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32()); *max = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32()); return reply.readInt32(); } virtual status_t getNumberOfSessions(uint32_t *open, uint32_t *max) const { Parcel data, reply; if (open == NULL || max == NULL) { return BAD_VALUE; } data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(GET_NUMBER_OF_SESSIONS, data, &reply); if (status != OK) { return status; } *open = reply.readInt32(); *max = reply.readInt32(); return reply.readInt32(); } virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId, DrmPlugin::SecurityLevel *level) const { Parcel data, reply; if (level == NULL) { return BAD_VALUE; } data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, sessionId); status_t status = remote()->transact(GET_SECURITY_LEVEL, data, &reply); if (status != OK) { return status; } *level = static_cast<DrmPlugin::SecurityLevel>(reply.readInt32()); return reply.readInt32(); } virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); status_t status = remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply); if (status != OK) { return status; } readVector(reply, value); return reply.readInt32(); } virtual status_t setPropertyString(String8 const &name, String8 const &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); data.writeString8(value); status_t status = remote()->transact(SET_PROPERTY_STRING, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t setPropertyByteArray(String8 const &name, Vector<uint8_t> const &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); writeVector(data, value); status_t status = remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply); if (status != OK) { return status; } return reply.readInt32(); } virtual status_t getMetrics(os::PersistableBundle *metrics) { if (metrics == NULL) { return BAD_VALUE; } Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); status_t status = remote()->transact(GET_METRICS, data, &reply); if (status != OK) { return status; } // The reply data is ordered as // 1) 32 bit integer reply followed by // 2) Serialized PersistableBundle containing metrics. status_t reply_status; if (reply.readInt32(&reply_status) != OK || reply_status != OK) { ALOGE("Failed to read getMetrics response code from parcel. %d", reply_status); return reply_status; } status = metrics->readFromParcel(&reply); if (status != OK) { ALOGE("Failed to read metrics from parcel. %d", status); return status; } return reply_status; } 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); status_t status = remote()->transact(SET_CIPHER_ALGORITHM, data, &reply); if (status != OK) { return status; } 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); status_t status = remote()->transact(SET_MAC_ALGORITHM, data, &reply); if (status != OK) { return status; } 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); status_t status = remote()->transact(ENCRYPT, data, &reply); if (status != OK) { return status; } 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); status_t status = remote()->transact(DECRYPT, data, &reply); if (status != OK) { return status; } 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); status_t status = remote()->transact(SIGN, data, &reply); if (status != OK) { return status; } 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); status_t status = remote()->transact(VERIFY, data, &reply); if (status != OK) { return status; } match = (bool)reply.readInt32(); return reply.readInt32(); } virtual status_t signRSA(Vector<uint8_t> const &sessionId, String8 const &algorithm, Vector<uint8_t> const &message, Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); writeVector(data, sessionId); data.writeString8(algorithm); writeVector(data, message); writeVector(data, wrappedKey); status_t status = remote()->transact(SIGN_RSA, data, &reply); if (status != OK) { return status; } readVector(reply, signature); return reply.readInt32(); } virtual status_t setListener(const sp<IDrmClient>& listener) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeStrongBinder(IInterface::asBinder(listener)); status_t status = remote()->transact(SET_LISTENER, data, &reply); if (status != OK) { return status; } 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); }; IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm"); //////////////////////////////////////////////////////////////////////////////// void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const { uint32_t size = data.readInt32(); if (vector.insertAt((size_t)0, size) < 0) { vector.clear(); } if (data.read(vector.editArray(), size) != NO_ERROR) { vector.clear(); android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0); } } 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) { case INIT_CHECK: { CHECK_INTERFACE(IDrm, data, reply); reply->writeInt32(initCheck()); return OK; } case IS_CRYPTO_SUPPORTED: { CHECK_INTERFACE(IDrm, data, reply); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); String8 mimeType = data.readString8(); reply->writeInt32(isCryptoSchemeSupported(uuid, mimeType)); return OK; } case CREATE_PLUGIN: { CHECK_INTERFACE(IDrm, data, reply); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); String8 appPackageName = data.readString8(); reply->writeInt32(createPlugin(uuid, appPackageName)); return OK; } case DESTROY_PLUGIN: { CHECK_INTERFACE(IDrm, data, reply); reply->writeInt32(destroyPlugin()); return OK; } case OPEN_SESSION: { CHECK_INTERFACE(IDrm, data, reply); DrmPlugin::SecurityLevel level = static_cast<DrmPlugin::SecurityLevel>(data.readInt32()); Vector<uint8_t> sessionId; status_t result = openSession(level, sessionId); writeVector(reply, sessionId); reply->writeInt32(result); return OK; } case CLOSE_SESSION: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> sessionId; readVector(data, sessionId); reply->writeInt32(closeSession(sessionId)); return OK; } case GET_KEY_REQUEST: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> sessionId, initData; readVector(data, sessionId); readVector(data, initData); String8 mimeType = data.readString8(); DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32(); KeyedVector<String8, String8> optionalParameters; uint32_t count = data.readInt32(); for (size_t i = 0; i < count; ++i) { String8 key, value; key = data.readString8(); value = data.readString8(); optionalParameters.add(key, value); } Vector<uint8_t> request; String8 defaultUrl; DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown; status_t result = getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters, request, defaultUrl, &keyRequestType); writeVector(reply, request); reply->writeString8(defaultUrl); reply->writeInt32(static_cast<int32_t>(keyRequestType)); reply->writeInt32(result); return OK; } case PROVIDE_KEY_RESPONSE: { CHECK_INTERFACE(IDrm, data, reply); 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_KEYS: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> keySetId; readVector(data, keySetId); reply->writeInt32(removeKeys(keySetId)); return OK; } 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; readVector(data, sessionId); KeyedVector<String8, String8> infoMap; status_t result = queryKeyStatus(sessionId, infoMap); size_t count = infoMap.size(); reply->writeInt32(count); for (size_t i = 0; i < count; ++i) { reply->writeString8(infoMap.keyAt(i)); reply->writeString8(infoMap.valueAt(i)); } reply->writeInt32(result); return OK; } case GET_PROVISION_REQUEST: { CHECK_INTERFACE(IDrm, data, reply); String8 certType = data.readString8(); String8 certAuthority = data.readString8(); Vector<uint8_t> request; String8 defaultUrl; status_t result = getProvisionRequest(certType, certAuthority, request, defaultUrl); writeVector(reply, request); reply->writeString8(defaultUrl); reply->writeInt32(result); return OK; } case PROVIDE_PROVISION_RESPONSE: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> response; Vector<uint8_t> certificate; Vector<uint8_t> wrappedKey; readVector(data, response); status_t result = provideProvisionResponse(response, certificate, wrappedKey); writeVector(reply, certificate); writeVector(reply, wrappedKey); reply->writeInt32(result); return OK; } case GET_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); List<Vector<uint8_t> > secureStops; status_t result = getSecureStops(secureStops); size_t count = secureStops.size(); reply->writeInt32(count); List<Vector<uint8_t> >::iterator iter = secureStops.begin(); while(iter != secureStops.end()) { size_t size = iter->size(); reply->writeInt32(size); reply->write(iter->array(), iter->size()); iter++; } reply->writeInt32(result); return OK; } case GET_SECURE_STOP_IDS: { CHECK_INTERFACE(IDrm, data, reply); List<Vector<uint8_t> > secureStopIds; status_t result = getSecureStopIds(secureStopIds); size_t count = secureStopIds.size(); reply->writeInt32(count); List<Vector<uint8_t> >::iterator iter = secureStopIds.begin(); while(iter != secureStopIds.end()) { size_t size = iter->size(); reply->writeInt32(size); reply->write(iter->array(), iter->size()); iter++; } reply->writeInt32(result); return OK; } case GET_SECURE_STOP: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> ssid, secureStop; readVector(data, ssid); status_t result = getSecureStop(ssid, secureStop); writeVector(reply, secureStop); reply->writeInt32(result); return OK; } case RELEASE_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> ssRelease; readVector(data, ssRelease); reply->writeInt32(releaseSecureStops(ssRelease)); return OK; } case REMOVE_SECURE_STOP: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> ssid; readVector(data, ssid); reply->writeInt32(removeSecureStop(ssid)); return OK; } case REMOVE_ALL_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); reply->writeInt32(removeAllSecureStops()); return OK; } case GET_HDCP_LEVELS: { CHECK_INTERFACE(IDrm, data, reply); DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown; DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown; status_t result = getHdcpLevels(&connected, &max); reply->writeInt32(connected); reply->writeInt32(max); reply->writeInt32(result); return OK; } case GET_NUMBER_OF_SESSIONS: { CHECK_INTERFACE(IDrm, data, reply); uint32_t open = 0, max = 0; status_t result = getNumberOfSessions(&open, &max); reply->writeInt32(open); reply->writeInt32(max); reply->writeInt32(result); return OK; } case GET_SECURITY_LEVEL: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> sessionId; readVector(data, sessionId); DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown; status_t result = getSecurityLevel(sessionId, &level); reply->writeInt32(level); reply->writeInt32(result); return OK; } case GET_PROPERTY_STRING: { CHECK_INTERFACE(IDrm, data, reply); String8 name = data.readString8(); String8 value; status_t result = getPropertyString(name, value); reply->writeString8(value); reply->writeInt32(result); return OK; } case GET_PROPERTY_BYTE_ARRAY: { CHECK_INTERFACE(IDrm, data, reply); String8 name = data.readString8(); Vector<uint8_t> value; status_t result = getPropertyByteArray(name, value); writeVector(reply, value); reply->writeInt32(result); return OK; } case SET_PROPERTY_STRING: { CHECK_INTERFACE(IDrm, data, reply); String8 name = data.readString8(); String8 value = data.readString8(); reply->writeInt32(setPropertyString(name, value)); return OK; } case SET_PROPERTY_BYTE_ARRAY: { CHECK_INTERFACE(IDrm, data, reply); String8 name = data.readString8(); Vector<uint8_t> value; readVector(data, value); reply->writeInt32(setPropertyByteArray(name, value)); return OK; } case GET_METRICS: { CHECK_INTERFACE(IDrm, data, reply); os::PersistableBundle metrics; status_t result = getMetrics(&metrics); // The reply data is ordered as // 1) 32 bit integer reply followed by // 2) Serialized PersistableBundle containing metrics. // Only write the metrics if the getMetrics result was // OK and we successfully added the status to reply. status_t parcel_result = reply->writeInt32(result); if (result == OK && parcel_result == OK) { parcel_result = metrics.writeToParcel(reply); } return parcel_result; } 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 = false; uint32_t result = verify(sessionId, keyId, message, signature, match); reply->writeInt32(match); reply->writeInt32(result); return OK; } case SIGN_RSA: { CHECK_INTERFACE(IDrm, data, reply); Vector<uint8_t> sessionId, message, wrappedKey, signature; readVector(data, sessionId); String8 algorithm = data.readString8(); readVector(data, message); readVector(data, wrappedKey); uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature); writeVector(reply, signature); reply->writeInt32(result); return OK; } case SET_LISTENER: { CHECK_INTERFACE(IDrm, data, reply); sp<IDrmClient> listener = interface_cast<IDrmClient>(data.readStrongBinder()); reply->writeInt32(setListener(listener)); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } } // namespace android