Merge "Implementing MediaDrm APIs" into jb-mr2-dev
This commit is contained in:
366
media/java/android/media/MediaDrm.java
Normal file
366
media/java/android/media/MediaDrm.java
Normal file
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.media;
|
||||
|
||||
import android.media.MediaDrmException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.UUID;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* MediaDrm class can be used in conjunction with {@link android.media.MediaCrypto}
|
||||
* to obtain licenses for decoding encrypted media data.
|
||||
*
|
||||
* Crypto schemes are assigned 16 byte UUIDs,
|
||||
* the method {@link #isCryptoSchemeSupported} can be used to query if a given
|
||||
* scheme is supported on the device.
|
||||
*
|
||||
* <a name="Callbacks"></a>
|
||||
* <h3>Callbacks</h3>
|
||||
* <p>Applications may want to register for informational events in order
|
||||
* to be informed of some internal state update during playback or streaming.
|
||||
* Registration for these events is done via a call to
|
||||
* {@link #setOnEventListener(OnInfoListener)}setOnInfoListener,
|
||||
* In order to receive the respective callback
|
||||
* associated with this listener, applications are required to create
|
||||
* MediaDrm objects on a thread with its own Looper running (main UI
|
||||
* thread by default has a Looper running).
|
||||
*
|
||||
* @hide -- don't expose yet
|
||||
*/
|
||||
public final class MediaDrm {
|
||||
|
||||
private final static String TAG = "MediaDrm";
|
||||
|
||||
private EventHandler mEventHandler;
|
||||
private OnEventListener mOnEventListener;
|
||||
|
||||
private int mNativeContext;
|
||||
|
||||
/**
|
||||
* Query if the given scheme identified by its UUID is supported on
|
||||
* this device.
|
||||
* @param uuid The UUID of the crypto scheme.
|
||||
*/
|
||||
public static final boolean isCryptoSchemeSupported(UUID uuid) {
|
||||
return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid));
|
||||
}
|
||||
|
||||
private static final byte[] getByteArrayFromUUID(UUID uuid) {
|
||||
long msb = uuid.getMostSignificantBits();
|
||||
long lsb = uuid.getLeastSignificantBits();
|
||||
|
||||
byte[] uuidBytes = new byte[16];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
uuidBytes[i] = (byte)(msb >>> (8 * (7 - i)));
|
||||
uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i)));
|
||||
}
|
||||
|
||||
return uuidBytes;
|
||||
}
|
||||
|
||||
private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid);
|
||||
|
||||
/**
|
||||
* Instantiate a MediaDrm object using opaque, crypto scheme specific
|
||||
* data.
|
||||
* @param uuid The UUID of the crypto scheme.
|
||||
*/
|
||||
public MediaDrm(UUID uuid) throws MediaDrmException {
|
||||
Looper looper;
|
||||
if ((looper = Looper.myLooper()) != null) {
|
||||
mEventHandler = new EventHandler(this, looper);
|
||||
} else if ((looper = Looper.getMainLooper()) != null) {
|
||||
mEventHandler = new EventHandler(this, looper);
|
||||
} else {
|
||||
mEventHandler = null;
|
||||
}
|
||||
|
||||
/* Native setup requires a weak reference to our object.
|
||||
* It's easier to create it here than in C++.
|
||||
*/
|
||||
native_setup(new WeakReference<MediaDrm>(this),
|
||||
getByteArrayFromUUID(uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when an event occurs
|
||||
*
|
||||
* @param listener the callback that will be run
|
||||
*/
|
||||
public void setOnEventListener(OnEventListener listener)
|
||||
{
|
||||
mOnEventListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when a drm event
|
||||
* occurs.
|
||||
*/
|
||||
public interface OnEventListener
|
||||
{
|
||||
/**
|
||||
* Called when an event occurs that requires the app to be notified
|
||||
*
|
||||
* @param md the MediaDrm object on which the event occurred
|
||||
* @param sessionId the DRM session ID on which the event occurred
|
||||
* @param event indicates the event type
|
||||
* @param extra an secondary error code
|
||||
* @param data optional byte array of data that may be associated with the event
|
||||
*/
|
||||
void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data);
|
||||
}
|
||||
|
||||
/* Do not change these values without updating their counterparts
|
||||
* in include/media/mediadrm.h!
|
||||
*/
|
||||
private static final int DRM_EVENT = 200;
|
||||
|
||||
private class EventHandler extends Handler
|
||||
{
|
||||
private MediaDrm mMediaDrm;
|
||||
|
||||
public EventHandler(MediaDrm md, Looper looper) {
|
||||
super(looper);
|
||||
mMediaDrm = md;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (mMediaDrm.mNativeContext == 0) {
|
||||
Log.w(TAG, "MediaDrm went away with unhandled events");
|
||||
return;
|
||||
}
|
||||
switch(msg.what) {
|
||||
|
||||
case DRM_EVENT:
|
||||
Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
|
||||
|
||||
if (mOnEventListener != null) {
|
||||
Bundle bundle = msg.getData();
|
||||
byte[] sessionId = bundle.getByteArray("sessionId");
|
||||
byte[] data = bundle.getByteArray("data");
|
||||
mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
Log.e(TAG, "Unknown message type " + msg.what);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from native code when an interesting event happens. This method
|
||||
* just uses the EventHandler system to post the event back to the main app thread.
|
||||
* We use a weak reference to the original MediaPlayer object so that the native
|
||||
* code is safe from the object disappearing from underneath it. (This is
|
||||
* the cookie passed to native_setup().)
|
||||
*/
|
||||
private static void postEventFromNative(Object mediadrm_ref,
|
||||
int what, int arg1, int arg2, Object obj)
|
||||
{
|
||||
MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get();
|
||||
if (md == null) {
|
||||
return;
|
||||
}
|
||||
if (md.mEventHandler != null) {
|
||||
Message m = md.mEventHandler.obtainMessage(what, arg1, arg2, obj);
|
||||
md.mEventHandler.sendMessage(m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a new session with the MediaDrm object. A session ID is returned.
|
||||
*/
|
||||
public native byte[] openSession() throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* Close a session on the MediaDrm object.
|
||||
*/
|
||||
public native void closeSession(byte[] sessionId) throws MediaDrmException;
|
||||
|
||||
public static final int MEDIA_DRM_LICENSE_TYPE_STREAMING = 1;
|
||||
public static final int MEDIA_DRM_LICENSE_TYPE_OFFLINE = 2;
|
||||
|
||||
public final class LicenseRequest {
|
||||
public LicenseRequest() {}
|
||||
public byte[] data;
|
||||
public String defaultUrl;
|
||||
};
|
||||
|
||||
/**
|
||||
* A license request/response exchange occurs between the app and a License
|
||||
* Server to obtain the keys required to decrypt the content. getLicenseRequest()
|
||||
* is used to obtain an opaque license request byte array that is delivered to the
|
||||
* license server. The opaque license request byte array is returned in
|
||||
* LicenseReqeust.data. The recommended URL to deliver the license request to is
|
||||
* returned in LicenseRequest.defaultUrl
|
||||
*
|
||||
* @param sessonId the session ID for the drm session
|
||||
* @param init container-specific data, its meaning is interpreted based on the
|
||||
* mime type provided in the mimeType parameter. It could contain, for example,
|
||||
* the content ID, key ID or other data obtained from the content metadata that is
|
||||
* required in generating the license request.
|
||||
* @param mimeType identifies the mime type of the content
|
||||
* @param licenseType specifes if the license is for streaming or offline content
|
||||
* @param optionalParameters are included in the license server request message to
|
||||
* allow a client application to provide additional message parameters to the server.
|
||||
*/
|
||||
public native LicenseRequest getLicenseRequest( byte[] sessionId, byte[] init,
|
||||
String mimeType, int licenseType,
|
||||
HashMap<String, String> optionalParameters )
|
||||
throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* After a license response is received by the app, it is provided to the DRM plugin
|
||||
* using provideLicenseResponse.
|
||||
*
|
||||
* @param sessionId the session ID for the DRM session
|
||||
* @param response the byte array response from the server
|
||||
*/
|
||||
public native void provideLicenseResponse( byte[] sessionId, byte[] response )
|
||||
throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* Remove the keys associated with a license for a session
|
||||
* @param sessionId the session ID for the DRM session
|
||||
*/
|
||||
public native void removeLicense( byte[] sessionId ) throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* Request an informative description of the license for the session. The status is
|
||||
* in the form of {name, value} pairs. Since DRM license policies vary by vendor,
|
||||
* the specific status field names are determined by each DRM vendor. Refer to your
|
||||
* DRM provider documentation for definitions of the field names for a particular
|
||||
* DrmEngine.
|
||||
*
|
||||
* @param sessionId the session ID for the DRM session
|
||||
*/
|
||||
public native HashMap<String, String> queryLicenseStatus( byte[] sessionId )
|
||||
throws MediaDrmException;
|
||||
|
||||
public final class ProvisionRequest {
|
||||
public ProvisionRequest() {}
|
||||
public byte[] data;
|
||||
public String defaultUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* A provision request/response exchange occurs between the app and a provisioning
|
||||
* server to retrieve a device certificate. getProvisionRequest is used to obtain
|
||||
* an opaque license request byte array that is delivered to the provisioning server.
|
||||
* The opaque provision request byte array is returned in ProvisionRequest.data
|
||||
* The recommended URL to deliver the license request to is returned in
|
||||
* ProvisionRequest.defaultUrl.
|
||||
*/
|
||||
public native ProvisionRequest getProvisionRequest() throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* After a provision response is received by the app, it is provided to the DRM
|
||||
* plugin using this method.
|
||||
*
|
||||
* @param response the opaque provisioning response byte array to provide to the
|
||||
* DrmEngine.
|
||||
*/
|
||||
public native void provideProvisionResponse( byte[] response )
|
||||
throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* A means of enforcing the contractual requirement for a concurrent stream limit
|
||||
* per subscriber across devices is provided via SecureStop. SecureStop is a means
|
||||
* of securely monitoring the lifetime of sessions. Since playback on a device can
|
||||
* be interrupted due to reboot, power failure, etc. a means of persisting the
|
||||
* lifetime information on the device is needed.
|
||||
*
|
||||
* A signed version of the sessionID is written to persistent storage on the device
|
||||
* when each MediaCrypto object is created. The sessionID is signed by the device
|
||||
* private key to prevent tampering.
|
||||
*
|
||||
* In the normal case, playback will be completed, the session destroyed and the
|
||||
* Secure Stops will be queried. The App queries secure stops and forwards the
|
||||
* secure stop message to the server which verifies the signature and notifies the
|
||||
* server side database that the session destruction has been confirmed. The persisted
|
||||
* record on the client is only removed after positive confirmation that the server
|
||||
* received the message using releaseSecureStops().
|
||||
*/
|
||||
public native List<byte[]> getSecureStops() throws MediaDrmException;
|
||||
|
||||
|
||||
/**
|
||||
* Process the SecureStop server response message ssRelease. After authenticating
|
||||
* the message, remove the SecureStops identiied in the response.
|
||||
*
|
||||
* @param ssRelease the server response indicating which secure stops to release
|
||||
*/
|
||||
public native void releaseSecureStops( byte[] ssRelease )
|
||||
throws MediaDrmException;
|
||||
|
||||
|
||||
/**
|
||||
* Read a Drm plugin property value, given the property name string. There are several
|
||||
* forms of property access functions, depending on the data type returned.
|
||||
*
|
||||
* Standard fields names are:
|
||||
* vendor String - identifies the maker of the plugin
|
||||
* version String - identifies the version of the plugin
|
||||
* description String - describes the plugin
|
||||
* deviceUniqueId byte[] - The device unique identifier is established during device
|
||||
* provisioning and provides a means of uniquely identifying
|
||||
* each device
|
||||
*/
|
||||
public native String getPropertyString( String propertyName )
|
||||
throws MediaDrmException;
|
||||
|
||||
public native byte[] getPropertyByteArray( String propertyName )
|
||||
throws MediaDrmException;
|
||||
|
||||
/**
|
||||
* Write a Drm plugin property value. There are several forms of property setting
|
||||
* functions, depending on the data type being set.
|
||||
*/
|
||||
public native void setPropertyString( String propertyName, String value )
|
||||
throws MediaDrmException;
|
||||
|
||||
public native void setPropertyByteArray( String propertyName, byte[] value )
|
||||
throws MediaDrmException;
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
native_finalize();
|
||||
}
|
||||
|
||||
public native final void release();
|
||||
private static native final void native_init();
|
||||
|
||||
private native final void native_setup(Object mediadrm_this, byte[] uuid)
|
||||
throws MediaDrmException;
|
||||
|
||||
private native final void native_finalize();
|
||||
|
||||
static {
|
||||
System.loadLibrary("media_jni");
|
||||
native_init();
|
||||
}
|
||||
}
|
||||
29
media/java/android/media/MediaDrmException.java
Normal file
29
media/java/android/media/MediaDrmException.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.media;
|
||||
|
||||
/**
|
||||
* Exception thrown if MediaDrm object could not be instantiated for
|
||||
* whatever reason.
|
||||
*
|
||||
* @hide -- don't expose yet
|
||||
*/
|
||||
public final class MediaDrmException extends Exception {
|
||||
public MediaDrmException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
|
||||
android_media_MediaCrypto.cpp \
|
||||
android_media_MediaCodec.cpp \
|
||||
android_media_MediaCodecList.cpp \
|
||||
android_media_MediaDrm.cpp \
|
||||
android_media_MediaExtractor.cpp \
|
||||
android_media_MediaMuxer.cpp \
|
||||
android_media_MediaPlayer.cpp \
|
||||
|
||||
817
media/jni/android_media_MediaDrm.cpp
Normal file
817
media/jni/android_media_MediaDrm.cpp
Normal file
@@ -0,0 +1,817 @@
|
||||
/*
|
||||
* Copyright 2013, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "MediaDrm-JNI"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "android_media_MediaDrm.h"
|
||||
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <media/IDrm.h>
|
||||
#include <media/IMediaPlayerService.h>
|
||||
#include <media/stagefright/foundation/ADebug.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
#define FIND_CLASS(var, className) \
|
||||
var = env->FindClass(className); \
|
||||
LOG_FATAL_IF(! var, "Unable to find class " className);
|
||||
|
||||
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
|
||||
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
|
||||
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
|
||||
|
||||
#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
|
||||
var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
|
||||
LOG_FATAL_IF(! var, "Unable to find method " fieldName);
|
||||
|
||||
struct RequestFields {
|
||||
jfieldID data;
|
||||
jfieldID defaultUrl;
|
||||
};
|
||||
|
||||
struct ArrayListFields {
|
||||
jmethodID init;
|
||||
jmethodID add;
|
||||
};
|
||||
|
||||
struct HashmapFields {
|
||||
jmethodID init;
|
||||
jmethodID get;
|
||||
jmethodID put;
|
||||
jmethodID entrySet;
|
||||
};
|
||||
|
||||
struct SetFields {
|
||||
jmethodID iterator;
|
||||
};
|
||||
|
||||
struct IteratorFields {
|
||||
jmethodID next;
|
||||
jmethodID hasNext;
|
||||
};
|
||||
|
||||
struct EntryFields {
|
||||
jmethodID getKey;
|
||||
jmethodID getValue;
|
||||
};
|
||||
|
||||
struct fields_t {
|
||||
jfieldID context;
|
||||
RequestFields licenseRequest;
|
||||
RequestFields provisionRequest;
|
||||
ArrayListFields arraylist;
|
||||
HashmapFields hashmap;
|
||||
SetFields set;
|
||||
IteratorFields iterator;
|
||||
EntryFields entry;
|
||||
};
|
||||
|
||||
static fields_t gFields;
|
||||
|
||||
static bool throwExceptionAsNecessary(
|
||||
JNIEnv *env, status_t err, const char *msg = NULL) {
|
||||
|
||||
if (err == BAD_VALUE) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", msg);
|
||||
return true;
|
||||
} else if (err != OK) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", msg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
|
||||
JDrm *jdrm = (JDrm *)env->GetIntField(thiz, gFields.context);
|
||||
return jdrm ? jdrm->getDrm() : NULL;
|
||||
}
|
||||
|
||||
JDrm::JDrm(
|
||||
JNIEnv *env, jobject thiz, const uint8_t uuid[16]) {
|
||||
mObject = env->NewWeakGlobalRef(thiz);
|
||||
mDrm = MakeDrm(uuid);
|
||||
}
|
||||
|
||||
JDrm::~JDrm() {
|
||||
mDrm.clear();
|
||||
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
|
||||
env->DeleteWeakGlobalRef(mObject);
|
||||
mObject = NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
sp<IDrm> JDrm::MakeDrm() {
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
|
||||
sp<IBinder> binder =
|
||||
sm->getService(String16("media.player"));
|
||||
|
||||
sp<IMediaPlayerService> service =
|
||||
interface_cast<IMediaPlayerService>(binder);
|
||||
|
||||
if (service == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp<IDrm> drm = service->makeDrm();
|
||||
|
||||
if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return drm;
|
||||
}
|
||||
|
||||
// static
|
||||
sp<IDrm> JDrm::MakeDrm(const uint8_t uuid[16]) {
|
||||
sp<IDrm> drm = MakeDrm();
|
||||
|
||||
if (drm == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_t err = drm->createPlugin(uuid);
|
||||
|
||||
if (err != OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return drm;
|
||||
}
|
||||
|
||||
// static
|
||||
bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) {
|
||||
sp<IDrm> drm = MakeDrm();
|
||||
|
||||
if (drm == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drm->isCryptoSchemeSupported(uuid);
|
||||
}
|
||||
|
||||
status_t JDrm::initCheck() const {
|
||||
return mDrm == NULL ? NO_INIT : OK;
|
||||
}
|
||||
|
||||
// JNI conversion utilities
|
||||
static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) {
|
||||
Vector<uint8_t> vector;
|
||||
size_t length = env->GetArrayLength(byteArray);
|
||||
vector.insertAt((size_t)0, length);
|
||||
env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
|
||||
return vector;
|
||||
}
|
||||
|
||||
static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) {
|
||||
size_t length = vector.size();
|
||||
jbyteArray result = env->NewByteArray(length);
|
||||
if (result != NULL) {
|
||||
env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
|
||||
jboolean isCopy;
|
||||
String8 result;
|
||||
|
||||
const char *s = env->GetStringUTFChars(jstr, &isCopy);
|
||||
if (s) {
|
||||
result = s;
|
||||
env->ReleaseStringUTFChars(jstr, s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.Map.Entry;
|
||||
import jav.util.Iterator;
|
||||
|
||||
HashMap<k, v> hm;
|
||||
Set<Entry<k, v> > s = hm.entrySet();
|
||||
Iterator i = s.iterator();
|
||||
Entry e = s.next();
|
||||
*/
|
||||
|
||||
static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "java/lang/String");
|
||||
KeyedVector<String8, String8> keyedVector;
|
||||
|
||||
jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
|
||||
if (entrySet) {
|
||||
jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
|
||||
if (iterator) {
|
||||
jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
|
||||
while (hasNext) {
|
||||
jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
|
||||
if (entry) {
|
||||
jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
|
||||
if (!env->IsInstanceOf(obj, clazz)) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
}
|
||||
jstring jkey = static_cast<jstring>(obj);
|
||||
|
||||
obj = env->CallObjectMethod(entry, gFields.entry.getValue);
|
||||
if (!env->IsInstanceOf(obj, clazz)) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
}
|
||||
jstring jvalue = static_cast<jstring>(obj);
|
||||
|
||||
String8 key = JStringToString8(env, jkey);
|
||||
String8 value = JStringToString8(env, jvalue);
|
||||
keyedVector.add(key, value);
|
||||
|
||||
env->DeleteLocalRef(jkey);
|
||||
env->DeleteLocalRef(jvalue);
|
||||
hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
|
||||
}
|
||||
env->DeleteLocalRef(entry);
|
||||
}
|
||||
env->DeleteLocalRef(iterator);
|
||||
}
|
||||
env->DeleteLocalRef(entrySet);
|
||||
}
|
||||
return keyedVector;
|
||||
}
|
||||
|
||||
static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "java/util/HashMap");
|
||||
jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
|
||||
for (size_t i = 0; i < map.size(); ++i) {
|
||||
jstring jkey = env->NewStringUTF(map.keyAt(i).string());
|
||||
jstring jvalue = env->NewStringUTF(map.valueAt(i).string());
|
||||
env->CallObjectMethod(hashMap, gFields.hashmap.put, jkey, jvalue);
|
||||
env->DeleteLocalRef(jkey);
|
||||
env->DeleteLocalRef(jvalue);
|
||||
}
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
|
||||
List<Vector<uint8_t> > list) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "java/util/ArrayList");
|
||||
jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
|
||||
List<Vector<uint8_t> >::iterator iter = list.begin();
|
||||
while (iter != list.end()) {
|
||||
jbyteArray byteArray = VectorToJByteArray(env, *iter);
|
||||
env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
|
||||
env->DeleteLocalRef(byteArray);
|
||||
iter++;
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
using namespace android;
|
||||
|
||||
static sp<JDrm> setDrm(
|
||||
JNIEnv *env, jobject thiz, const sp<JDrm> &drm) {
|
||||
sp<JDrm> old = (JDrm *)env->GetIntField(thiz, gFields.context);
|
||||
if (drm != NULL) {
|
||||
drm->incStrong(thiz);
|
||||
}
|
||||
if (old != NULL) {
|
||||
old->decStrong(thiz);
|
||||
}
|
||||
env->SetIntField(thiz, gFields.context, (int)drm.get());
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
|
||||
{
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (jsessionId == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
|
||||
setDrm(env, thiz, NULL);
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_native_init(JNIEnv *env) {
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm");
|
||||
GET_FIELD_ID(gFields.context, clazz, "mNativeContext", "I");
|
||||
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm$LicenseRequest");
|
||||
GET_FIELD_ID(gFields.licenseRequest.data, clazz, "data", "[B");
|
||||
GET_FIELD_ID(gFields.licenseRequest.defaultUrl, clazz, "defaultUrl", "Ljava/lang/String;");
|
||||
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
|
||||
GET_FIELD_ID(gFields.provisionRequest.data, clazz, "data", "[B");
|
||||
GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "defaultUrl", "Ljava/lang/String;");
|
||||
|
||||
FIND_CLASS(clazz, "java/util/ArrayList");
|
||||
GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
|
||||
GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
FIND_CLASS(clazz, "java/util/HashMap");
|
||||
GET_METHOD_ID(gFields.hashmap.init, clazz, "<init>", "()V");
|
||||
GET_METHOD_ID(gFields.hashmap.get, clazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
GET_METHOD_ID(gFields.hashmap.put, clazz, "put",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
GET_METHOD_ID(gFields.hashmap.entrySet, clazz, "entrySet", "()Ljava/util/Set;");
|
||||
|
||||
FIND_CLASS(clazz, "java/util/Set");
|
||||
GET_METHOD_ID(gFields.set.iterator, clazz, "iterator", "()Ljava/util/Iterator;");
|
||||
|
||||
FIND_CLASS(clazz, "java/util/Iterator");
|
||||
GET_METHOD_ID(gFields.iterator.next, clazz, "next", "()Ljava/lang/Object;");
|
||||
GET_METHOD_ID(gFields.iterator.hasNext, clazz, "hasNext", "()Z");
|
||||
|
||||
FIND_CLASS(clazz, "java/util/Map$Entry");
|
||||
GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
|
||||
GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_native_setup(
|
||||
JNIEnv *env, jobject thiz,
|
||||
jobject weak_this, jbyteArray uuidObj) {
|
||||
|
||||
if (uuidObj == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
|
||||
|
||||
if (uuid.size() != 16) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
sp<JDrm> drm = new JDrm(env, thiz, uuid.array());
|
||||
|
||||
status_t err = drm->initCheck();
|
||||
|
||||
if (err != OK) {
|
||||
jniThrowException(
|
||||
env,
|
||||
"android/media/MediaDrmException",
|
||||
"Failed to instantiate drm object.");
|
||||
return;
|
||||
}
|
||||
|
||||
setDrm(env, thiz, drm);
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_native_finalize(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
android_media_MediaDrm_release(env, thiz);
|
||||
}
|
||||
|
||||
static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
|
||||
JNIEnv *env, jobject thiz, jbyteArray uuidObj) {
|
||||
|
||||
if (uuidObj == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
|
||||
|
||||
if (uuid.size() != 16) {
|
||||
jniThrowException(
|
||||
env,
|
||||
"java/lang/IllegalArgumentException",
|
||||
NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return JDrm::IsCryptoSchemeSupported(uuid.array());
|
||||
}
|
||||
|
||||
static jbyteArray android_media_MediaDrm_openSession(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<uint8_t> sessionId;
|
||||
status_t err = drm->openSession(sessionId);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to open session")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return VectorToJByteArray(env, sessionId);
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_closeSession(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (!CheckSession(env, drm, jsessionId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
|
||||
|
||||
status_t err = drm->closeSession(sessionId);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to close session");
|
||||
}
|
||||
|
||||
static jobject android_media_MediaDrm_getLicenseRequest(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
|
||||
jstring jmimeType, jint jlicenseType, jobject joptParams) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (!CheckSession(env, drm, jsessionId)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
|
||||
|
||||
Vector<uint8_t> initData;
|
||||
if (jinitData != NULL) {
|
||||
initData = JByteArrayToVector(env, jinitData);
|
||||
}
|
||||
|
||||
String8 mimeType;
|
||||
if (jmimeType != NULL) {
|
||||
mimeType = JStringToString8(env, jmimeType);
|
||||
}
|
||||
|
||||
DrmPlugin::LicenseType licenseType = (DrmPlugin::LicenseType)jlicenseType;
|
||||
|
||||
KeyedVector<String8, String8> optParams;
|
||||
if (joptParams != NULL) {
|
||||
optParams = HashMapToKeyedVector(env, joptParams);
|
||||
}
|
||||
|
||||
Vector<uint8_t> request;
|
||||
String8 defaultUrl;
|
||||
|
||||
status_t err = drm->getLicenseRequest(sessionId, initData, mimeType,
|
||||
licenseType, optParams, request, defaultUrl);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to get license request")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fill out return obj
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm$LicenseRequest");
|
||||
|
||||
jobject licenseObj = NULL;
|
||||
|
||||
if (clazz) {
|
||||
licenseObj = env->AllocObject(clazz);
|
||||
jbyteArray jrequest = VectorToJByteArray(env, request);
|
||||
env->SetObjectField(licenseObj, gFields.licenseRequest.data, jrequest);
|
||||
|
||||
jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
|
||||
env->SetObjectField(licenseObj, gFields.licenseRequest.defaultUrl, jdefaultUrl);
|
||||
}
|
||||
|
||||
return licenseObj;
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_provideLicenseResponse(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (!CheckSession(env, drm, jsessionId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
|
||||
|
||||
if (jresponse == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
|
||||
|
||||
status_t err = drm->provideLicenseResponse(sessionId, response);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to handle license response");
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_removeLicense(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (!CheckSession(env, drm, jsessionId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
|
||||
|
||||
status_t err = drm->removeLicense(sessionId);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to remove license");
|
||||
}
|
||||
|
||||
static jobject android_media_MediaDrm_queryLicenseStatus(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jsessionId) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (!CheckSession(env, drm, jsessionId)) {
|
||||
return NULL;
|
||||
}
|
||||
Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
|
||||
|
||||
KeyedVector<String8, String8> infoMap;
|
||||
|
||||
status_t err = drm->queryLicenseStatus(sessionId, infoMap);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to query license")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return KeyedVectorToHashMap(env, infoMap);
|
||||
}
|
||||
|
||||
static jobject android_media_MediaDrm_getProvisionRequest(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector<uint8_t> request;
|
||||
String8 defaultUrl;
|
||||
|
||||
status_t err = drm->getProvisionRequest(request, defaultUrl);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fill out return obj
|
||||
jclass clazz;
|
||||
FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
|
||||
|
||||
jobject provisionObj = NULL;
|
||||
|
||||
if (clazz) {
|
||||
provisionObj = env->AllocObject(clazz);
|
||||
jbyteArray jrequest = VectorToJByteArray(env, request);
|
||||
env->SetObjectField(provisionObj, gFields.provisionRequest.data, jrequest);
|
||||
|
||||
jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
|
||||
env->SetObjectField(provisionObj, gFields.provisionRequest.defaultUrl, jdefaultUrl);
|
||||
}
|
||||
|
||||
return provisionObj;
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_provideProvisionResponse(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jresponse) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jresponse == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
|
||||
|
||||
status_t err = drm->provideProvisionResponse(response);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to handle provision response");
|
||||
}
|
||||
|
||||
static jobject android_media_MediaDrm_getSecureStops(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List<Vector<uint8_t> > secureStops;
|
||||
|
||||
status_t err = drm->getSecureStops(secureStops);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to get secure stops")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ListOfVectorsToArrayListOfByteArray(env, secureStops);
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_releaseSecureStops(
|
||||
JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
|
||||
|
||||
status_t err = drm->releaseSecureStops(ssRelease);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to release secure stops");
|
||||
}
|
||||
|
||||
static jstring android_media_MediaDrm_getPropertyString(
|
||||
JNIEnv *env, jobject thiz, jstring jname) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (jname == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
String8 name = JStringToString8(env, jname);
|
||||
String8 value;
|
||||
|
||||
status_t err = drm->getPropertyString(name, value);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return env->NewStringUTF(value.string());
|
||||
}
|
||||
|
||||
static jbyteArray android_media_MediaDrm_getPropertyByteArray(
|
||||
JNIEnv *env, jobject thiz, jstring jname) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (jname == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
String8 name = JStringToString8(env, jname);
|
||||
Vector<uint8_t> value;
|
||||
|
||||
status_t err = drm->getPropertyByteArray(name, value);
|
||||
|
||||
if (throwExceptionAsNecessary(env, err, "Failed to get property")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return VectorToJByteArray(env, value);
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_setPropertyString(
|
||||
JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jname == NULL || jvalue == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
String8 name = JStringToString8(env, jname);
|
||||
String8 value = JStringToString8(env, jvalue);
|
||||
|
||||
status_t err = drm->setPropertyString(name, value);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to set property");
|
||||
}
|
||||
|
||||
static void android_media_MediaDrm_setPropertyByteArray(
|
||||
JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
|
||||
sp<IDrm> drm = GetDrm(env, thiz);
|
||||
|
||||
if (drm == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jname == NULL || jvalue == NULL) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
String8 name = JStringToString8(env, jname);
|
||||
Vector<uint8_t> value = JByteArrayToVector(env, jvalue);
|
||||
|
||||
status_t err = drm->setPropertyByteArray(name, value);
|
||||
|
||||
throwExceptionAsNecessary(env, err, "Failed to set property");
|
||||
}
|
||||
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{ "release", "()V", (void *)android_media_MediaDrm_release },
|
||||
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
|
||||
|
||||
{ "native_setup", "(Ljava/lang/Object;[B)V",
|
||||
(void *)android_media_MediaDrm_native_setup },
|
||||
|
||||
{ "native_finalize", "()V",
|
||||
(void *)android_media_MediaDrm_native_finalize },
|
||||
|
||||
{ "isCryptoSchemeSupportedNative", "([B)Z",
|
||||
(void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
|
||||
|
||||
{ "openSession", "()[B",
|
||||
(void *)android_media_MediaDrm_openSession },
|
||||
|
||||
{ "closeSession", "([B)V",
|
||||
(void *)android_media_MediaDrm_closeSession },
|
||||
|
||||
{ "getLicenseRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
|
||||
"Landroid/media/MediaDrm$LicenseRequest;",
|
||||
(void *)android_media_MediaDrm_getLicenseRequest },
|
||||
|
||||
{ "provideLicenseResponse", "([B[B)V",
|
||||
(void *)android_media_MediaDrm_provideLicenseResponse },
|
||||
|
||||
{ "removeLicense", "([B)V",
|
||||
(void *)android_media_MediaDrm_removeLicense },
|
||||
|
||||
{ "queryLicenseStatus", "([B)Ljava/util/HashMap;",
|
||||
(void *)android_media_MediaDrm_queryLicenseStatus },
|
||||
|
||||
{ "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
|
||||
(void *)android_media_MediaDrm_getProvisionRequest },
|
||||
|
||||
{ "provideProvisionResponse", "([B)V",
|
||||
(void *)android_media_MediaDrm_provideProvisionResponse },
|
||||
|
||||
{ "getSecureStops", "()Ljava/util/List;",
|
||||
(void *)android_media_MediaDrm_getSecureStops },
|
||||
|
||||
{ "releaseSecureStops", "([B)V",
|
||||
(void *)android_media_MediaDrm_releaseSecureStops },
|
||||
|
||||
{ "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
|
||||
(void *)android_media_MediaDrm_getPropertyString },
|
||||
|
||||
{ "getPropertyByteArray", "(Ljava/lang/String;)[B",
|
||||
(void *)android_media_MediaDrm_getPropertyByteArray },
|
||||
|
||||
{ "setPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",
|
||||
(void *)android_media_MediaDrm_setPropertyString },
|
||||
|
||||
{ "setPropertyByteArray", "(Ljava/lang/String;[B)V",
|
||||
(void *)android_media_MediaDrm_setPropertyByteArray },
|
||||
};
|
||||
|
||||
int register_android_media_Drm(JNIEnv *env) {
|
||||
return AndroidRuntime::registerNativeMethods(env,
|
||||
"android/media/MediaDrm", gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
54
media/jni/android_media_MediaDrm.h
Normal file
54
media/jni/android_media_MediaDrm.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2013, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_MEDIA_DRM_H_
|
||||
#define _ANDROID_MEDIA_DRM_H_
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include <media/stagefright/foundation/ABase.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
struct IDrm;
|
||||
|
||||
struct JDrm : public RefBase {
|
||||
static bool IsCryptoSchemeSupported(const uint8_t uuid[16]);
|
||||
|
||||
JDrm(JNIEnv *env, jobject thiz, const uint8_t uuid[16]);
|
||||
|
||||
status_t initCheck() const;
|
||||
|
||||
sp<IDrm> getDrm() { return mDrm; }
|
||||
|
||||
protected:
|
||||
virtual ~JDrm();
|
||||
|
||||
private:
|
||||
jweak mObject;
|
||||
sp<IDrm> mDrm;
|
||||
|
||||
static sp<IDrm> MakeDrm();
|
||||
static sp<IDrm> MakeDrm(const uint8_t uuid[16]);
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(JDrm);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // _ANDROID_MEDIA_DRM_H_
|
||||
@@ -879,6 +879,7 @@ static int register_android_media_MediaPlayer(JNIEnv *env)
|
||||
}
|
||||
|
||||
extern int register_android_media_Crypto(JNIEnv *env);
|
||||
extern int register_android_media_Drm(JNIEnv *env);
|
||||
extern int register_android_media_MediaCodec(JNIEnv *env);
|
||||
extern int register_android_media_MediaExtractor(JNIEnv *env);
|
||||
extern int register_android_media_MediaCodecList(JNIEnv *env);
|
||||
@@ -979,6 +980,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (register_android_media_Drm(env) < 0) {
|
||||
ALOGE("ERROR: MediaDrm native registration failed");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* success -- return valid version number */
|
||||
result = JNI_VERSION_1_4;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user