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

Commit b01fb48f authored by Chong Zhang's avatar Chong Zhang
Browse files

MediaCas: fixes for playback tests

- Set crypto mode to kMode_AES_CTR, since kMode_AES_CBC is not defined
  on Java API, and is rejected when the sample is queued to MediaCodec.

- Wrap the plugin object in a RefBase, and hold a strong ref to it
  when executing any API calls in CasImpl. This is needed because
  CasImpl could be released by Java API, while MediaCodec native is
  still trying to access it.

- Fix build warnings.

Tests: cts-tradefed run cts-dev --module CtsMediaTestCases --test android.media.cts.ClearKeySystemTest

It should not fail.

bug: 22804304
Change-Id: Id4ef037d57dd741d2bb22b1de3d04c8d078b69fb
parent 6480d09e
Loading
Loading
Loading
Loading
+70 −26
Original line number Diff line number Diff line
@@ -49,13 +49,24 @@ static String8 sessionIdToString(const CasSessionId &sessionId) {
    return result;
}

struct CasImpl::PluginHolder : public RefBase {
public:
    explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
    ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
    CasPlugin* get() { return mPlugin; }

private:
    CasPlugin *mPlugin;
    DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
};

CasImpl::CasImpl(const sp<ICasListener> &listener)
    : mPlugin(NULL), mListener(listener) {
    ALOGV("CTOR: mPlugin=%p", mPlugin);
    : mPluginHolder(NULL), mListener(listener) {
    ALOGV("CTOR");
}

CasImpl::~CasImpl() {
    ALOGV("DTOR: mPlugin=%p", mPlugin);
    ALOGV("DTOR");
    release();
}

@@ -76,7 +87,7 @@ void CasImpl::OnEvent(

void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
    mLibrary = library;
    mPlugin = plugin;
    mPluginHolder = new PluginHolder(plugin);
}

void CasImpl::onEvent(
@@ -95,13 +106,20 @@ void CasImpl::onEvent(

Status CasImpl::setPrivateData(const CasData& pvtData) {
    ALOGV("setPrivateData");
    return getBinderStatus(mPlugin->setPrivateData(pvtData));
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }
    return getBinderStatus(holder->get()->setPrivateData(pvtData));
}

Status CasImpl::openSession(int32_t program_number, CasSessionId* sessionId) {
    ALOGV("openSession: program_number=%d", program_number);

    status_t err = mPlugin->openSession(program_number, sessionId);
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }
    status_t err = holder->get()->openSession(program_number, sessionId);

    ALOGV("openSession: session opened for program_number=%d, sessionId=%s",
            program_number, sessionIdToString(*sessionId).string());
@@ -115,8 +133,11 @@ Status CasImpl::openSessionForStream(
        CasSessionId* sessionId) {
    ALOGV("openSession: program_number=%d, elementary_PID=%d",
            program_number, elementary_PID);

    status_t err = mPlugin->openSession(
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }
    status_t err = holder->get()->openSession(
            program_number, elementary_PID, sessionId);

    ALOGV("openSession: session opened for "
@@ -131,69 +152,92 @@ Status CasImpl::setSessionPrivateData(
        const CasSessionId &sessionId, const CasData& pvtData) {
    ALOGV("setSessionPrivateData: sessionId=%s",
            sessionIdToString(sessionId).string());

    return getBinderStatus(mPlugin->setSessionPrivateData(sessionId, pvtData));
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }
    return getBinderStatus(holder->get()->setSessionPrivateData(sessionId, pvtData));
}

Status CasImpl::closeSession(const CasSessionId &sessionId) {
    ALOGV("closeSession: sessionId=%s",
            sessionIdToString(sessionId).string());

    return getBinderStatus(mPlugin->closeSession(sessionId));
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }
    return getBinderStatus(holder->get()->closeSession(sessionId));
}

Status CasImpl::processEcm(const CasSessionId &sessionId, const ParcelableCasData& ecm) {
    ALOGV("processEcm: sessionId=%s",
            sessionIdToString(sessionId).string());
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }

    return getBinderStatus(mPlugin->processEcm(sessionId, ecm));
    return getBinderStatus(holder->get()->processEcm(sessionId, ecm));
}

Status CasImpl::processEmm(const ParcelableCasData& emm) {
    ALOGV("processEmm");
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }

    return getBinderStatus(mPlugin->processEmm(emm));
    return getBinderStatus(holder->get()->processEmm(emm));
}

Status CasImpl::sendEvent(
        int32_t event, int32_t arg, const ::std::unique_ptr<CasData> &eventData) {
    ALOGV("sendEvent");
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }

    status_t err;
    if (eventData == nullptr) {
        err = mPlugin->sendEvent(event, arg, CasData());
        err = holder->get()->sendEvent(event, arg, CasData());
    } else {
        err = mPlugin->sendEvent(event, arg, *eventData);
        err = holder->get()->sendEvent(event, arg, *eventData);
    }
    return getBinderStatus(err);
}

Status CasImpl::provision(const String16& provisionString) {
    ALOGV("provision: provisionString=%s", String8(provisionString).string());
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }

    return getBinderStatus(mPlugin->provision(String8(provisionString)));
    return getBinderStatus(holder->get()->provision(String8(provisionString)));
}

Status CasImpl::refreshEntitlements(
        int32_t refreshType, const ::std::unique_ptr<CasData> &refreshData) {
    ALOGV("refreshEntitlements");
    sp<PluginHolder> holder = mPluginHolder;
    if (holder == NULL) {
        return getBinderStatus(INVALID_OPERATION);
    }

    status_t err;
    if (refreshData == nullptr) {
        err = mPlugin->refreshEntitlements(refreshType, CasData());
        err = holder->get()->refreshEntitlements(refreshType, CasData());
    } else {
        err = mPlugin->refreshEntitlements(refreshType, *refreshData);
        err = holder->get()->refreshEntitlements(refreshType, *refreshData);
    }
    return getBinderStatus(err);
}

Status CasImpl::release() {
    ALOGV("release: mPlugin=%p", mPlugin);

    if (mPlugin != NULL) {
        delete mPlugin;
        mPlugin = NULL;
    }
    ALOGV("release: plugin=%p",
            mPluginHolder == NULL ? mPluginHolder->get() : NULL);
    mPluginHolder.clear();
    return Status::ok();
}

+11 −7
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ status_t ClearKeyDescramblerFactory::createPlugin(
///////////////////////////////////////////////////////////////////////////////
ClearKeyCasPlugin::ClearKeyCasPlugin(
        uint64_t appData, CasPluginCallback callback)
    : mAppData(appData), mCallback(callback) {
    : mCallback(callback), mAppData(appData) {
    ALOGV("CTOR");
}

@@ -93,7 +93,7 @@ ClearKeyCasPlugin::~ClearKeyCasPlugin() {
    ClearKeySessionLibrary::get()->destroyPlugin(this);
}

status_t ClearKeyCasPlugin::setPrivateData(const CasData &data) {
status_t ClearKeyCasPlugin::setPrivateData(const CasData &/*data*/) {
    ALOGV("setPrivateData");

    return OK;
@@ -142,7 +142,7 @@ status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
}

status_t ClearKeyCasPlugin::setSessionPrivateData(
        const CasSessionId &sessionId, const CasData &data) {
        const CasSessionId &sessionId, const CasData & /*data*/) {
    ALOGV("setSessionPrivateData: sessionId=%s",
            sessionIdToString(sessionId).string());
    sp<ClearKeyCasSession> session =
@@ -167,7 +167,7 @@ status_t ClearKeyCasPlugin::processEcm(
    return session->updateECM(mKeyFetcher.get(), (void*)ecm.data(), ecm.size());
}

status_t ClearKeyCasPlugin::processEmm(const CasEmm& emm) {
status_t ClearKeyCasPlugin::processEmm(const CasEmm& /*emm*/) {
    ALOGV("processEmm");
    Mutex::Autolock lock(mKeyFetcherLock);

@@ -212,8 +212,8 @@ status_t ClearKeyCasPlugin::provision(const String8 &str) {
}

status_t ClearKeyCasPlugin::refreshEntitlements(
        int32_t refreshType, const CasData &refreshData) {
    ALOGV("refreshEntitlements");
        int32_t refreshType, const CasData &/*refreshData*/) {
    ALOGV("refreshEntitlements: refreshType=%d", refreshType);
    Mutex::Autolock lock(mKeyFetcherLock);

    return OK;
@@ -344,7 +344,7 @@ status_t ClearKeyCasSession::updateECM(
                AES_BLOCK_SIZE * 8, &mKeyInfo[keyIndex].contentKey);
        mKeyInfo[keyIndex].valid = (result == 0);
        if (!mKeyInfo[keyIndex].valid) {
            ALOGE("updateECM: failed to set key %d, key_id=%d",
            ALOGE("updateECM: failed to set key %zu, key_id=%d",
                    keyIndex, keys[keyIndex].key_id);
        }
    }
@@ -356,6 +356,10 @@ ssize_t ClearKeyCasSession::decrypt(
        bool secure, DescramblerPlugin::ScramblingControl scramblingControl,
        size_t numSubSamples, const DescramblerPlugin::SubSample *subSamples,
        const void *srcPtr, void *dstPtr, AString * /* errorDetailMsg */) {
    if (secure) {
        return ERROR_DRM_CANNOT_HANDLE;
    }

    AES_KEY contentKey;

    if (scramblingControl != DescramblerPlugin::kScrambling_Unscrambled) {
+3 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define LOG_TAG "ClearKeyFetcher"

#include <algorithm>
#include <inttypes.h>
#include <string>

#include "ClearKeyFetcher.h"
@@ -70,7 +71,7 @@ status_t ClearKeyFetcher::ObtainKey(const sp<ABuffer>& buffer,
        bool same_parity = (((container.descriptor(0).id() & 0x01) ^
                (container.descriptor(1).id() & 0x01)) == 0);
        if (same_parity) {
            ALOGW("asset_id=%llu: malformed Ecm, "
            ALOGW("asset_id=%" PRIu64 ": malformed Ecm, "
                    "content keys have same parity, id0=%d, id1=%d",
                    container.descriptor(0).ecm().asset_id(),
                    container.descriptor(0).id(),
@@ -88,7 +89,7 @@ status_t ClearKeyFetcher::ObtainKey(const sp<ABuffer>& buffer,
    // asset_id change. If it sends an EcmContainer with 2 Ecms with different
    // asset_ids (old and new) then it might be best to prefetch the Emm.
    if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
        ALOGW("Asset_id change from %llu to %llu", asset_.id(), *asset_id);
        ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
        asset_.Clear();
    }

+1 −1
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ status_t DecodeECMClearFields(const sp<ABuffer>& ecm, Asset* asset,
    CHECK(default_fields);

    if (ecm->size() < kTotalEcmSize) {
        ALOGE("Short ECM: expected_length=%zu, actual_length=%zu",
        ALOGE("Short ECM: expected_length=%d, actual_length=%zu",
                kTotalEcmSize, ecm->size());
        return BAD_VALUE;
    }
+2 −1
Original line number Diff line number Diff line
@@ -84,8 +84,9 @@ public:
    virtual Status release() override;

private:
    struct PluginHolder;
    sp<SharedLibrary> mLibrary;
    CasPlugin *mPlugin;
    sp<PluginHolder> mPluginHolder;
    sp<ICasListener> mListener;

    DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
Loading