IDrmClient: remove Parcel from interface

This is part of the effort to remove binder-related classes from libmediadrm.
This change replaces a generic listener for Parcel data with separate
listeners for each event type.

Bug: 134787536
Test: MediaDrmClearkeyTest
Test: NativeMediaDrmClearkeyTest
Test: MediaDrmMockTest
Change-Id: I90cbb75b21cc63737994a01a2171caee5cfb84ad
gugelfrei
Robert Shih 5 years ago
parent b1150c2023
commit 61e1c76cf3

@ -39,6 +39,8 @@
#include <mediadrm/DrmSessionClientInterface.h>
#include <mediadrm/DrmSessionManager.h>
#include <vector>
using drm::V1_0::KeyedVector;
using drm::V1_0::KeyRequestType;
using drm::V1_0::KeyType;
@ -496,10 +498,6 @@ Return<void> DrmHal::sendEvent(EventType hEventType,
mEventLock.unlock();
if (listener != NULL) {
Parcel obj;
writeByteArray(obj, sessionId);
writeByteArray(obj, data);
Mutex::Autolock lock(mNotifyLock);
DrmPlugin::EventType eventType;
switch(hEventType) {
@ -521,7 +519,7 @@ Return<void> DrmHal::sendEvent(EventType hEventType,
default:
return Void();
}
listener->notify(eventType, 0, &obj);
listener->sendEvent(eventType, sessionId, data);
}
return Void();
}
@ -534,12 +532,8 @@ Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
mEventLock.unlock();
if (listener != NULL) {
Parcel obj;
writeByteArray(obj, sessionId);
obj.writeInt64(expiryTimeInMS);
Mutex::Autolock lock(mNotifyLock);
listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
}
return Void();
}
@ -556,21 +550,17 @@ Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
}
Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
const hidl_vec<KeyStatus>& hKeyStatusList, bool hasNewUsableKey) {
mEventLock.lock();
sp<IDrmClient> listener = mListener;
mEventLock.unlock();
if (listener != NULL) {
Parcel obj;
writeByteArray(obj, sessionId);
size_t nKeys = keyStatusList.size();
obj.writeInt32(nKeys);
std::vector<DrmKeyStatus> keyStatusList;
size_t nKeys = hKeyStatusList.size();
for (size_t i = 0; i < nKeys; ++i) {
const KeyStatus &keyStatus = keyStatusList[i];
writeByteArray(obj, keyStatus.keyId);
const KeyStatus &keyStatus = hKeyStatusList[i];
uint32_t type;
switch(keyStatus.type) {
case KeyStatusType::USABLE:
@ -593,19 +583,18 @@ Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
type = DrmPlugin::kKeyStatusType_InternalError;
break;
}
obj.writeInt32(type);
keyStatusList.push_back({type, keyStatus.keyId});
mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
}
obj.writeInt32(hasNewUsableKey);
Mutex::Autolock lock(mNotifyLock);
listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
} else {
// There's no listener. But we still want to count the key change
// events.
size_t nKeys = keyStatusList.size();
size_t nKeys = hKeyStatusList.size();
for (size_t i = 0; i < nKeys; i++) {
mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
mMetrics.mKeyStatusChangeCounter.Increment(hKeyStatusList[i].type);
}
}
@ -620,10 +609,8 @@ Return<void> DrmHal::sendSessionLostState(
mEventLock.unlock();
if (listener != NULL) {
Parcel obj;
writeByteArray(obj, sessionId);
Mutex::Autolock lock(mNotifyLock);
listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
listener->sendSessionLostState(sessionId);
}
return Void();
}
@ -1585,16 +1572,6 @@ void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
cleanup();
}
void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
{
if (vec.size()) {
obj.writeInt32(vec.size());
obj.write(vec.data(), vec.size());
} else {
obj.writeInt32(0);
}
}
void DrmHal::reportFrameworkMetrics() const
{
std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm"));

@ -17,39 +17,104 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "IDrmClient"
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <hidl/HidlSupport.h>
#include <media/IMediaPlayerClient.h>
#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrmClient.h>
#include <cstddef>
#include <cstdint>
#include <vector>
namespace android {
enum {
NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
SEND_EVENT = IBinder::FIRST_CALL_TRANSACTION,
SEND_EXPIRATION_UPDATE,
SEND_KEYS_CHANGE,
SEND_SESSION_LOST_STATE,
};
namespace {
hardware::hidl_vec<uint8_t> ReadByteArray(const Parcel &obj, status_t *err)
{
int32_t len = obj.readInt32();
hardware::hidl_vec<uint8_t> ret;
if (len < 0) {
ALOGE("Invalid array len");
*err = BAD_VALUE;
return ret;
}
ret.resize(static_cast<size_t>(len));
*err = obj.read(ret.data(), ret.size());
return ret;
}
}
class BpDrmClient: public BpInterface<IDrmClient>
{
template <typename F>
void notify(uint32_t code, F fillParcel) {
Parcel obj, reply;
obj.writeInterfaceToken(IDrmClient::getInterfaceDescriptor());
fillParcel(obj);
remote()->transact(code, obj, &reply, IBinder::FLAG_ONEWAY);
}
public:
explicit BpDrmClient(const sp<IBinder>& impl)
: BpInterface<IDrmClient>(impl)
{
}
virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj)
virtual void sendEvent(
DrmPlugin::EventType eventType,
const hardware::hidl_vec<uint8_t> &sessionId,
const hardware::hidl_vec<uint8_t> &data)
{
Parcel data, reply;
data.writeInterfaceToken(IDrmClient::getInterfaceDescriptor());
data.writeInt32((int)eventType);
data.writeInt32(extra);
if (obj && obj->dataSize() > 0) {
data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
}
remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
auto fillParcel = [&] (Parcel &p) {
DrmUtils::WriteEventToParcel(p, eventType, sessionId, data);
};
notify(SEND_EVENT, fillParcel);
}
virtual void sendExpirationUpdate(
const hardware::hidl_vec<uint8_t> &sessionId,
int64_t expiryTimeInMS)
{
auto fillParcel = [&] (Parcel &p) {
DrmUtils::WriteExpirationUpdateToParcel(p, sessionId, expiryTimeInMS);
};
notify(SEND_EXPIRATION_UPDATE, fillParcel);
}
virtual void sendKeysChange(
const hardware::hidl_vec<uint8_t> &sessionId,
const std::vector<DrmKeyStatus> &keyStatusList,
bool hasNewUsableKey)
{
auto fillParcel = [&] (Parcel &p) {
DrmUtils::WriteKeysChange(p, sessionId, keyStatusList, hasNewUsableKey);
};
notify(SEND_KEYS_CHANGE, fillParcel);
}
virtual void sendSessionLostState(
const hardware::hidl_vec<uint8_t> &sessionId)
{
auto fillParcel = [&] (Parcel &p) {
DrmUtils::WriteByteArray(p, sessionId);
};
notify(SEND_SESSION_LOST_STATE, fillParcel);
}
};
@ -58,23 +123,58 @@ IMPLEMENT_META_INTERFACE(DrmClient, "android.media.IDrmClient");
// ----------------------------------------------------------------------
status_t BnDrmClient::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
uint32_t code, const Parcel& obj, Parcel* reply, uint32_t flags)
{
CHECK_INTERFACE(IDrmClient, obj, reply);
status_t err = NO_ERROR;
hardware::hidl_vec<uint8_t> sessionId(ReadByteArray(obj, &err));
if (err != NO_ERROR) {
ALOGE("Failed to read session id, error=%d", err);
return err;
}
switch (code) {
case NOTIFY: {
CHECK_INTERFACE(IDrmClient, data, reply);
int eventType = data.readInt32();
int extra = data.readInt32();
Parcel obj;
if (data.dataAvail() > 0) {
obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
case SEND_EVENT: {
hardware::hidl_vec<uint8_t> data(ReadByteArray(obj, &err));
int eventType = obj.readInt32();
if (err == NO_ERROR) {
sendEvent(static_cast<DrmPlugin::EventType>(eventType), sessionId, data);
}
notify((DrmPlugin::EventType)eventType, extra, &obj);
return err;
} break;
case SEND_EXPIRATION_UPDATE: {
int64_t expiryTimeInMS = obj.readInt64();
sendExpirationUpdate(sessionId, expiryTimeInMS);
return NO_ERROR;
} break;
case SEND_KEYS_CHANGE: {
// ...
int32_t n = obj.readInt32();
if (n < 0) {
return BAD_VALUE;
}
std::vector<DrmKeyStatus> keyStatusList;
for (int32_t i = 0; i < n; ++i) {
hardware::hidl_vec<uint8_t> keyId(ReadByteArray(obj, &err));
if (err != NO_ERROR) {
return err;
}
int32_t type = obj.readInt32();
if (type < 0) {
return BAD_VALUE;
}
keyStatusList.push_back({static_cast<uint32_t>(type), keyId});
}
int32_t hasNewUsableKey = obj.readInt32();
sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
return NO_ERROR;
} break;
case SEND_SESSION_LOST_STATE: {
sendSessionLostState(sessionId);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
return BBinder::onTransact(code, obj, reply, flags);
}
}

@ -22,14 +22,41 @@
#include <binder/Parcel.h>
#include <media/drm/DrmAPI.h>
#include <android/hardware/drm/1.2/types.h>
#include <hidl/HidlSupport.h>
#include <cstdint>
#include <vector>
namespace android {
struct DrmKeyStatus {
const uint32_t type;
const hardware::hidl_vec<uint8_t> keyId;
};
class IDrmClient: public IInterface
{
public:
DECLARE_META_INTERFACE(DrmClient);
virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) = 0;
virtual void sendEvent(
DrmPlugin::EventType eventType,
const hardware::hidl_vec<uint8_t> &sessionId,
const hardware::hidl_vec<uint8_t> &data) = 0;
virtual void sendExpirationUpdate(
const hardware::hidl_vec<uint8_t> &sessionId,
int64_t expiryTimeInMS) = 0;
virtual void sendKeysChange(
const hardware::hidl_vec<uint8_t> &sessionId,
const std::vector<DrmKeyStatus> &keyStatusList,
bool hasNewUsableKey) = 0;
virtual void sendSessionLostState(
const hardware::hidl_vec<uint8_t> &sessionId) = 0;
};
// ----------------------------------------------------------------------------

@ -19,6 +19,7 @@
#include <utils/Errors.h> // for status_t
#include <utils/StrongPointer.h>
#include <binder/Parcel.h>
namespace android {
@ -33,6 +34,49 @@ sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
sp<ICrypto> MakeCrypto(status_t *pstatus = nullptr);
template<typename BA>
void WriteByteArray(Parcel &obj, const BA &vec) {
obj.writeInt32(vec.size());
if (vec.size()) {
obj.write(vec.data(), vec.size());
}
}
template<typename ET, typename BA>
void WriteEventToParcel(
Parcel &obj,
ET eventType,
const BA &sessionId,
const BA &data) {
WriteByteArray(obj, sessionId);
WriteByteArray(obj, data);
obj.writeInt32(eventType);
}
template<typename BA>
void WriteExpirationUpdateToParcel(
Parcel &obj,
const BA &sessionId,
int64_t expiryTimeInMS) {
WriteByteArray(obj, sessionId);
obj.writeInt64(expiryTimeInMS);
}
template<typename BA, typename KSL>
void WriteKeysChange(
Parcel &obj,
const BA &sessionId,
const KSL &keyStatusList,
bool hasNewUsableKey) {
WriteByteArray(obj, sessionId);
obj.writeInt32(keyStatusList.size());
for (const auto &keyStatus : keyStatusList) {
WriteByteArray(obj, keyStatus.keyId);
obj.writeInt32(keyStatus.type);
}
obj.writeInt32(hasNewUsableKey);
}
} // namespace DrmUtils
} // namespace android

@ -72,12 +72,27 @@ public:
mKeysChangeListener = listener;
}
void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
void sendEvent(
DrmPlugin::EventType eventType,
const hardware::hidl_vec<uint8_t> &sessionId,
const hardware::hidl_vec<uint8_t> &data) override;
void sendExpirationUpdate(
const hardware::hidl_vec<uint8_t> &sessionId,
int64_t expiryTimeInMS) override;
void sendKeysChange(
const hardware::hidl_vec<uint8_t> &sessionId,
const std::vector<DrmKeyStatus> &keyStatusList,
bool hasNewUsableKey) override;
void sendSessionLostState(
const hardware::hidl_vec<uint8_t> &) override {}
};
struct AMediaDrm {
sp<IDrm> mDrm;
sp<IDrmClient> mDrmClient;
List<idvec_t> mIds;
KeyedVector<String8, String8> mQueryResults;
Vector<uint8_t> mKeyRequest;
@ -89,71 +104,52 @@ struct AMediaDrm {
sp<DrmListener> mListener;
};
void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
if (!mEventListener || !mExpirationUpdateListener || !mKeysChangeListener) {
ALOGE("No listeners are specified");
void DrmListener::sendExpirationUpdate(
const hardware::hidl_vec<uint8_t> &sessionId,
int64_t expiryTimeInMS) {
if (!mExpirationUpdateListener) {
ALOGE("No ExpirationUpdateListener specified");
return;
}
obj->setDataPosition(0);
AMediaDrmSessionId sessionId = {NULL, 0};
int32_t sessionIdSize = obj->readInt32();
if (sessionIdSize <= 0) {
ALOGE("Invalid session id size");
return;
if (expiryTimeInMS >= 0) {
AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
(*mExpirationUpdateListener)(mObj, &asid, expiryTimeInMS);
} else {
ALOGE("expiry time negative, status=%" PRId64 "", expiryTimeInMS);
}
}
std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
sessionId.ptr = sessionIdData.get();
sessionId.length = sessionIdSize;
status_t err = obj->read(sessionIdData.get(), sessionId.length);
if (err != OK) {
ALOGE("Failed to read session id, error=%d", err);
void DrmListener::sendKeysChange(
const hardware::hidl_vec<uint8_t> &sessionId,
const std::vector<DrmKeyStatus> &keyStatusList,
bool hasNewUsableKey) {
if (!mKeysChangeListener) {
ALOGE("No KeysChangeListener specified");
return;
}
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;
Vector<AMediaDrmKeyStatus> keysStatus;
for (const auto &drmKeyStatus : keyStatusList) {
AMediaDrmKeyStatus keyStatus;
keyStatus.keyId.ptr = drmKeyStatus.keyId.data();
keyStatus.keyId.length = drmKeyStatus.keyId.size();
keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(drmKeyStatus.type);
keysStatus.push(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);
}
AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
int32_t numKeys = keyStatusList.size();
(*mKeysChangeListener)(mObj, &asid, keysStatus.array(), numKeys, hasNewUsableKey);
return;
}
bool hasNewUsableKey = obj->readInt32();
(*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
void DrmListener::sendEvent(
DrmPlugin::EventType eventType,
const hardware::hidl_vec<uint8_t> &sessionId,
const hardware::hidl_vec<uint8_t> &data) {
if (!mEventListener) {
ALOGE("No EventListener specified");
return;
}
@ -177,23 +173,17 @@ void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel
ndkEventType = EVENT_SESSION_RECLAIMED;
break;
default:
ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
ALOGE("Invalid event DrmPlugin::EventType %d, ignored", eventType);
return;
}
int32_t dataSize = obj->readInt32();
uint8_t *data = NULL;
AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
int32_t dataSize = data.size();
const uint8_t *dataPtr = data.data();
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;
(*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
} else {
ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
ALOGE("invalid event data size=%d", dataSize);
}
}

Loading…
Cancel
Save