Modular DRM for MediaPlayer
Bug: 34559906
Test: Manual through the test app
Change-Id: I752c3e2bbc2fac9c75f7ddc986014c4b8ce75d84
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 9ffde4e..966267a 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -70,8 +70,28 @@
SET_RETRANSMIT_ENDPOINT,
GET_RETRANSMIT_ENDPOINT,
SET_NEXT_PLAYER,
+ // ModDrm
+ PREPARE_DRM,
+ RELEASE_DRM,
+ GET_KEY_REQUEST,
+ PROVIDE_KEY_RESPONSE,
+ RESTORE_KEYS,
+ GET_DRM_PROPERTY_STRING,
+ SET_DRM_PROPERTY_STRING,
};
+// ModDrm helpers
+static void readVector(const Parcel& reply, Vector<uint8_t>& vector) {
+ uint32_t size = reply.readUint32();
+ vector.insertAt((size_t)0, size);
+ reply.read(vector.editArray(), size);
+}
+
+static void writeVector(Parcel& data, Vector<uint8_t> const& vector) {
+ data.writeUint32(vector.size());
+ data.write(vector.array(), vector.size());
+}
+
class BpMediaPlayer: public BpInterface<IMediaPlayer>
{
public:
@@ -447,6 +467,137 @@
return err;
}
+
+ // ModDrm
+ status_t prepareDrm(const uint8_t uuid[16], const int mode)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ data.write(uuid, 16);
+ data.writeInt32(mode);
+
+ status_t status = remote()->transact(PREPARE_DRM, data, &reply);
+ if (status != OK) {
+ ALOGE("prepareDrm: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
+
+ status_t releaseDrm()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ status_t status = remote()->transact(RELEASE_DRM, data, &reply);
+ if (status != OK) {
+ ALOGE("releaseDrm: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
+
+ status_t getKeyRequest(Vector<uint8_t> const& scope, String8 const& mimeType,
+ DrmPlugin::KeyType keyType, KeyedVector<String8, String8>& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType& keyRequestType)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ writeVector(data, scope);
+ data.writeString8(mimeType);
+ data.writeInt32((int32_t)keyType);
+
+ data.writeUint32(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) {
+ ALOGE("getKeyRequest: binder call failed: %d", status);
+ return status;
+ }
+
+ readVector(reply, request);
+ defaultUrl = reply.readString8();
+ keyRequestType = (DrmPlugin::KeyRequestType)reply.readInt32();
+
+ return reply.readInt32();
+ }
+
+ status_t provideKeyResponse(Vector<uint8_t>& releaseKeySetId, Vector<uint8_t>& response,
+ Vector<uint8_t> &keySetId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ writeVector(data, releaseKeySetId);
+ writeVector(data, response);
+
+ status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
+ if (status != OK) {
+ ALOGE("provideKeyResponse: binder call failed: %d", status);
+ return status;
+ }
+
+ readVector(reply, keySetId);
+
+ return reply.readInt32();
+ }
+
+ status_t restoreKeys(Vector<uint8_t> const& keySetId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ writeVector(data, keySetId);
+
+ status_t status = remote()->transact(RESTORE_KEYS, data, &reply);
+ if (status != OK) {
+ ALOGE("restoreKeys: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
+
+ status_t getDrmPropertyString(String8 const& name, String8& value)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ data.writeString8(name);
+ status_t status = remote()->transact(GET_DRM_PROPERTY_STRING, data, &reply);
+ if (status != OK) {
+ ALOGE("getDrmPropertyString: binder call failed: %d", status);
+ return status;
+ }
+
+ value = reply.readString8();
+ return reply.readInt32();
+ }
+
+ status_t setDrmPropertyString(String8 const& name, String8 const& value)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+ data.writeString8(name);
+ data.writeString8(value);
+ status_t status = remote()->transact(SET_DRM_PROPERTY_STRING, data, &reply);
+ if (status != OK) {
+ ALOGE("setDrmPropertyString: binder call failed: %d", status);
+ return status;
+ }
+
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -741,6 +892,93 @@
return NO_ERROR;
} break;
+
+ // ModDrm
+ case PREPARE_DRM: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ uint8_t uuid[16];
+ data.read(uuid, sizeof(uuid));
+
+ int mode = data.readInt32();
+
+ uint32_t result = prepareDrm(uuid, mode);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case RELEASE_DRM: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ uint32_t result = releaseDrm();
+ reply->writeInt32(result);
+ return OK;
+ }
+ case GET_KEY_REQUEST: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ Vector<uint8_t> scope;
+ readVector(data, scope);
+ String8 mimeType = data.readString8();
+ DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
+
+ KeyedVector<String8, String8> optionalParameters;
+ uint32_t count = data.readUint32();
+ 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(scope, mimeType, keyType, optionalParameters,
+ request, defaultUrl, keyRequestType);
+
+ writeVector(*reply, request);
+ reply->writeString8(defaultUrl);
+ reply->writeInt32(keyRequestType);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case PROVIDE_KEY_RESPONSE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ Vector<uint8_t> releaseKeySetId, response, keySetId;
+ readVector(data, releaseKeySetId);
+ readVector(data, response);
+ uint32_t result = provideKeyResponse(releaseKeySetId, response, keySetId);
+ writeVector(*reply, keySetId);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case RESTORE_KEYS: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ Vector<uint8_t> keySetId;
+ readVector(data, keySetId);
+ uint32_t result = restoreKeys(keySetId);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case GET_DRM_PROPERTY_STRING: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ String8 name, value;
+ name = data.readString8();
+ uint32_t result = getDrmPropertyString(name, value);
+ reply->writeString8(value);
+ reply->writeInt32(result);
+ return OK;
+ }
+ case SET_DRM_PROPERTY_STRING: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ String8 name, value;
+ name = data.readString8();
+ value = data.readString8();
+ uint32_t result = setDrmPropertyString(name, value);
+ reply->writeInt32(result);
+ return OK;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}