12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045 |
- /*
- * 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_media_MediaMetricsJNI.h"
- #include "android_os_Parcel.h"
- #include "android_runtime/AndroidRuntime.h"
- #include "android_runtime/Log.h"
- #include "android_os_Parcel.h"
- #include "jni.h"
- #include <nativehelper/JNIHelp.h>
- #include <binder/IServiceManager.h>
- #include <binder/Parcel.h>
- #include <binder/PersistableBundle.h>
- #include <cutils/properties.h>
- #include <media/stagefright/foundation/ADebug.h>
- #include <media/stagefright/MediaErrors.h>
- #include <mediadrm/IDrm.h>
- #include <mediadrm/IMediaDrmService.h>
- using ::android::os::PersistableBundle;
- namespace android {
- #define FIND_CLASS(var, className) \
- var = env->FindClass(className); \
- LOG_FATAL_IF(! (var), "Unable to find class %s", className);
- #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
- #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! (var), "Unable to find method %s", fieldName);
- #define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! (var), "Unable to find field %s", fieldName);
- #define GET_STATIC_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
- var = env->GetStaticMethodID(clazz, fieldName, fieldDescriptor); \
- LOG_FATAL_IF(! (var), "Unable to find static method %s", fieldName);
- #define GET_STATIC_OBJECT_FIELD(var, clazz, fieldId) \
- var = env->GetStaticObjectField(clazz, fieldId); \
- LOG_FATAL_IF(! (var), "Unable to find static object field %p", fieldId);
- struct RequestFields {
- jfieldID data;
- jfieldID defaultUrl;
- jfieldID requestType;
- };
- 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 EventTypes {
- jint kEventProvisionRequired;
- jint kEventKeyRequired;
- jint kEventKeyExpired;
- jint kEventVendorDefined;
- jint kEventSessionReclaimed;
- } gEventTypes;
- struct EventWhat {
- jint kWhatDrmEvent;
- jint kWhatExpirationUpdate;
- jint kWhatKeyStatusChange;
- jint kWhatSessionLostState;
- } gEventWhat;
- struct KeyTypes {
- jint kKeyTypeStreaming;
- jint kKeyTypeOffline;
- jint kKeyTypeRelease;
- } gKeyTypes;
- struct KeyRequestTypes {
- jint kKeyRequestTypeInitial;
- jint kKeyRequestTypeRenewal;
- jint kKeyRequestTypeRelease;
- jint kKeyRequestTypeNone;
- jint kKeyRequestTypeUpdate;
- } gKeyRequestTypes;
- struct CertificateTypes {
- jint kCertificateTypeNone;
- jint kCertificateTypeX509;
- } gCertificateTypes;
- struct CertificateFields {
- jfieldID wrappedPrivateKey;
- jfieldID certificateData;
- };
- struct StateExceptionFields {
- jmethodID init;
- jclass classId;
- };
- struct SessionExceptionFields {
- jmethodID init;
- jclass classId;
- jfieldID errorCode;
- };
- struct SessionExceptionErrorCodes {
- jint kErrorUnknown;
- jint kResourceContention;
- } gSessionExceptionErrorCodes;
- struct HDCPLevels {
- jint kHdcpLevelUnknown;
- jint kHdcpNone;
- jint kHdcpV1;
- jint kHdcpV2;
- jint kHdcpV2_1;
- jint kHdcpV2_2;
- jint kHdcpV2_3;
- jint kHdcpNoOutput;
- } gHdcpLevels;
- struct SecurityLevels {
- jint kSecurityLevelUnknown;
- jint kSecurityLevelMax;
- jint kSecurityLevelSwSecureCrypto;
- jint kSecurityLevelSwSecureDecode;
- jint kSecurityLevelHwSecureCrypto;
- jint kSecurityLevelHwSecureDecode;
- jint kSecurityLevelHwSecureAll;
- } gSecurityLevels;
- struct OfflineLicenseState {
- jint kOfflineLicenseStateUsable;
- jint kOfflineLicenseStateReleased;
- jint kOfflineLicenseStateUnknown;
- } gOfflineLicenseStates;
- struct fields_t {
- jfieldID context;
- jmethodID post_event;
- RequestFields keyRequest;
- RequestFields provisionRequest;
- ArrayListFields arraylist;
- HashmapFields hashmap;
- SetFields set;
- IteratorFields iterator;
- EntryFields entry;
- CertificateFields certificate;
- StateExceptionFields stateException;
- SessionExceptionFields sessionException;
- jclass certificateClassId;
- jclass hashmapClassId;
- jclass arraylistClassId;
- jclass stringClassId;
- jobject bundleCreator;
- jmethodID createFromParcelId;
- jclass parcelCreatorClassId;
- };
- static fields_t gFields;
- namespace {
- // Helper function to convert a native PersistableBundle to a Java
- // PersistableBundle.
- jobject nativeToJavaPersistableBundle(JNIEnv *env, jobject thiz,
- PersistableBundle* nativeBundle) {
- if (env == NULL || thiz == NULL || nativeBundle == NULL) {
- ALOGE("Unexpected NULL parmeter");
- return NULL;
- }
- // Create a Java parcel with the native parcel data.
- // Then create a new PersistableBundle with that parcel as a parameter.
- jobject jParcel = android::createJavaParcelObject(env);
- if (jParcel == NULL) {
- ALOGE("Failed to create a Java Parcel.");
- return NULL;
- }
- android::Parcel* nativeParcel = android::parcelForJavaObject(env, jParcel);
- if (nativeParcel == NULL) {
- ALOGE("Failed to get the native Parcel.");
- return NULL;
- }
- android::status_t result = nativeBundle->writeToParcel(nativeParcel);
- nativeParcel->setDataPosition(0);
- if (result != android::OK) {
- ALOGE("Failed to write nativeBundle to Parcel: %d.", result);
- return NULL;
- }
- jobject newBundle = env->CallObjectMethod(gFields.bundleCreator,
- gFields.createFromParcelId,
- jParcel);
- if (newBundle == NULL) {
- ALOGE("Failed to create a new PersistableBundle "
- "from the createFromParcel call.");
- }
- return newBundle;
- }
- } // namespace anonymous
- // ----------------------------------------------------------------------------
- // ref-counted object for callbacks
- 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);
- private:
- JNIDrmListener();
- jclass mClass; // Reference to MediaDrm class
- jobject mObject; // Weak ref to MediaDrm Java object to call on
- };
- JNIDrmListener::JNIDrmListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
- {
- // Hold onto the MediaDrm class for use in calling the static method
- // that posts events to the application thread.
- jclass clazz = env->GetObjectClass(thiz);
- if (clazz == NULL) {
- ALOGE("Can't find android/media/MediaDrm");
- jniThrowException(env, "java/lang/Exception",
- "Can't find android/media/MediaDrm");
- return;
- }
- mClass = (jclass)env->NewGlobalRef(clazz);
- // We use a weak reference so the MediaDrm object can be garbage collected.
- // The reference is only used as a proxy for callbacks.
- mObject = env->NewGlobalRef(weak_thiz);
- }
- JNIDrmListener::~JNIDrmListener()
- {
- // remove global references
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->DeleteGlobalRef(mObject);
- env->DeleteGlobalRef(mClass);
- }
- void JNIDrmListener::notify(DrmPlugin::EventType eventType, int extra,
- const Parcel *obj)
- {
- jint jwhat;
- jint jeventType = 0;
- // translate DrmPlugin event types into their java equivalents
- switch (eventType) {
- case DrmPlugin::kDrmPluginEventProvisionRequired:
- jwhat = gEventWhat.kWhatDrmEvent;
- jeventType = gEventTypes.kEventProvisionRequired;
- break;
- case DrmPlugin::kDrmPluginEventKeyNeeded:
- jwhat = gEventWhat.kWhatDrmEvent;
- jeventType = gEventTypes.kEventKeyRequired;
- break;
- case DrmPlugin::kDrmPluginEventKeyExpired:
- jwhat = gEventWhat.kWhatDrmEvent;
- jeventType = gEventTypes.kEventKeyExpired;
- break;
- case DrmPlugin::kDrmPluginEventVendorDefined:
- jwhat = gEventWhat.kWhatDrmEvent;
- jeventType = gEventTypes.kEventVendorDefined;
- break;
- case DrmPlugin::kDrmPluginEventSessionReclaimed:
- jwhat = gEventWhat.kWhatDrmEvent;
- jeventType = gEventTypes.kEventSessionReclaimed;
- break;
- case DrmPlugin::kDrmPluginEventExpirationUpdate:
- jwhat = gEventWhat.kWhatExpirationUpdate;
- break;
- case DrmPlugin::kDrmPluginEventKeysChange:
- jwhat = gEventWhat.kWhatKeyStatusChange;
- break;
- case DrmPlugin::kDrmPluginEventSessionLostState:
- jwhat = gEventWhat.kWhatSessionLostState;
- break;
- default:
- ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
- return;
- }
- 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 (env->ExceptionCheck()) {
- ALOGW("An exception occurred while notifying an event.");
- LOGW_EX(env);
- env->ExceptionClear();
- }
- }
- static void throwStateException(JNIEnv *env, const char *msg, status_t err) {
- ALOGE("Illegal state exception: %s (%d)", msg, err);
- jobject exception = env->NewObject(gFields.stateException.classId,
- gFields.stateException.init, static_cast<int>(err),
- env->NewStringUTF(msg));
- env->Throw(static_cast<jthrowable>(exception));
- }
- static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
- ALOGE("Session exception: %s (%d)", msg, err);
- jint jErrorCode = 0;
- switch(err) {
- case ERROR_DRM_RESOURCE_CONTENTION:
- jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
- break;
- default:
- break;
- }
- jobject exception = env->NewObject(gFields.sessionException.classId,
- gFields.sessionException.init, static_cast<int>(err),
- env->NewStringUTF(msg));
- env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
- env->Throw(static_cast<jthrowable>(exception));
- }
- static bool isSessionException(status_t err) {
- return err == ERROR_DRM_RESOURCE_CONTENTION;
- }
- static bool throwExceptionAsNecessary(
- JNIEnv *env, status_t err, const char *msg = NULL) {
- const char *drmMessage = NULL;
- switch (err) {
- case ERROR_DRM_UNKNOWN:
- drmMessage = "General DRM error";
- break;
- case ERROR_DRM_NO_LICENSE:
- drmMessage = "No license";
- break;
- case ERROR_DRM_LICENSE_EXPIRED:
- drmMessage = "License expired";
- break;
- case ERROR_DRM_SESSION_NOT_OPENED:
- drmMessage = "Session not opened";
- break;
- case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
- drmMessage = "Not initialized";
- break;
- case ERROR_DRM_DECRYPT:
- drmMessage = "Decrypt error";
- break;
- case ERROR_DRM_CANNOT_HANDLE:
- drmMessage = "Invalid parameter or data format";
- break;
- case ERROR_DRM_INVALID_STATE:
- drmMessage = "Invalid state";
- break;
- default:
- break;
- }
- String8 vendorMessage;
- if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
- vendorMessage = String8::format("DRM vendor-defined error: %d", err);
- drmMessage = vendorMessage.string();
- }
- if (err == BAD_VALUE || err == ERROR_DRM_CANNOT_HANDLE) {
- jniThrowException(env, "java/lang/IllegalArgumentException", msg);
- return true;
- } else if (err == ERROR_UNSUPPORTED) {
- jniThrowException(env, "java/lang/UnsupportedOperationException", msg);
- return true;
- } else if (err == ERROR_DRM_NOT_PROVISIONED) {
- jniThrowException(env, "android/media/NotProvisionedException", msg);
- return true;
- } else if (err == ERROR_DRM_RESOURCE_BUSY) {
- jniThrowException(env, "android/media/ResourceBusyException", msg);
- return true;
- } else if (err == ERROR_DRM_DEVICE_REVOKED) {
- jniThrowException(env, "android/media/DeniedByServerException", msg);
- return true;
- } else if (err == DEAD_OBJECT) {
- jniThrowException(env, "android/media/MediaDrmResetException",
- "mediaserver died");
- return true;
- } else if (isSessionException(err)) {
- throwSessionException(env, msg, err);
- return true;
- } else if (err != OK) {
- String8 errbuf;
- if (drmMessage != NULL) {
- if (msg == NULL) {
- msg = drmMessage;
- } else {
- errbuf = String8::format("%s: %s", msg, drmMessage);
- msg = errbuf.string();
- }
- }
- throwStateException(env, msg, err);
- return true;
- }
- return false;
- }
- static sp<IDrm> GetDrm(JNIEnv *env, jobject thiz) {
- JDrm *jdrm = (JDrm *)env->GetLongField(thiz, gFields.context);
- return jdrm ? jdrm->getDrm() : NULL;
- }
- JDrm::JDrm(
- JNIEnv *env, jobject thiz, const uint8_t uuid[16],
- const String8 &appPackageName) {
- mObject = env->NewWeakGlobalRef(thiz);
- mDrm = MakeDrm(uuid, appPackageName);
- if (mDrm != NULL) {
- mDrm->setListener(this);
- }
- }
- JDrm::~JDrm() {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->DeleteWeakGlobalRef(mObject);
- mObject = NULL;
- }
- // static
- sp<IDrm> JDrm::MakeDrm() {
- sp<IServiceManager> sm = initdefaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(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], const String8 &appPackageName) {
- sp<IDrm> drm = MakeDrm();
- if (drm == NULL) {
- return NULL;
- }
- status_t err = drm->createPlugin(uuid, appPackageName);
- if (err != OK) {
- return NULL;
- }
- return drm;
- }
- status_t JDrm::setListener(const sp<DrmListener>& listener) {
- Mutex::Autolock lock(mLock);
- mListener = listener;
- return OK;
- }
- void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
- sp<DrmListener> listener;
- mLock.lock();
- listener = mListener;
- mLock.unlock();
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- listener->notify(eventType, extra, obj);
- }
- }
- void JDrm::disconnect() {
- if (mDrm != NULL) {
- mDrm->destroyPlugin();
- mDrm.clear();
- }
- }
- // static
- status_t JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
- DrmPlugin::SecurityLevel securityLevel, bool *isSupported) {
- sp<IDrm> drm = MakeDrm();
- if (drm == NULL) {
- return BAD_VALUE;
- }
- return drm->isCryptoSchemeSupported(uuid, mimeType, securityLevel, isSupported);
- }
- 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) {
- String8 result;
- const char *s = env->GetStringUTFChars(jstr, NULL);
- 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, bool* pIsOK) {
- jclass clazz = gFields.stringClassId;
- KeyedVector<String8, String8> keyedVector;
- *pIsOK = true;
- 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 (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "HashMap key is not a String");
- env->DeleteLocalRef(entry);
- *pIsOK = false;
- break;
- }
- jstring jkey = static_cast<jstring>(obj);
- obj = env->CallObjectMethod(entry, gFields.entry.getValue);
- if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "HashMap value is not a String");
- env->DeleteLocalRef(entry);
- *pIsOK = false;
- break;
- }
- 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 = gFields.hashmapClassId;
- 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 = gFields.arraylistClassId;
- 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->GetLongField(thiz, gFields.context);
- if (drm != NULL) {
- drm->incStrong(thiz);
- }
- if (old != NULL) {
- old->decStrong(thiz);
- }
- env->SetLongField(thiz, gFields.context, reinterpret_cast<jlong>(drm.get()));
- return old;
- }
- static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
- return false;
- }
- return true;
- }
- static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
- {
- if (!CheckDrm(env, drm)) {
- return false;
- }
- if (jsessionId == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
- return false;
- }
- return true;
- }
- static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
- sp<JDrm> drm = setDrm(env, thiz, NULL);
- if (drm != NULL) {
- drm->setListener(NULL);
- drm->disconnect();
- }
- }
- static void android_media_MediaDrm_native_init(JNIEnv *env) {
- jclass clazz;
- 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");
- jfieldID field;
- GET_STATIC_FIELD_ID(field, clazz, "EVENT_PROVISION_REQUIRED", "I");
- gEventTypes.kEventProvisionRequired = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_REQUIRED", "I");
- gEventTypes.kEventKeyRequired = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "EVENT_KEY_EXPIRED", "I");
- gEventTypes.kEventKeyExpired = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "EVENT_VENDOR_DEFINED", "I");
- gEventTypes.kEventVendorDefined = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "EVENT_SESSION_RECLAIMED", "I");
- gEventTypes.kEventSessionReclaimed = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "DRM_EVENT", "I");
- gEventWhat.kWhatDrmEvent = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "EXPIRATION_UPDATE", "I");
- gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
- gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
- gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
- gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
- gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
- gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
- gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
- gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
- gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
- gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
- gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
- gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
- gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
- gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I");
- gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
- gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
- gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_CRYPTO", "I");
- gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_SW_SECURE_DECODE", "I");
- gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
- gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_DECODE", "I");
- gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
- gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_USABLE", "I");
- gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_RELEASED", "I");
- gOfflineLicenseStates.kOfflineLicenseStateReleased = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
- gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
- jmethodID getMaxSecurityLevel;
- GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
- gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
- FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
- GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
- GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
- GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
- gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
- gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
- gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_NONE", "I");
- gKeyRequestTypes.kKeyRequestTypeNone = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_UPDATE", "I");
- gKeyRequestTypes.kKeyRequestTypeUpdate = env->GetStaticIntField(clazz, field);
- FIND_CLASS(clazz, "android/media/MediaDrm$ProvisionRequest");
- GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
- GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
- FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
- GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
- GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
- gFields.certificateClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
- // Metrics-related fields and classes.
- FIND_CLASS(clazz, "android/os/PersistableBundle");
- jfieldID bundleCreatorId;
- GET_STATIC_FIELD_ID(bundleCreatorId, clazz, "CREATOR",
- "Landroid/os/Parcelable$Creator;");
- jobject bundleCreator;
- GET_STATIC_OBJECT_FIELD(bundleCreator, clazz, bundleCreatorId);
- gFields.bundleCreator = static_cast<jobject>(env->NewGlobalRef(bundleCreator));
- FIND_CLASS(clazz, "android/os/Parcelable$Creator");
- GET_METHOD_ID(gFields.createFromParcelId, clazz, "createFromParcel",
- "(Landroid/os/Parcel;)Ljava/lang/Object;");
- gFields.parcelCreatorClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
- 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;");
- FIND_CLASS(clazz, "java/util/HashMap");
- gFields.hashmapClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
- FIND_CLASS(clazz, "java/lang/String");
- gFields.stringClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
- FIND_CLASS(clazz, "java/util/ArrayList");
- gFields.arraylistClassId = static_cast<jclass>(env->NewGlobalRef(clazz));
- FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
- GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
- gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
- FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
- GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
- gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
- GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
- GET_STATIC_FIELD_ID(field, clazz, "ERROR_UNKNOWN", "I");
- gSessionExceptionErrorCodes.kErrorUnknown = env->GetStaticIntField(clazz, field);
- GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
- gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
- }
- static void android_media_MediaDrm_native_setup(
- JNIEnv *env, jobject thiz,
- jobject weak_this, jbyteArray uuidObj, jstring jappPackageName) {
- if (uuidObj == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "uuid is null");
- return;
- }
- Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
- if (uuid.size() != 16) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "invalid UUID size, expected 16 bytes");
- return;
- }
- String8 packageName;
- if (jappPackageName == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "application package name cannot be null");
- return;
- }
- packageName = JStringToString8(env, jappPackageName);
- sp<JDrm> drm = new JDrm(env, thiz, uuid.array(), packageName);
- status_t err = drm->initCheck();
- if (err != OK) {
- jniThrowException(
- env,
- "android/media/UnsupportedSchemeException",
- "Failed to instantiate drm object.");
- return;
- }
- sp<JNIDrmListener> listener = new JNIDrmListener(env, thiz, weak_this);
- drm->setListener(listener);
- setDrm(env, thiz, drm);
- }
- DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) {
- DrmPlugin::SecurityLevel level;
- if (jlevel == gSecurityLevels.kSecurityLevelMax) {
- level = DrmPlugin::kSecurityLevelMax;
- } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
- level = DrmPlugin::kSecurityLevelSwSecureCrypto;
- } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
- level = DrmPlugin::kSecurityLevelSwSecureDecode;
- } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
- level = DrmPlugin::kSecurityLevelHwSecureCrypto;
- } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
- level = DrmPlugin::kSecurityLevelHwSecureDecode;
- } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
- level = DrmPlugin::kSecurityLevelHwSecureAll;
- } else {
- level = DrmPlugin::kSecurityLevelUnknown;
- }
- return level;
- }
- static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
- JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType,
- jint jSecurityLevel) {
- 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",
- "invalid UUID size, expected 16 bytes");
- return false;
- }
- String8 mimeType;
- if (jmimeType != NULL) {
- mimeType = JStringToString8(env, jmimeType);
- }
- DrmPlugin::SecurityLevel securityLevel = jintToSecurityLevel(jSecurityLevel);
- bool isSupported;
- status_t err = JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType,
- securityLevel, &isSupported);
- if (throwExceptionAsNecessary(env, err, "Failed to query crypto scheme support")) {
- return false;
- }
- return isSupported;
- }
- static jbyteArray android_media_MediaDrm_openSession(
- JNIEnv *env, jobject thiz, jint jlevel) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- Vector<uint8_t> sessionId;
- DrmPlugin::SecurityLevel level = jintToSecurityLevel(jlevel);
- if (level == DrmPlugin::kSecurityLevelUnknown) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
- return NULL;
- }
- status_t err = drm->openSession(level, 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_getKeyRequest(
- JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jinitData,
- jstring jmimeType, jint jkeyType, 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::KeyType keyType;
- if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
- keyType = DrmPlugin::kKeyType_Streaming;
- } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
- keyType = DrmPlugin::kKeyType_Offline;
- } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
- keyType = DrmPlugin::kKeyType_Release;
- } else {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "invalid keyType");
- return NULL;
- }
- KeyedVector<String8, String8> optParams;
- if (joptParams != NULL) {
- bool isOK;
- optParams = HashMapToKeyedVector(env, joptParams, &isOK);
- if (!isOK) {
- return NULL;
- }
- }
- Vector<uint8_t> request;
- String8 defaultUrl;
- DrmPlugin::KeyRequestType keyRequestType;
- status_t err = drm->getKeyRequest(sessionId, initData, mimeType,
- keyType, optParams, request, defaultUrl, &keyRequestType);
- if (throwExceptionAsNecessary(env, err, "Failed to get key request")) {
- return NULL;
- }
- // Fill out return obj
- jclass clazz;
- FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
- jobject keyObj = NULL;
- if (clazz) {
- keyObj = env->AllocObject(clazz);
- jbyteArray jrequest = VectorToJByteArray(env, request);
- env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
- jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
- env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
- switch (keyRequestType) {
- case DrmPlugin::kKeyRequestType_Initial:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeInitial);
- break;
- case DrmPlugin::kKeyRequestType_Renewal:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeRenewal);
- break;
- case DrmPlugin::kKeyRequestType_Release:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeRelease);
- break;
- case DrmPlugin::kKeyRequestType_None:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeNone);
- break;
- case DrmPlugin::kKeyRequestType_Update:
- env->SetIntField(keyObj, gFields.keyRequest.requestType,
- gKeyRequestTypes.kKeyRequestTypeUpdate);
- break;
- default:
- throwStateException(env, "DRM plugin failure: unknown key request type",
- ERROR_DRM_UNKNOWN);
- break;
- }
- }
- return keyObj;
- }
- static jbyteArray android_media_MediaDrm_provideKeyResponse(
- JNIEnv *env, jobject thiz, jbyteArray jsessionId, jbyteArray jresponse) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckSession(env, drm, jsessionId)) {
- return NULL;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- if (jresponse == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "key response is null");
- return NULL;
- }
- Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
- Vector<uint8_t> keySetId;
- status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
- if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
- return NULL;
- }
- return VectorToJByteArray(env, keySetId);
- }
- static void android_media_MediaDrm_removeKeys(
- JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return;
- }
- if (jkeysetId == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "keySetId is null");
- return;
- }
- Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
- status_t err = drm->removeKeys(keySetId);
- throwExceptionAsNecessary(env, err, "Failed to remove keys");
- }
- static void android_media_MediaDrm_restoreKeys(
- JNIEnv *env, jobject thiz, jbyteArray jsessionId,
- jbyteArray jkeysetId) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckSession(env, drm, jsessionId)) {
- return;
- }
- if (jkeysetId == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeysetId));
- status_t err = drm->restoreKeys(sessionId, keySetId);
- throwExceptionAsNecessary(env, err, "Failed to restore keys");
- }
- static jobject android_media_MediaDrm_queryKeyStatus(
- 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->queryKeyStatus(sessionId, infoMap);
- if (throwExceptionAsNecessary(env, err, "Failed to query key status")) {
- return NULL;
- }
- return KeyedVectorToHashMap(env, infoMap);
- }
- static jobject android_media_MediaDrm_getProvisionRequestNative(
- JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- Vector<uint8_t> request;
- String8 defaultUrl;
- String8 certType;
- if (jcertType == gCertificateTypes.kCertificateTypeX509) {
- certType = "X.509";
- } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
- certType = "none";
- } else {
- certType = "invalid";
- }
- String8 certAuthority = JStringToString8(env, jcertAuthority);
- status_t err = drm->getProvisionRequest(certType, certAuthority, 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 jobject android_media_MediaDrm_provideProvisionResponseNative(
- JNIEnv *env, jobject thiz, jbyteArray jresponse) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- if (jresponse == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "provision response is null");
- return NULL;
- }
- Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
- Vector<uint8_t> certificate, wrappedKey;
- status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
- // Fill out return obj
- jclass clazz = gFields.certificateClassId;
- jobject certificateObj = NULL;
- if (clazz && certificate.size() && wrappedKey.size()) {
- certificateObj = env->AllocObject(clazz);
- jbyteArray jcertificate = VectorToJByteArray(env, certificate);
- env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
- jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
- env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
- }
- throwExceptionAsNecessary(env, err, "Failed to handle provision response");
- return certificateObj;
- }
- static jobject android_media_MediaDrm_getSecureStops(
- JNIEnv *env, jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- 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 jobject android_media_MediaDrm_getSecureStopIds(
- JNIEnv *env, jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- List<Vector<uint8_t>> secureStopIds;
- status_t err = drm->getSecureStopIds(secureStopIds);
- if (throwExceptionAsNecessary(env, err, "Failed to get secure stop Ids")) {
- return NULL;
- }
- return ListOfVectorsToArrayListOfByteArray(env, secureStopIds);
- }
- static jbyteArray android_media_MediaDrm_getSecureStop(
- JNIEnv *env, jobject thiz, jbyteArray ssid) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- Vector<uint8_t> secureStop;
- status_t err = drm->getSecureStop(JByteArrayToVector(env, ssid), secureStop);
- if (throwExceptionAsNecessary(env, err, "Failed to get secure stop")) {
- return NULL;
- }
- return VectorToJByteArray(env, secureStop);
- }
- static void android_media_MediaDrm_releaseSecureStops(
- JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return;
- }
- Vector<uint8_t> ssRelease(JByteArrayToVector(env, jssRelease));
- status_t err = drm->releaseSecureStops(ssRelease);
- throwExceptionAsNecessary(env, err, "Failed to release secure stops");
- }
- static void android_media_MediaDrm_removeSecureStop(
- JNIEnv *env, jobject thiz, jbyteArray ssid) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return;
- }
- status_t err = drm->removeSecureStop(JByteArrayToVector(env, ssid));
- throwExceptionAsNecessary(env, err, "Failed to remove secure stop");
- }
- static void android_media_MediaDrm_removeAllSecureStops(
- JNIEnv *env, jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return;
- }
- status_t err = drm->removeAllSecureStops();
- throwExceptionAsNecessary(env, err, "Failed to remove all secure stops");
- }
- static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
- switch(level) {
- case DrmPlugin::kHdcpLevelUnknown:
- return gHdcpLevels.kHdcpLevelUnknown;
- case DrmPlugin::kHdcpNone:
- return gHdcpLevels.kHdcpNone;
- case DrmPlugin::kHdcpV1:
- return gHdcpLevels.kHdcpV1;
- case DrmPlugin::kHdcpV2:
- return gHdcpLevels.kHdcpV2;
- case DrmPlugin::kHdcpV2_1:
- return gHdcpLevels.kHdcpV2_1;
- case DrmPlugin::kHdcpV2_2:
- return gHdcpLevels.kHdcpV2_2;
- case DrmPlugin::kHdcpV2_3:
- return gHdcpLevels.kHdcpV2_3;
- case DrmPlugin::kHdcpNoOutput:
- return gHdcpLevels.kHdcpNoOutput;
- }
- return gHdcpLevels.kHdcpNone;
- }
- static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
- jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return gHdcpLevels.kHdcpNone;
- }
- DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
- DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
- status_t err = drm->getHdcpLevels(&connected, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
- return gHdcpLevels.kHdcpLevelUnknown;
- }
- return HdcpLevelTojint(connected);
- }
- static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
- jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return gHdcpLevels.kHdcpLevelUnknown;
- }
- DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
- DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
- status_t err = drm->getHdcpLevels(&connected, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
- return gHdcpLevels.kHdcpLevelUnknown;
- }
- return HdcpLevelTojint(max);
- }
- static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
- jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return 0;
- }
- uint32_t open = 0, max = 0;
- status_t err = drm->getNumberOfSessions(&open, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
- return 0;
- }
- return open;
- }
- static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
- jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return 0;
- }
- uint32_t open = 0, max = 0;
- status_t err = drm->getNumberOfSessions(&open, &max);
- if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
- return 0;
- }
- return max;
- }
- static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
- jobject thiz, jbyteArray jsessionId) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckSession(env, drm, jsessionId)) {
- return gSecurityLevels.kSecurityLevelUnknown;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
- status_t err = drm->getSecurityLevel(sessionId, &level);
- if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
- return gSecurityLevels.kSecurityLevelUnknown;
- }
- switch(level) {
- case DrmPlugin::kSecurityLevelSwSecureCrypto:
- return gSecurityLevels.kSecurityLevelSwSecureCrypto;
- case DrmPlugin::kSecurityLevelSwSecureDecode:
- return gSecurityLevels.kSecurityLevelSwSecureDecode;
- case DrmPlugin::kSecurityLevelHwSecureCrypto:
- return gSecurityLevels.kSecurityLevelHwSecureCrypto;
- case DrmPlugin::kSecurityLevelHwSecureDecode:
- return gSecurityLevels.kSecurityLevelHwSecureDecode;
- case DrmPlugin::kSecurityLevelHwSecureAll:
- return gSecurityLevels.kSecurityLevelHwSecureAll;
- default:
- return gSecurityLevels.kSecurityLevelUnknown;
- }
- }
- static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
- JNIEnv *env, jobject thiz) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- List<Vector<uint8_t> > keySetIds;
- status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
- if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
- return NULL;
- }
- return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
- }
- static void android_media_MediaDrm_removeOfflineLicense(
- JNIEnv *env, jobject thiz, jbyteArray keySetId) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return;
- }
- status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
- throwExceptionAsNecessary(env, err, "Failed to remove offline license");
- }
- static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
- jobject thiz, jbyteArray jkeySetId) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
- }
- Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
- DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
- status_t err = drm->getOfflineLicenseState(keySetId, &state);
- if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
- return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
- }
- switch(state) {
- case DrmPlugin::kOfflineLicenseStateUsable:
- return gOfflineLicenseStates.kOfflineLicenseStateUsable;
- case DrmPlugin::kOfflineLicenseStateReleased:
- return gOfflineLicenseStates.kOfflineLicenseStateReleased;
- default:
- return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
- }
- }
- static jstring android_media_MediaDrm_getPropertyString(
- JNIEnv *env, jobject thiz, jstring jname) {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is 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 (!CheckDrm(env, drm)) {
- return NULL;
- }
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is 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 (!CheckDrm(env, drm)) {
- return;
- }
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is null");
- return;
- }
- if (jvalue == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property value String is 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 (!CheckDrm(env, drm)) {
- return;
- }
- if (jname == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property name String is null");
- return;
- }
- if (jvalue == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "property value byte array is 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 void android_media_MediaDrm_setCipherAlgorithmNative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jstring jalgorithm) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return;
- }
- if (jalgorithm == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "algorithm String is null");
- return;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- String8 algorithm = JStringToString8(env, jalgorithm);
- status_t err = drm->setCipherAlgorithm(sessionId, algorithm);
- throwExceptionAsNecessary(env, err, "Failed to set cipher algorithm");
- }
- static void android_media_MediaDrm_setMacAlgorithmNative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jstring jalgorithm) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return;
- }
- if (jalgorithm == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "algorithm String is null");
- return;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- String8 algorithm = JStringToString8(env, jalgorithm);
- status_t err = drm->setMacAlgorithm(sessionId, algorithm);
- throwExceptionAsNecessary(env, err, "Failed to set mac algorithm");
- }
- static jbyteArray android_media_MediaDrm_encryptNative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return NULL;
- }
- if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "required argument is null");
- return NULL;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
- Vector<uint8_t> input(JByteArrayToVector(env, jinput));
- Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
- Vector<uint8_t> output;
- status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
- if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
- return NULL;
- }
- return VectorToJByteArray(env, output);
- }
- static jbyteArray android_media_MediaDrm_decryptNative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jbyteArray jkeyId, jbyteArray jinput, jbyteArray jiv) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return NULL;
- }
- if (jkeyId == NULL || jinput == NULL || jiv == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "required argument is null");
- return NULL;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
- Vector<uint8_t> input(JByteArrayToVector(env, jinput));
- Vector<uint8_t> iv(JByteArrayToVector(env, jiv));
- Vector<uint8_t> output;
- status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
- if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
- return NULL;
- }
- return VectorToJByteArray(env, output);
- }
- static jbyteArray android_media_MediaDrm_signNative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jbyteArray jkeyId, jbyteArray jmessage) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return NULL;
- }
- if (jkeyId == NULL || jmessage == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "required argument is null");
- return NULL;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
- Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
- Vector<uint8_t> signature;
- status_t err = drm->sign(sessionId, keyId, message, signature);
- if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
- return NULL;
- }
- return VectorToJByteArray(env, signature);
- }
- static jboolean android_media_MediaDrm_verifyNative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jbyteArray jkeyId, jbyteArray jmessage, jbyteArray jsignature) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return false;
- }
- if (jkeyId == NULL || jmessage == NULL || jsignature == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "required argument is null");
- return false;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- Vector<uint8_t> keyId(JByteArrayToVector(env, jkeyId));
- Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
- Vector<uint8_t> signature(JByteArrayToVector(env, jsignature));
- bool match;
- status_t err = drm->verify(sessionId, keyId, message, signature, match);
- throwExceptionAsNecessary(env, err, "Failed to verify");
- return match;
- }
- static jobject
- android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
- {
- sp<IDrm> drm = GetDrm(env, thiz);
- if (!CheckDrm(env, drm)) {
- return NULL;
- }
- // Retrieve current metrics snapshot from drm.
- PersistableBundle metrics;
- status_t err = drm->getMetrics(&metrics);
- if (err != OK) {
- ALOGE("getMetrics failed: %d", (int)err);
- return (jobject) NULL;
- }
- return nativeToJavaPersistableBundle(env, thiz, &metrics);
- }
- static jbyteArray android_media_MediaDrm_signRSANative(
- JNIEnv *env, jobject /* thiz */, jobject jdrm, jbyteArray jsessionId,
- jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
- sp<IDrm> drm = GetDrm(env, jdrm);
- if (!CheckSession(env, drm, jsessionId)) {
- return NULL;
- }
- if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "required argument is null");
- return NULL;
- }
- Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
- String8 algorithm = JStringToString8(env, jalgorithm);
- Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
- Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
- Vector<uint8_t> signature;
- status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
- if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
- return NULL;
- }
- return VectorToJByteArray(env, signature);
- }
- static const JNINativeMethod gMethods[] = {
- { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
- { "native_init", "()V", (void *)android_media_MediaDrm_native_init },
- { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
- (void *)android_media_MediaDrm_native_setup },
- { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z",
- (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
- { "openSession", "(I)[B",
- (void *)android_media_MediaDrm_openSession },
- { "closeSession", "([B)V",
- (void *)android_media_MediaDrm_closeSession },
- { "getKeyRequest", "([B[BLjava/lang/String;ILjava/util/HashMap;)"
- "Landroid/media/MediaDrm$KeyRequest;",
- (void *)android_media_MediaDrm_getKeyRequest },
- { "provideKeyResponse", "([B[B)[B",
- (void *)android_media_MediaDrm_provideKeyResponse },
- { "removeKeys", "([B)V",
- (void *)android_media_MediaDrm_removeKeys },
- { "restoreKeys", "([B[B)V",
- (void *)android_media_MediaDrm_restoreKeys },
- { "queryKeyStatus", "([B)Ljava/util/HashMap;",
- (void *)android_media_MediaDrm_queryKeyStatus },
- { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
- (void *)android_media_MediaDrm_getProvisionRequestNative },
- { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
- (void *)android_media_MediaDrm_provideProvisionResponseNative },
- { "getSecureStops", "()Ljava/util/List;",
- (void *)android_media_MediaDrm_getSecureStops },
- { "getSecureStopIds", "()Ljava/util/List;",
- (void *)android_media_MediaDrm_getSecureStopIds },
- { "getSecureStop", "([B)[B",
- (void *)android_media_MediaDrm_getSecureStop },
- { "releaseSecureStops", "([B)V",
- (void *)android_media_MediaDrm_releaseSecureStops },
- { "removeSecureStop", "([B)V",
- (void *)android_media_MediaDrm_removeSecureStop },
- { "removeAllSecureStops", "()V",
- (void *)android_media_MediaDrm_removeAllSecureStops },
- { "getConnectedHdcpLevel", "()I",
- (void *)android_media_MediaDrm_getConnectedHdcpLevel },
- { "getMaxHdcpLevel", "()I",
- (void *)android_media_MediaDrm_getMaxHdcpLevel },
- { "getOpenSessionCount", "()I",
- (void *)android_media_MediaDrm_getOpenSessionCount },
- { "getMaxSessionCount", "()I",
- (void *)android_media_MediaDrm_getMaxSessionCount },
- { "getSecurityLevel", "([B)I",
- (void *)android_media_MediaDrm_getSecurityLevel },
- { "removeOfflineLicense", "([B)V",
- (void *)android_media_MediaDrm_removeOfflineLicense },
- { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
- (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
- { "getOfflineLicenseState", "([B)I",
- (void *)android_media_MediaDrm_getOfflineLicenseState },
- { "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 },
- { "setCipherAlgorithmNative",
- "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
- (void *)android_media_MediaDrm_setCipherAlgorithmNative },
- { "setMacAlgorithmNative",
- "(Landroid/media/MediaDrm;[BLjava/lang/String;)V",
- (void *)android_media_MediaDrm_setMacAlgorithmNative },
- { "encryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
- (void *)android_media_MediaDrm_encryptNative },
- { "decryptNative", "(Landroid/media/MediaDrm;[B[B[B[B)[B",
- (void *)android_media_MediaDrm_decryptNative },
- { "signNative", "(Landroid/media/MediaDrm;[B[B[B)[B",
- (void *)android_media_MediaDrm_signNative },
- { "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
- (void *)android_media_MediaDrm_verifyNative },
- { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
- (void *)android_media_MediaDrm_signRSANative },
- { "getMetricsNative", "()Landroid/os/PersistableBundle;",
- (void *)android_media_MediaDrm_native_getMetrics },
- };
- int register_android_media_Drm(JNIEnv *env) {
- return AndroidRuntime::registerNativeMethods(env,
- "android/media/MediaDrm", gMethods, NELEM(gMethods));
- }
|