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

Commit becb0586 authored by Ilya Matyukhin's avatar Ilya Matyukhin Committed by Gerrit Code Review
Browse files

Merge changes from topic "drmAddListeners"

* changes:
  Add onExpirationUpdate and onKeyStatusChange listeners.
  Add onExpirationUpdate and onKeyStatusChange listeners.
parents 1b7026ed 19a282a4
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -245,11 +245,29 @@ Return<void> DrmPlugin::provideKeyResponse(

    setPlayPolicy();
    std::vector<uint8_t> keySetId;
    keySetId.clear();

    Status status = session->provideKeyResponse(response);
    if (status == Status::OK) {
        // This is for testing AMediaDrm_setOnEventListener only.
        sendEvent(EventType::VENDOR_DEFINED, 0, scope);
        keySetId.clear();
        // Test calling AMediaDrm listeners.
        sendEvent(EventType::VENDOR_DEFINED, toVector(scope), toVector(scope));

        sendExpirationUpdate(toVector(scope), 100);

        std::vector<KeyStatus> keysStatus;
        KeyStatus keyStatus;

        std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
        keyStatus.keyId = keyId1;
        keyStatus.type = V1_0::KeyStatusType::USABLE;
        keysStatus.push_back(keyStatus);

        std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
        keyStatus.keyId = keyId2;
        keyStatus.type = V1_0::KeyStatusType::EXPIRED;
        keysStatus.push_back(keyStatus);

        sendKeysChange(toVector(scope), keysStatus, true);
    }

    installSecureStop(scope);
+143 −22
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "NdkMediaDrm"

#include <inttypes.h>

#include <media/NdkMediaDrm.h>

#include <cutils/properties.h>
@@ -40,10 +42,32 @@ struct DrmListener: virtual public BnDrmClient
{
private:
    AMediaDrm *mObj;
    AMediaDrmEventListener mListener;
    AMediaDrmEventListener mEventListener;
    AMediaDrmExpirationUpdateListener mExpirationUpdateListener;
    AMediaDrmKeysChangeListener mKeysChangeListener;

public:
    DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj), mListener(listener) {}
    DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj),
            mEventListener(listener), mExpirationUpdateListener(NULL), mKeysChangeListener(NULL) {}

    DrmListener(AMediaDrm *obj, AMediaDrmExpirationUpdateListener listener) : mObj(obj),
            mEventListener(NULL), mExpirationUpdateListener(listener), mKeysChangeListener(NULL) {}

    DrmListener(AMediaDrm *obj, AMediaDrmKeysChangeListener listener) : mObj(obj),
            mEventListener(NULL), mExpirationUpdateListener(NULL), mKeysChangeListener(listener) {}

    void setEventListener(AMediaDrmEventListener listener) {
        mEventListener = listener;
    }

    void setExpirationUpdateListener(AMediaDrmExpirationUpdateListener listener) {
        mExpirationUpdateListener = listener;
    }

    void setKeysChangeListener(AMediaDrmKeysChangeListener listener) {
        mKeysChangeListener = listener;
    }

    void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
};

@@ -62,27 +86,75 @@ struct AMediaDrm {
};

void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
    if (!mListener) {
    if (!mEventListener && !mExpirationUpdateListener && !mKeysChangeListener) {
        ALOGE("No listeners are specified");
        return;
    }

    obj->setDataPosition(0);

    AMediaDrmSessionId sessionId = {NULL, 0};
    int32_t sessionIdSize = obj->readInt32();
    if (sessionIdSize) {
        uint8_t *sessionIdData = new uint8_t[sessionIdSize];
        sessionId.ptr = sessionIdData;
    if (sessionIdSize <= 0) {
        ALOGE("Invalid session id size");
        return;
    }

    std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
    sessionId.ptr = sessionIdData.get();
    sessionId.length = sessionIdSize;
        obj->read(sessionIdData, sessionId.length);
    status_t err = obj->read(sessionIdData.get(), sessionId.length);
    if (err != OK) {
        ALOGE("Failed to read session id, error=%d", err);
        return;
    }

    int32_t dataSize = obj->readInt32();
    uint8_t *data = NULL;
    if (dataSize) {
        data = new uint8_t[dataSize];
        obj->read(data, dataSize);
    if (DrmPlugin::kDrmPluginEventExpirationUpdate == eventType) {
        int64_t expiryTimeInMS = obj->readInt64();
        if (expiryTimeInMS >= 0) {
            (*mExpirationUpdateListener)(mObj, &sessionId, expiryTimeInMS);
        } else {
            ALOGE("Failed to read expiry time, status=%" PRId64 "", expiryTimeInMS);
        }
        return;
    } else if (DrmPlugin::kDrmPluginEventKeysChange == eventType) {
        int32_t numKeys = 0;
        err = obj->readInt32(&numKeys);
        if (err != OK) {
            ALOGE("Failed to read number of keys status, error=%d", err);
            return;
        }

        Vector<AMediaDrmKeyStatus> keysStatus;
        std::vector<std::unique_ptr<uint8_t[]> > dataPointers;
        AMediaDrmKeyStatus keyStatus;

        for (size_t i = 0; i < numKeys; ++i) {
            keyStatus.keyId.ptr = nullptr;
            keyStatus.keyId.length = 0;
            int32_t idSize = obj->readInt32();
            if (idSize > 0) {
                std::unique_ptr<uint8_t[]> data(new uint8_t[idSize]);
                err = obj->read(data.get(), idSize);
                if (err != OK) {
                    ALOGE("Failed to read key data, error=%d", err);
                    return;
                }
                keyStatus.keyId.ptr = data.get();
                keyStatus.keyId.length = idSize;
                dataPointers.push_back(std::move(data));
            }
            keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(obj->readInt32());
            keysStatus.push(keyStatus);
        }

    // translate DrmPlugin event types into their NDK equivalents
        bool hasNewUsableKey = obj->readInt32();
        (*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
        return;
    }

    // Handles AMediaDrmEventListener below:
    //  translates DrmPlugin event types into their NDK equivalents
    AMediaDrmEventType ndkEventType;
    switch(eventType) {
        case DrmPlugin::kDrmPluginEventProvisionRequired:
@@ -97,18 +169,29 @@ void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel
        case DrmPlugin::kDrmPluginEventVendorDefined:
            ndkEventType = EVENT_VENDOR_DEFINED;
            break;
        case DrmPlugin::kDrmPluginEventSessionReclaimed:
            ndkEventType = EVENT_SESSION_RECLAIMED;
            break;
        default:
            ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
            goto cleanup;
            return;
    }

    (*mListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);

 cleanup:
    delete [] sessionId.ptr;
    int32_t dataSize = obj->readInt32();
    uint8_t *data = NULL;
    if (dataSize > 0) {
        data = new uint8_t[dataSize];
        err = obj->read(data, dataSize);
        if (err == OK) {
            (*mEventListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
        } else {
            ALOGE("Failed to read event data, error=%d", err);
        }
        delete [] data;
    } else {
        ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
    }
}


extern "C" {

@@ -198,6 +281,8 @@ EXPORT
AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
    AMediaDrm *mObj = new AMediaDrm();
    mObj->mDrm = CreateDrmFromUUID(uuid);

    mObj->mListener.clear();
    return mObj;
}

@@ -216,11 +301,47 @@ media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListe
    if (!mObj || mObj->mDrm == NULL) {
        return AMEDIA_ERROR_INVALID_OBJECT;
    }

    if (mObj->mListener.get()) {
        mObj->mListener->setEventListener(listener);
    } else {
        mObj->mListener = new DrmListener(mObj, listener);
    }
    mObj->mDrm->setListener(mObj->mListener);
    return AMEDIA_OK;
}

EXPORT
media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
        AMediaDrmExpirationUpdateListener listener) {
    if (!mObj || mObj->mDrm == NULL) {
        return AMEDIA_ERROR_INVALID_OBJECT;
    }

    if (mObj->mListener.get()) {
        mObj->mListener->setExpirationUpdateListener(listener);
    } else {
        mObj->mListener = new DrmListener(mObj, listener);
    }
    mObj->mDrm->setListener(mObj->mListener);
    return AMEDIA_OK;
}

EXPORT
media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
        AMediaDrmKeysChangeListener listener) {
    if (!mObj || mObj->mDrm == NULL) {
        return AMEDIA_ERROR_INVALID_OBJECT;
    }

    if (mObj->mListener.get()) {
        mObj->mListener->setKeysChangeListener(listener);
    } else {
        mObj->mListener = new DrmListener(mObj, listener);
    }
    mObj->mDrm->setListener(mObj->mListener);
    return AMEDIA_OK;
}

static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
    for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
+95 −29
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ typedef AMediaDrmByteArray AMediaDrmSessionId;
typedef AMediaDrmByteArray AMediaDrmScope;
typedef AMediaDrmByteArray AMediaDrmKeySetId;
typedef AMediaDrmByteArray AMediaDrmSecureStop;
typedef AMediaDrmByteArray AMediaDrmKeyId;

typedef enum AMediaDrmEventType {
    /**
@@ -81,12 +82,89 @@ typedef enum AMediaDrmEventType {
     * This event may indicate some specific vendor-defined condition, see your
     * DRM provider documentation for details
     */
    EVENT_VENDOR_DEFINED = 4
    EVENT_VENDOR_DEFINED = 4,

    /**
     * This event indicates that a session opened by the app has been reclaimed
     * by the resource manager.
     */
    EVENT_SESSION_RECLAIMED = 5,
} AMediaDrmEventType;

typedef enum AMediaDrmKeyType {
    /**
     * This key request type specifies that the keys will be for online use, they will
     * not be saved to the device for subsequent use when the device is not connected
     * to a network.
     */
    KEY_TYPE_STREAMING = 1,

    /**
     * This key request type specifies that the keys will be for offline use, they
     * will be saved to the device for use when the device is not connected to a network.
     */
    KEY_TYPE_OFFLINE = 2,

    /**
     * This key request type specifies that previously saved offline keys should be released.
     */
    KEY_TYPE_RELEASE = 3
} AMediaDrmKeyType;

/**
 *  Data type containing {key, value} pair
 */
typedef struct AMediaDrmKeyValuePair {
    const char *mKey;
    const char *mValue;
} AMediaDrmKeyValue;

typedef enum AMediaKeyStatusType {
    /**
     * The key is currently usable to decrypt media data.
     */
    KEY_STATUS_TYPE_USABLE,

    /**
     * The key is no longer usable to decrypt media data because its expiration
     * time has passed.
     */
    KEY_STATUS_TYPE_EXPIRED,

    /**
     * The key is not currently usable to decrypt media data because its output
     * requirements cannot currently be met.
     */
    KEY_STATUS_TYPE_OUTPUTNOTALLOWED,

    /**
     * The status of the key is not yet known and is being determined.
     */
    KEY_STATUS_TYPE_STATUSPENDING,

    /**
     * The key is not currently usable to decrypt media data because of an
     * internal error in processing unrelated to input parameters.
     */
    KEY_STATUS_TYPE_INTERNALERROR,

} AMediaDrmKeyStatusType;

typedef struct AMediaDrmKeyStatus {
    AMediaDrmKeyId keyId;
    AMediaDrmKeyStatusType keyType;
} AMediaDrmKeyStatus;

typedef void (*AMediaDrmEventListener)(AMediaDrm *, const AMediaDrmSessionId *sessionId,
        AMediaDrmEventType eventType, int extra, const uint8_t *data, size_t dataSize);

typedef void (*AMediaDrmExpirationUpdateListener)(AMediaDrm *,
        const AMediaDrmSessionId *sessionId, int64_t expiryTimeInMS);

typedef void (*AMediaDrmKeysChangeListener)(AMediaDrm *,
        const AMediaDrmSessionId *sessionId, const AMediaDrmKeyStatus *keyStatus,
        size_t numKeys, bool hasNewUsableKey);

#if __ANDROID_API__ >= 21

/**
@@ -119,6 +197,22 @@ void AMediaDrm_release(AMediaDrm *) __INTRODUCED_IN(21);
media_status_t AMediaDrm_setOnEventListener(AMediaDrm *,
        AMediaDrmEventListener listener) __INTRODUCED_IN(21);

/**
 * Register a callback to be invoked when an expiration update event occurs
 *
 * listener is the callback that will be invoked on event
 */
media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *,
        AMediaDrmExpirationUpdateListener listener) __INTRODUCED_IN(29);

/**
 * Register a callback to be invoked when a key status change event occurs
 *
 * listener is the callback that will be invoked on event
 */
media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *,
        AMediaDrmKeysChangeListener listener) __INTRODUCED_IN(29);

/**
 * Open a new session with the MediaDrm object.  A session ID is returned.
 *
@@ -135,34 +229,6 @@ media_status_t AMediaDrm_openSession(AMediaDrm *,
media_status_t AMediaDrm_closeSession(AMediaDrm *,
        const AMediaDrmSessionId *sessionId) __INTRODUCED_IN(21);

typedef enum AMediaDrmKeyType {
    /**
     * This key request type species that the keys will be for online use, they will
     * not be saved to the device for subsequent use when the device is not connected
     * to a network.
     */
    KEY_TYPE_STREAMING = 1,

    /**
     * This key request type specifies that the keys will be for offline use, they
     * will be saved to the device for use when the device is not connected to a network.
     */
    KEY_TYPE_OFFLINE = 2,

    /**
     * This key request type specifies that previously saved offline keys should be released.
     */
    KEY_TYPE_RELEASE = 3
} AMediaDrmKeyType;

/**
 *  Data type containing {key, value} pair
 */
typedef struct AMediaDrmKeyValuePair {
    const char *mKey;
    const char *mValue;
} AMediaDrmKeyValue;

/**
 * A key request/response exchange occurs between the app and a license server
 * to obtain or release keys used to decrypt encrypted content.
+2 −0
Original line number Diff line number Diff line
@@ -163,6 +163,8 @@ LIBMEDIANDK {
    AMediaDrm_setOnEventListener;
    AMediaDrm_setPropertyByteArray;
    AMediaDrm_setPropertyString;
    AMediaDrm_setOnExpirationUpdateListener; # introduced=29
    AMediaDrm_setOnKeysChangeListener; # introduced=29
    AMediaDrm_sign;
    AMediaDrm_verify;
    AMediaExtractor_advance;