summaryrefslogtreecommitdiffstats
path: root/media/jni
diff options
context:
space:
mode:
Diffstat (limited to 'media/jni')
-rw-r--r--media/jni/Android.mk4
-rw-r--r--media/jni/android_media_MediaDrm.cpp126
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp76
3 files changed, 155 insertions, 51 deletions
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 63a61e2..dea971e 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -41,13 +41,13 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_amrnb_common \
LOCAL_REQUIRED_MODULES := \
- libexif_jni
+ libjhead_jni
LOCAL_STATIC_LIBRARIES := \
libstagefright_amrnbenc
LOCAL_C_INCLUDES += \
- external/jhead \
+ external/libexif/ \
external/tremor/Tremor \
frameworks/base/core/jni \
frameworks/av/media/libmedia \
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 052d97d..7c45682 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -100,6 +100,16 @@ struct KeyTypes {
jint kKeyTypeRelease;
} gKeyTypes;
+struct CertificateTypes {
+ jint kCertificateTypeNone;
+ jint kCertificateTypeX509;
+} gCertificateTypes;
+
+struct CertificateFields {
+ jfieldID wrappedPrivateKey;
+ jfieldID certificateData;
+};
+
struct fields_t {
jfieldID context;
jmethodID post_event;
@@ -110,6 +120,11 @@ struct fields_t {
SetFields set;
IteratorFields iterator;
EntryFields entry;
+ CertificateFields certificate;
+ jclass certificateClassId;
+ jclass hashmapClassId;
+ jclass arraylistClassId;
+ jclass stringClassId;
};
static fields_t gFields;
@@ -406,8 +421,7 @@ static String8 JStringToString8(JNIEnv *env, jstring const &jstr) {
*/
static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
- jclass clazz;
- FIND_CLASS(clazz, "java/lang/String");
+ jclass clazz = gFields.stringClassId;
KeyedVector<String8, String8> keyedVector;
jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
@@ -450,8 +464,7 @@ static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &
}
static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
- jclass clazz;
- FIND_CLASS(clazz, "java/util/HashMap");
+ 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());
@@ -465,8 +478,7 @@ static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8>
static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
List<Vector<uint8_t> > list) {
- jclass clazz;
- FIND_CLASS(clazz, "java/util/ArrayList");
+ jclass clazz = gFields.arraylistClassId;
jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
List<Vector<uint8_t> >::iterator iter = list.begin();
while (iter != list.end()) {
@@ -542,6 +554,11 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
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);
+
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;");
@@ -550,6 +567,11 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
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));
+
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");
@@ -571,6 +593,15 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
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));
}
static void android_media_MediaDrm_native_setup(
@@ -826,8 +857,8 @@ static jobject android_media_MediaDrm_queryKeyStatus(
return KeyedVectorToHashMap(env, infoMap);
}
-static jobject android_media_MediaDrm_getProvisionRequest(
- JNIEnv *env, jobject thiz) {
+static jobject android_media_MediaDrm_getProvisionRequestNative(
+ JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
sp<IDrm> drm = GetDrm(env, thiz);
if (drm == NULL) {
@@ -839,7 +870,17 @@ static jobject android_media_MediaDrm_getProvisionRequest(
Vector<uint8_t> request;
String8 defaultUrl;
- status_t err = drm->getProvisionRequest(request, 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;
@@ -863,27 +904,43 @@ static jobject android_media_MediaDrm_getProvisionRequest(
return provisionObj;
}
-static void android_media_MediaDrm_provideProvisionResponse(
+static jobject android_media_MediaDrm_provideProvisionResponseNative(
JNIEnv *env, jobject thiz, jbyteArray jresponse) {
sp<IDrm> drm = GetDrm(env, thiz);
if (drm == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"MediaDrm obj is null");
- return;
+ return NULL;
}
if (jresponse == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"provision response is null");
- return;
+ 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);
- status_t err = drm->provideProvisionResponse(response);
+ 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(
@@ -1209,6 +1266,38 @@ static jboolean android_media_MediaDrm_verifyNative(
}
+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 JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaDrm_release },
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
@@ -1244,11 +1333,11 @@ static JNINativeMethod gMethods[] = {
{ "queryKeyStatus", "([B)Ljava/util/HashMap;",
(void *)android_media_MediaDrm_queryKeyStatus },
- { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
- (void *)android_media_MediaDrm_getProvisionRequest },
+ { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
+ (void *)android_media_MediaDrm_getProvisionRequestNative },
- { "provideProvisionResponse", "([B)V",
- (void *)android_media_MediaDrm_provideProvisionResponse },
+ { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
+ (void *)android_media_MediaDrm_provideProvisionResponseNative },
{ "getSecureStops", "()Ljava/util/List;",
(void *)android_media_MediaDrm_getSecureStops },
@@ -1287,6 +1376,9 @@ static JNINativeMethod gMethods[] = {
{ "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 },
};
int register_android_media_Drm(JNIEnv *env) {
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 8129c0d..7df56f4 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -38,7 +38,10 @@
#include "mtp.h"
extern "C" {
-#include "jhead.h"
+#include "libexif/exif-content.h"
+#include "libexif/exif-data.h"
+#include "libexif/exif-tag.h"
+#include "libexif/exif-utils.h"
}
using namespace android;
@@ -751,6 +754,22 @@ MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
return result;
}
+static void foreachentry(ExifEntry *entry, void *user) {
+ char buf[1024];
+ ALOGI("entry %x, format %d, size %d: %s",
+ entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
+}
+
+static void foreachcontent(ExifContent *content, void *user) {
+ ALOGI("content %d", exif_content_get_ifd(content));
+ exif_content_foreach_entry(content, foreachentry, user);
+}
+
+static long getLongFromExifEntry(ExifEntry *e) {
+ ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
+ return exif_get_long(e->data, o);
+}
+
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) {
char date[20];
@@ -793,23 +812,22 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
// read EXIF data for thumbnail information
if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
- ResetJpgfile();
- // Start with an empty image information structure.
- memset(&ImageInfo, 0, sizeof(ImageInfo));
- ImageInfo.FlashUsed = -1;
- ImageInfo.MeteringMode = -1;
- ImageInfo.Whitebalance = -1;
- strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
- if (ReadJpegFile((const char*)path, READ_METADATA)) {
- Section_t* section = FindSection(M_EXIF);
- if (section) {
- info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
- info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
- info.mImagePixWidth = ImageInfo.Width;
- info.mImagePixHeight = ImageInfo.Height;
- }
+
+ ExifData *exifdata = exif_data_new_from_file(path);
+ if (exifdata) {
+ //exif_data_foreach_content(exifdata, foreachcontent, NULL);
+
+ // XXX get this from exif, or parse jpeg header instead?
+ ExifEntry *w = exif_content_get_entry(
+ exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
+ ExifEntry *h = exif_content_get_entry(
+ exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
+ info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
+ info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
+ info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
+ info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
+ exif_data_unref(exifdata);
}
- DiscardData();
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -825,22 +843,16 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
&& (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
- ResetJpgfile();
- // Start with an empty image information structure.
- memset(&ImageInfo, 0, sizeof(ImageInfo));
- ImageInfo.FlashUsed = -1;
- ImageInfo.MeteringMode = -1;
- ImageInfo.Whitebalance = -1;
- strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
- if (ReadJpegFile((const char*)path, READ_METADATA)) {
- Section_t* section = FindSection(M_EXIF);
- if (section) {
- outThumbSize = ImageInfo.ThumbnailSize;
- result = malloc(outThumbSize);
- if (result)
- memcpy(result, section->Data + ImageInfo.ThumbnailOffset + 8, outThumbSize);
+
+ ExifData *exifdata = exif_data_new_from_file(path);
+ if (exifdata) {
+ if (exifdata->data) {
+ result = malloc(exifdata->size);
+ if (result) {
+ memcpy(result, exifdata->data, exifdata->size);
+ }
}
- DiscardData();
+ exif_data_unref(exifdata);
}
}