MediaDrm: remove Parcel from event listener impl

Bug: 134787536
Test: MediaDrmClearkeyTest
Test: MediaDrmMockTest
Change-Id: I0ae07ed2477de0da53a3622d86adc106723c1acf
This commit is contained in:
Robert Shih
2019-11-08 13:51:49 -08:00
parent a2267bb525
commit 9d4e2d48a3
3 changed files with 109 additions and 46 deletions

View File

@@ -748,12 +748,12 @@ public final class MediaDrm implements AutoCloseable {
private Consumer<ListenerArgs> createOnEventListener(OnEventListener listener) {
return args -> {
byte[] sessionId = args.parcel.createByteArray();
byte[] sessionId = args.sessionId;
if (sessionId.length == 0) {
sessionId = null;
}
byte[] data = args.parcel.createByteArray();
if (data.length == 0) {
byte[] data = args.data;
if (data != null && data.length == 0) {
data = null;
}
@@ -765,10 +765,10 @@ public final class MediaDrm implements AutoCloseable {
private Consumer<ListenerArgs> createOnKeyStatusChangeListener(
OnKeyStatusChangeListener listener) {
return args -> {
byte[] sessionId = args.parcel.createByteArray();
byte[] sessionId = args.sessionId;
if (sessionId.length > 0) {
List<KeyStatus> keyStatusList = keyStatusListFromParcel(args.parcel);
boolean hasNewUsableKey = (args.parcel.readInt() != 0);
List<KeyStatus> keyStatusList = args.keyStatusList;
boolean hasNewUsableKey = args.hasNewUsableKey;
Log.i(TAG, "Drm key status changed");
listener.onKeyStatusChange(this, sessionId, keyStatusList, hasNewUsableKey);
@@ -779,9 +779,9 @@ public final class MediaDrm implements AutoCloseable {
private Consumer<ListenerArgs> createOnExpirationUpdateListener(
OnExpirationUpdateListener listener) {
return args -> {
byte[] sessionId = args.parcel.createByteArray();
byte[] sessionId = args.sessionId;
if (sessionId.length > 0) {
long expirationTime = args.parcel.readLong();
long expirationTime = args.expirationTime;
Log.i(TAG, "Drm key expiration update: " + expirationTime);
listener.onExpirationUpdate(this, sessionId, expirationTime);
@@ -792,22 +792,38 @@ public final class MediaDrm implements AutoCloseable {
private Consumer<ListenerArgs> createOnSessionLostStateListener(
OnSessionLostStateListener listener) {
return args -> {
byte[] sessionId = args.parcel.createByteArray();
byte[] sessionId = args.sessionId;
Log.i(TAG, "Drm session lost state event: ");
listener.onSessionLostState(this, sessionId);
};
}
private static class ListenerArgs {
private final Parcel parcel;
private final int arg1;
private final int arg2;
private final byte[] sessionId;
private final byte[] data;
private final long expirationTime;
private final List<KeyStatus> keyStatusList;
private final boolean hasNewUsableKey;
public ListenerArgs(Parcel parcel, int arg1, int arg2) {
this.parcel = parcel;
public ListenerArgs(
int arg1,
int arg2,
byte[] sessionId,
byte[] data,
long expirationTime,
List<KeyStatus> keyStatusList,
boolean hasNewUsableKey) {
this.arg1 = arg1;
this.arg2 = arg2;
this.sessionId = sessionId;
this.data = data;
this.expirationTime = expirationTime;
this.keyStatusList = keyStatusList;
this.hasNewUsableKey = hasNewUsableKey;
}
}
private static class ListenerWithExecutor {
@@ -843,7 +859,9 @@ public final class MediaDrm implements AutoCloseable {
* the cookie passed to native_setup().)
*/
private static void postEventFromNative(@NonNull Object mediadrm_ref,
int what, int eventType, int extra, @Nullable Object obj)
int what, int eventType, int extra,
byte[] sessionId, byte[] data, long expirationTime,
List<KeyStatus> keyStatusList, boolean hasNewUsableKey)
{
MediaDrm md = (MediaDrm)((WeakReference<MediaDrm>)mediadrm_ref).get();
if (md == null) {
@@ -861,10 +879,10 @@ public final class MediaDrm implements AutoCloseable {
Log.w(TAG, "MediaDrm went away with unhandled events");
return;
}
if (obj != null && obj instanceof Parcel) {
Parcel p = (Parcel)obj;
listener.mConsumer.accept(new ListenerArgs(p, eventType, extra));
}
ListenerArgs args = new ListenerArgs(eventType, extra,
sessionId, data, expirationTime,
keyStatusList, hasNewUsableKey);
listener.mConsumer.accept(args);
};
listener.mExecutor.execute(command);
}

View File

@@ -179,6 +179,10 @@ struct OfflineLicenseState {
jint kOfflineLicenseStateUnknown;
} gOfflineLicenseStates;
struct KeyStatusFields {
jmethodID init;
jclass classId;
};
struct fields_t {
jfieldID context;
@@ -200,6 +204,7 @@ struct fields_t {
jobject bundleCreator;
jmethodID createFromParcelId;
jclass parcelCreatorClassId;
KeyStatusFields keyStatus;
};
static fields_t gFields;
@@ -247,6 +252,17 @@ jobject nativeToJavaPersistableBundle(JNIEnv *env, jobject thiz,
return newBundle;
}
jbyteArray hidlVectorToJByteArray(const hardware::hidl_vec<uint8_t> &vector) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
size_t length = vector.size();
jbyteArray result = env->NewByteArray(length);
if (result != NULL) {
env->SetByteArrayRegion(result, 0, length, reinterpret_cast<const jbyte *>(vector.data()));
}
return result;
}
} // namespace anonymous
// ----------------------------------------------------------------------------
@@ -256,7 +272,7 @@ class JNIDrmListener: public DrmListener
public:
JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
~JNIDrmListener();
virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj = NULL);
virtual void notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *arg = NULL);
private:
JNIDrmListener();
jclass mClass; // Reference to MediaDrm class
@@ -290,7 +306,7 @@ JNIDrmListener::~JNIDrmListener()
}
void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
const Parcel *obj)
const ListenerArgs *args)
{
jint jwhat;
jint jeventType = 0;
@@ -332,15 +348,11 @@ void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (obj && obj->dataSize() > 0) {
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL) {
Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
nativeParcel->setData(obj->data(), obj->dataSize());
env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
jwhat, jeventType, extra, jParcel);
env->DeleteLocalRef(jParcel);
}
if (args) {
env->CallStaticVoidMethod(mClass, gFields.post_event, mObject,
jwhat, jeventType, extra,
args->jSessionId, args->jData, args->jExpirationTime,
args->jKeyStatusList, args->jHasNewUsableKey);
}
if (env->ExceptionCheck()) {
@@ -511,7 +523,7 @@ status_t JDrm::setListener(const sp<DrmListener>& listener) {
return OK;
}
void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
void JDrm::notify(DrmPlugin::EventType eventType, int extra, const ListenerArgs *args) {
sp<DrmListener> listener;
mLock.lock();
listener = mListener;
@@ -519,7 +531,7 @@ void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj)
if (listener != NULL) {
Mutex::Autolock lock(mNotifyLock);
listener->notify(eventType, extra, obj);
listener->notify(eventType, extra, args);
}
}
@@ -527,34 +539,51 @@ void JDrm::sendEvent(
DrmPlugin::EventType eventType,
const hardware::hidl_vec<uint8_t> &sessionId,
const hardware::hidl_vec<uint8_t> &data) {
Parcel obj;
DrmUtils::WriteByteArray(obj, sessionId);
DrmUtils::WriteByteArray(obj, data);
notify(eventType, 0, &obj);
ListenerArgs args{
.jSessionId = hidlVectorToJByteArray(sessionId),
.jData = hidlVectorToJByteArray(data),
};
notify(eventType, 0, &args);
}
void JDrm::sendExpirationUpdate(
const hardware::hidl_vec<uint8_t> &sessionId,
int64_t expiryTimeInMS) {
Parcel obj;
DrmUtils::WriteExpirationUpdateToParcel(obj, sessionId, expiryTimeInMS);
notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
ListenerArgs args{
.jSessionId = hidlVectorToJByteArray(sessionId),
.jExpirationTime = expiryTimeInMS,
};
notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &args);
}
void JDrm::sendKeysChange(
const hardware::hidl_vec<uint8_t> &sessionId,
const std::vector<DrmKeyStatus> &keyStatusList,
bool hasNewUsableKey) {
Parcel obj;
DrmUtils::WriteKeysChange(obj, sessionId, keyStatusList, hasNewUsableKey);
notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = gFields.arraylistClassId;
jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
clazz = gFields.keyStatus.classId;
for (const auto &keyStatus : keyStatusList) {
jbyteArray jKeyId(hidlVectorToJByteArray(keyStatus.keyId));
jint jStatusCode(keyStatus.type);
jobject jKeyStatus = env->NewObject(clazz, gFields.keyStatus.init, jKeyId, jStatusCode);
env->CallBooleanMethod(arrayList, gFields.arraylist.add, jKeyStatus);
}
ListenerArgs args{
.jSessionId = hidlVectorToJByteArray(sessionId),
.jKeyStatusList = arrayList,
.jHasNewUsableKey = hasNewUsableKey,
};
notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &args);
}
void JDrm::sendSessionLostState(
const hardware::hidl_vec<uint8_t> &sessionId) {
Parcel obj;
DrmUtils::WriteByteArray(obj, sessionId);
notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
ListenerArgs args{
.jSessionId = hidlVectorToJByteArray(sessionId),
};
notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &args);
}
void JDrm::disconnect() {
@@ -753,7 +782,7 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
FIND_CLASS(clazz, "android/media/MediaDrm");
GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "J");
GET_STATIC_METHOD_ID(gFields.post_event, clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
"(Ljava/lang/Object;III[B[BJLjava/util/List;Z)V");
jfieldID field;
GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
@@ -913,6 +942,10 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
FIND_CLASS(clazz, "android/media/MediaDrm$KeyStatus");
gFields.keyStatus.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
GET_METHOD_ID(gFields.keyStatus.init, clazz, "<init>", "([BI)V");
}
static void android_media_MediaDrm_native_setup(

View File

@@ -26,13 +26,25 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
namespace {
struct ListenerArgs {
jbyteArray jSessionId;
jbyteArray jData;
jlong jExpirationTime;
jobject jKeyStatusList;
jboolean jHasNewUsableKey;
};
}
namespace android {
class DrmListener: virtual public RefBase
{
public:
virtual void notify(DrmPlugin::EventType eventType, int extra,
const Parcel *obj) = 0;
const ListenerArgs *args) = 0;
};
struct JDrm : public BnDrmClient {
@@ -81,7 +93,7 @@ private:
static sp<IDrm> MakeDrm();
static sp<IDrm> MakeDrm(const uint8_t uuid[16], const String8 &appPackageName);
void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
void notify(DrmPlugin::EventType, int extra, const ListenerArgs *args);
DISALLOW_EVIL_CONSTRUCTORS(JDrm);
};