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 "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, conn->getIMemory()->asBinder()); 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 138 if (size > JMediaHTTPConnection::kBufferSize) { 139 size = JMediaHTTPConnection::kBufferSize; 140 } 141 142 jbyteArray byteArrayObj = conn->getByteArrayObj(); 143 144 jint n = env->CallIntMethod( 145 thiz, gFields.readAtMethodID, offset, byteArrayObj, size); 146 147 if (n > 0) { 148 env->GetByteArrayRegion( 149 byteArrayObj, 150 0, 151 n, 152 (jbyte *)conn->getIMemory()->pointer()); 153 } 154 155 return n; 156 } 157 158 static JNINativeMethod gMethods[] = { 159 { "native_getIMemory", "()Landroid/os/IBinder;", 160 (void *)android_media_MediaHTTPConnection_native_getIMemory }, 161 162 { "native_readAt", "(JI)I", 163 (void *)android_media_MediaHTTPConnection_native_readAt }, 164 165 { "native_init", "()V", 166 (void *)android_media_MediaHTTPConnection_native_init }, 167 168 { "native_setup", "()V", 169 (void *)android_media_MediaHTTPConnection_native_setup }, 170 171 { "native_finalize", "()V", 172 (void *)android_media_MediaHTTPConnection_native_finalize }, 173 }; 174 175 int register_android_media_MediaHTTPConnection(JNIEnv *env) { 176 return AndroidRuntime::registerNativeMethods(env, 177 "android/media/MediaHTTPConnection", gMethods, NELEM(gMethods)); 178 } 179 180