Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2013, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "MediaHTTPConnection-JNI"
     19 #include <utils/Log.h>
     20 
     21 #include <binder/MemoryDealer.h>
     22 #include <media/stagefright/foundation/ADebug.h>
     23 #include <nativehelper/ScopedLocalRef.h>
     24 
     25 #include "android_media_MediaHTTPConnection.h"
     26 #include "android_util_Binder.h"
     27 
     28 #include "android_runtime/AndroidRuntime.h"
     29 #include "jni.h"
     30 #include <nativehelper/JNIHelp.h>
     31 
     32 namespace android {
     33 
     34 JMediaHTTPConnection::JMediaHTTPConnection(JNIEnv *env, jobject thiz)
     35     : mClass(NULL),
     36       mObject(NULL),
     37       mByteArrayObj(NULL) {
     38     jclass clazz = env->GetObjectClass(thiz);
     39     CHECK(clazz != NULL);
     40 
     41     mClass = (jclass)env->NewGlobalRef(clazz);
     42     mObject = env->NewWeakGlobalRef(thiz);
     43 
     44     mDealer = new MemoryDealer(kBufferSize, "MediaHTTPConnection");
     45     mMemory = mDealer->allocate(kBufferSize);
     46 
     47     ScopedLocalRef<jbyteArray> tmp(
     48             env, env->NewByteArray(JMediaHTTPConnection::kBufferSize));
     49 
     50     mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
     51 }
     52 
     53 JMediaHTTPConnection::~JMediaHTTPConnection() {
     54     JNIEnv *env = AndroidRuntime::getJNIEnv();
     55 
     56     env->DeleteGlobalRef(mByteArrayObj);
     57     mByteArrayObj = NULL;
     58     env->DeleteWeakGlobalRef(mObject);
     59     mObject = NULL;
     60     env->DeleteGlobalRef(mClass);
     61     mClass = NULL;
     62 }
     63 
     64 sp<IMemory> JMediaHTTPConnection::getIMemory() {
     65     return mMemory;
     66 }
     67 
     68 jbyteArray JMediaHTTPConnection::getByteArrayObj() {
     69     return mByteArrayObj;
     70 }
     71 
     72 }  // namespace android
     73 
     74 using namespace android;
     75 
     76 struct fields_t {
     77     jfieldID context;
     78 
     79     jmethodID readAtMethodID;
     80 };
     81 
     82 static fields_t gFields;
     83 
     84 static sp<JMediaHTTPConnection> setObject(
     85         JNIEnv *env, jobject thiz, const sp<JMediaHTTPConnection> &conn) {
     86     sp<JMediaHTTPConnection> old =
     87         (JMediaHTTPConnection *)env->GetLongField(thiz, gFields.context);
     88 
     89     if (conn != NULL) {
     90         conn->incStrong(thiz);
     91     }
     92     if (old != NULL) {
     93         old->decStrong(thiz);
     94     }
     95     env->SetLongField(thiz, gFields.context, (jlong)conn.get());
     96 
     97     return old;
     98 }
     99 
    100 static sp<JMediaHTTPConnection> getObject(JNIEnv *env, jobject thiz) {
    101     return (JMediaHTTPConnection *)env->GetLongField(thiz, gFields.context);
    102 }
    103 
    104 static void android_media_MediaHTTPConnection_native_init(JNIEnv *env) {
    105     ScopedLocalRef<jclass> clazz(
    106             env, env->FindClass("android/media/MediaHTTPConnection"));
    107     CHECK(clazz.get() != NULL);
    108 
    109     gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
    110     CHECK(gFields.context != NULL);
    111 
    112     gFields.readAtMethodID = env->GetMethodID(clazz.get(), "readAt", "(J[BI)I");
    113 }
    114 
    115 static void android_media_MediaHTTPConnection_native_setup(
    116         JNIEnv *env, jobject thiz) {
    117     sp<JMediaHTTPConnection> conn = new JMediaHTTPConnection(env, thiz);
    118 
    119     setObject(env, thiz, conn);
    120 }
    121 
    122 static void android_media_MediaHTTPConnection_native_finalize(
    123         JNIEnv *env, jobject thiz) {
    124     setObject(env, thiz, NULL);
    125 }
    126 
    127 static jobject android_media_MediaHTTPConnection_native_getIMemory(
    128         JNIEnv *env, jobject thiz) {
    129     sp<JMediaHTTPConnection> conn = getObject(env, thiz);
    130 
    131     return javaObjectForIBinder(env, IInterface::asBinder(conn->getIMemory()));
    132 }
    133 
    134 static jint android_media_MediaHTTPConnection_native_readAt(
    135         JNIEnv *env, jobject thiz, jlong offset, jint size) {
    136     sp<JMediaHTTPConnection> conn = getObject(env, thiz);
    137     if (size > JMediaHTTPConnection::kBufferSize) {
    138         size = JMediaHTTPConnection::kBufferSize;
    139     }
    140 
    141     jbyteArray byteArrayObj = conn->getByteArrayObj();
    142 
    143     jint n = env->CallIntMethod(
    144             thiz, gFields.readAtMethodID, offset, byteArrayObj, size);
    145 
    146     if (n > 0) {
    147         env->GetByteArrayRegion(
    148                 byteArrayObj,
    149                 0,
    150                 n,
    151                 (jbyte *)conn->getIMemory()->pointer());
    152     }
    153 
    154     return n;
    155 }
    156 
    157 static const JNINativeMethod gMethods[] = {
    158     { "native_getIMemory", "()Landroid/os/IBinder;",
    159       (void *)android_media_MediaHTTPConnection_native_getIMemory },
    160 
    161     { "native_readAt", "(JI)I",
    162       (void *)android_media_MediaHTTPConnection_native_readAt },
    163 
    164     { "native_init", "()V",
    165       (void *)android_media_MediaHTTPConnection_native_init },
    166 
    167     { "native_setup", "()V",
    168       (void *)android_media_MediaHTTPConnection_native_setup },
    169 
    170     { "native_finalize", "()V",
    171       (void *)android_media_MediaHTTPConnection_native_finalize },
    172 };
    173 
    174 int register_android_media_MediaHTTPConnection(JNIEnv *env) {
    175     return AndroidRuntime::registerNativeMethods(env,
    176                 "android/media/MediaHTTPConnection", gMethods, NELEM(gMethods));
    177 }
    178 
    179