Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1784ec91 authored by Hassan Shojania's avatar Hassan Shojania Committed by Android (Google) Code Review
Browse files

Merge "Modular DRM for MediaPlayer"

parents 3a0a8b4c 071437a2
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <system/audio.h>

#include <media/IMediaSource.h>
#include <media/drm/DrmAPI.h>   // for DrmPlugin::* enum

// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
// global, and not in android::
@@ -89,6 +90,22 @@ public:
    virtual status_t        setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
    virtual status_t        getRetransmitEndpoint(struct sockaddr_in* endpoint) = 0;
    virtual status_t        setNextPlayer(const sp<IMediaPlayer>& next) = 0;
    // ModDrm
    virtual status_t        prepareDrm(const uint8_t uuid[16], const int mode) = 0;
    virtual status_t        releaseDrm() = 0;
    virtual 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) = 0;
    virtual status_t        provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
                                    Vector<uint8_t>& response,
                                    Vector<uint8_t>& keySetId) = 0;
    virtual status_t        restoreKeys(Vector<uint8_t> const& keySetId) = 0;
    virtual status_t        getDrmPropertyString(String8 const& name, String8& value) = 0;
    virtual status_t        setDrmPropertyString(String8 const& name, String8 const& value) = 0;

    // Invoke a generic method on the player by using opaque parcels
    // for the request and reply.
+28 −0
Original line number Diff line number Diff line
@@ -280,6 +280,34 @@ public:
        return INVALID_OPERATION;
    }

    // ModDrm
    virtual status_t prepareDrm(const uint8_t uuid[16], const int mode) {
        return INVALID_OPERATION;
    }
    virtual status_t releaseDrm() {
        return INVALID_OPERATION;
    }
    virtual 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) {
        return INVALID_OPERATION;
    }
    virtual status_t provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
                             Vector<uint8_t>& response, Vector<uint8_t>& keySetId) {
        return INVALID_OPERATION;
    }
    virtual status_t restoreKeys(Vector<uint8_t> const& keySetId) {
        return INVALID_OPERATION;
    }
    virtual status_t getDrmPropertyString(String8 const& name, String8& value) {
        return INVALID_OPERATION;
    }
    virtual status_t setDrmPropertyString(String8 const& name, String8 const& value) {
        return INVALID_OPERATION;
    }

private:
    friend class MediaPlayerService;

+14 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ enum media_event_type {
    MEDIA_INFO              = 200,
    MEDIA_SUBTITLE_DATA     = 201,
    MEDIA_META_DATA         = 202,
    MEDIA_DRM_INFO          = 210,
};

// Generic error codes for the media player framework.  Errors are fatal, the
@@ -260,6 +261,19 @@ public:
            status_t        getParameter(int key, Parcel* reply);
            status_t        setRetransmitEndpoint(const char* addrString, uint16_t port);
            status_t        setNextMediaPlayer(const sp<MediaPlayer>& player);
            // ModDrm
            status_t        prepareDrm(const uint8_t uuid[16], const int mode);
            status_t        releaseDrm();
            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);
            status_t        provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
                                    Vector<uint8_t>& response, Vector<uint8_t>& keySetId);
            status_t        restoreKeys(Vector<uint8_t> const& keySetId);
            status_t        getDrmPropertyString(String8 const& name, String8& value);
            status_t        setDrmPropertyString(String8 const& name, String8 const& value);

private:
            void            clear_l();
+238 −0
Original line number Diff line number Diff line
@@ -70,8 +70,28 @@ enum {
    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 @@ public:

        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 @@ status_t BnMediaPlayer::onTransact(

            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);
    }
+123 −1
Original line number Diff line number Diff line
@@ -879,7 +879,7 @@ void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
    case MEDIA_NOP: // interface test message
        break;
    case MEDIA_PREPARED:
        ALOGV("prepared");
        ALOGV("MediaPlayer::notify() prepared");
        mCurrentState = MEDIA_PLAYER_PREPARED;
        if (mPrepareSync) {
            ALOGV("signal application thread");
@@ -888,6 +888,9 @@ void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
            mSignal.signal();
        }
        break;
    case MEDIA_DRM_INFO:
        ALOGV("MediaPlayer::notify() MEDIA_DRM_INFO(%d, %d, %d, %p)", msg, ext1, ext2, obj);
        break;
    case MEDIA_PLAYBACK_COMPLETE:
        ALOGV("playback complete");
        if (mCurrentState == MEDIA_PLAYER_IDLE) {
@@ -988,4 +991,123 @@ status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
    return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
}

// ModDrm
status_t MediaPlayer::prepareDrm(const uint8_t uuid[16], const int mode)
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Only allowing it in player's prepared state
    if (!(mCurrentState & MEDIA_PLAYER_PREPARED)) {
        ALOGE("prepareDrm must only be called in the prepared state.");
        return INVALID_OPERATION;
    }

    status_t ret = mPlayer->prepareDrm(uuid, mode);
    ALOGV("prepareDrm: ret=%d", ret);

    return ret;
}

status_t MediaPlayer::releaseDrm()
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Not allowing releaseDrm in an active state
    if (mCurrentState & (MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED)) {
        ALOGE("releaseDrm can not be called in the started/paused state.");
        return INVALID_OPERATION;
    }

    status_t ret = mPlayer->releaseDrm();
    ALOGV("releaseDrm: ret=%d", ret);

    return ret;
}

status_t MediaPlayer::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)
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Not enforcing a particular state beyond the checks enforced by the Java layer
    // Key exchange can happen after the start.
    status_t ret = mPlayer->getKeyRequest(scope, mimeType, keyType, optionalParameters,
                                     request, defaultUrl, keyRequestType);
    ALOGV("getKeyRequest ret=%d  %d %s %d ", ret,
          (int)request.size(), defaultUrl.string(), (int)keyRequestType);

    return ret;
}

status_t MediaPlayer::provideKeyResponse(Vector<uint8_t>& releaseKeySetId,
                              Vector<uint8_t>& response, Vector<uint8_t>& keySetId)
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Not enforcing a particular state beyond the checks enforced by the Java layer
    // Key exchange can happen after the start.
    status_t ret = mPlayer->provideKeyResponse(releaseKeySetId, response, keySetId);
    ALOGV("provideKeyResponse: ret=%d", ret);

    return ret;
}

status_t MediaPlayer::restoreKeys(Vector<uint8_t> const& keySetId)
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Not enforcing a particular state beyond the checks enforced by the Java layer
    // Key exchange can happen after the start.
    status_t ret = mPlayer->restoreKeys(keySetId);
    ALOGV("restoreKeys: ret=%d", ret);

    return ret;
}

status_t MediaPlayer::getDrmPropertyString(String8 const& name, String8& value)
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Not enforcing a particular state beyond the checks enforced by the Java layer
    status_t ret = mPlayer->getDrmPropertyString(name, value);
    ALOGV("getDrmPropertyString: ret=%d", ret);

    return ret;
}

status_t MediaPlayer::setDrmPropertyString(String8 const& name, String8 const& value)
{
    Mutex::Autolock _l(mLock);
    if (mPlayer == NULL) {
        return NO_INIT;
    }

    // Not enforcing a particular state beyond the checks enforced by the Java layer
    status_t ret = mPlayer->setDrmPropertyString(name, value);
    ALOGV("setDrmPropertyString: ret=%d", ret);

    return ret;
}

} // namespace android
Loading