/* * 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 #include #include #include #include #include namespace android { enum { INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, IS_CRYPTO_SUPPORTED, CREATE_PLUGIN, DESTROY_PLUGIN, OPEN_SESSION, CLOSE_SESSION, GET_LICENSE_REQUEST, PROVIDE_LICENSE_RESPONSE, REMOVE_LICENSE, QUERY_LICENSE_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 }; struct BpDrm : public BpInterface { BpDrm(const sp &impl) : BpInterface(impl) { } virtual status_t initCheck() const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); remote()->transact(INIT_CHECK, data, &reply); return reply.readInt32(); } virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.write(uuid, 16); remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); return reply.readInt32() != 0; } virtual status_t createPlugin(const uint8_t uuid[16]) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.write(uuid, 16); remote()->transact(CREATE_PLUGIN, data, &reply); return reply.readInt32(); } virtual status_t destroyPlugin() { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); remote()->transact(DESTROY_PLUGIN, data, &reply); return reply.readInt32(); } virtual status_t openSession(Vector &sessionId) { Parcel data, reply; 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); return reply.readInt32(); } virtual status_t closeSession(Vector const &sessionId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeInt32(sessionId.size()); data.write(sessionId.array(), sessionId.size()); remote()->transact(CLOSE_SESSION, data, &reply); return reply.readInt32(); } virtual status_t getLicenseRequest(Vector const &sessionId, Vector const &initData, String8 const &mimeType, DrmPlugin::LicenseType licenseType, KeyedVector const &optionalParameters, Vector &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()); data.writeString8(mimeType); data.writeInt32((uint32_t)licenseType); 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); uint32_t len = reply.readInt32(); request.insertAt((size_t)0, len); reply.read(request.editArray(), len); defaultUrl = reply.readString8(); return reply.readInt32(); } virtual status_t provideLicenseResponse(Vector const &sessionId, Vector const &response) { 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); return reply.readInt32(); } virtual status_t removeLicense(Vector const &sessionId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeInt32(sessionId.size()); data.write(sessionId.array(), sessionId.size()); remote()->transact(REMOVE_LICENSE, data, &reply); return reply.readInt32(); } virtual status_t queryLicenseStatus(Vector const &sessionId, KeyedVector &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); 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(Vector &request, String8 &defaultUrl) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); remote()->transact(GET_PROVISION_REQUEST, data, &reply); uint32_t len = reply.readInt32(); request.insertAt((size_t)0, len); reply.read(request.editArray(), len); defaultUrl = reply.readString8(); return reply.readInt32(); } virtual status_t provideProvisionResponse(Vector const &response) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeInt32(response.size()); data.write(response.array(), response.size()); remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply); return reply.readInt32(); } virtual status_t getSecureStops(List > &secureStops) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); remote()->transact(GET_SECURE_STOPS, data, &reply); secureStops.clear(); uint32_t count = reply.readInt32(); for (size_t i = 0; i < count; i++) { Vector secureStop; uint32_t len = reply.readInt32(); secureStop.insertAt((size_t)0, len); reply.read(secureStop.editArray(), len); secureStops.push_back(secureStop); } return reply.readInt32(); } virtual status_t releaseSecureStops(Vector const &ssRelease) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeInt32(ssRelease.size()); data.write(ssRelease.array(), ssRelease.size()); remote()->transact(RELEASE_SECURE_STOPS, data, &reply); return reply.readInt32(); } virtual status_t getPropertyString(String8 const &name, String8 &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); remote()->transact(GET_PROPERTY_STRING, data, &reply); value = reply.readString8(); return reply.readInt32(); } virtual status_t getPropertyByteArray(String8 const &name, Vector &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); 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); 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); remote()->transact(SET_PROPERTY_STRING, data, &reply); return reply.readInt32(); } virtual status_t setPropertyByteArray(String8 const &name, Vector const &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); data.writeInt32(value.size()); data.write(value.array(), value.size()); remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply); return reply.readInt32(); } private: DISALLOW_EVIL_CONSTRUCTORS(BpDrm); }; IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm"); //////////////////////////////////////////////////////////////////////////////// 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)); reply->writeInt32(isCryptoSchemeSupported(uuid)); return OK; } case CREATE_PLUGIN: { CHECK_INTERFACE(IDrm, data, reply); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); reply->writeInt32(createPlugin(uuid)); return OK; } case DESTROY_PLUGIN: { CHECK_INTERFACE(IDrm, data, reply); reply->writeInt32(destroyPlugin()); return OK; } case OPEN_SESSION: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; status_t result = openSession(sessionId); reply->writeInt32(sessionId.size()); reply->write(sessionId.array(), sessionId.size()); reply->writeInt32(result); return OK; } case CLOSE_SESSION: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; uint32_t size = data.readInt32(); sessionId.insertAt((size_t)0, size); data.read(sessionId.editArray(), size); reply->writeInt32(closeSession(sessionId)); return OK; } case GET_LICENSE_REQUEST: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; uint32_t size = data.readInt32(); sessionId.insertAt((size_t)0, size); data.read(sessionId.editArray(), size); Vector initData; size = data.readInt32(); initData.insertAt((size_t)0, size); data.read(initData.editArray(), size); String8 mimeType = data.readString8(); DrmPlugin::LicenseType licenseType = (DrmPlugin::LicenseType)data.readInt32(); KeyedVector 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 request; String8 defaultUrl; status_t result = getLicenseRequest(sessionId, initData, mimeType, licenseType, optionalParameters, request, defaultUrl); reply->writeInt32(request.size()); reply->write(request.array(), request.size()); reply->writeString8(defaultUrl); reply->writeInt32(result); return OK; } case PROVIDE_LICENSE_RESPONSE: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; uint32_t size = data.readInt32(); sessionId.insertAt((size_t)0, size); data.read(sessionId.editArray(), size); Vector response; size = data.readInt32(); response.insertAt((size_t)0, size); data.read(response.editArray(), size); reply->writeInt32(provideLicenseResponse(sessionId, response)); return OK; } case REMOVE_LICENSE: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; uint32_t size = data.readInt32(); sessionId.insertAt((size_t)0, size); data.read(sessionId.editArray(), size); reply->writeInt32(removeLicense(sessionId)); return OK; } case QUERY_LICENSE_STATUS: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; uint32_t size = data.readInt32(); sessionId.insertAt((size_t)0, size); data.read(sessionId.editArray(), size); KeyedVector infoMap; status_t result = queryLicenseStatus(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); Vector request; String8 defaultUrl; status_t result = getProvisionRequest(request, defaultUrl); reply->writeInt32(request.size()); reply->write(request.array(), request.size()); reply->writeString8(defaultUrl); reply->writeInt32(result); return OK; } case PROVIDE_PROVISION_RESPONSE: { CHECK_INTERFACE(IDrm, data, reply); Vector response; uint32_t size = data.readInt32(); response.insertAt((size_t)0, size); data.read(response.editArray(), size); reply->writeInt32(provideProvisionResponse(response)); return OK; } case GET_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); List > secureStops; status_t result = getSecureStops(secureStops); size_t count = secureStops.size(); reply->writeInt32(count); List >::iterator iter = secureStops.begin(); while(iter != secureStops.end()) { size_t size = iter->size(); reply->writeInt32(size); reply->write(iter->array(), iter->size()); } reply->writeInt32(result); return OK; } case RELEASE_SECURE_STOPS: { CHECK_INTERFACE(IDrm, data, reply); Vector ssRelease; uint32_t size = data.readInt32(); ssRelease.insertAt((size_t)0, size); data.read(ssRelease.editArray(), size); reply->writeInt32(releaseSecureStops(ssRelease)); 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 value; status_t result = getPropertyByteArray(name, value); reply->writeInt32(value.size()); reply->write(value.array(), value.size()); 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 value; size_t count = data.readInt32(); value.insertAt((size_t)0, count); data.read(value.editArray(), count); reply->writeInt32(setPropertyByteArray(name, value)); return OK; } default: return BBinder::onTransact(code, data, reply, flags); } } } // namespace android