/* * 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 "MediaHTTPConnection-JNI" #include #include #include #include #include "android_media_MediaHTTPConnection.h" #include "android_util_Binder.h" #include "android_runtime/AndroidRuntime.h" #include "jni.h" #include "JNIHelp.h" namespace android { JMediaHTTPConnection::JMediaHTTPConnection(JNIEnv *env, jobject thiz) : mClass(NULL), mObject(NULL), mByteArrayObj(NULL) { jclass clazz = env->GetObjectClass(thiz); CHECK(clazz != NULL); mClass = (jclass)env->NewGlobalRef(clazz); mObject = env->NewWeakGlobalRef(thiz); mDealer = new MemoryDealer(kBufferSize, "MediaHTTPConnection"); mMemory = mDealer->allocate(kBufferSize); ScopedLocalRef tmp( env, env->NewByteArray(JMediaHTTPConnection::kBufferSize)); mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get()); } JMediaHTTPConnection::~JMediaHTTPConnection() { JNIEnv *env = AndroidRuntime::getJNIEnv(); env->DeleteGlobalRef(mByteArrayObj); mByteArrayObj = NULL; env->DeleteWeakGlobalRef(mObject); mObject = NULL; env->DeleteGlobalRef(mClass); mClass = NULL; } sp JMediaHTTPConnection::getIMemory() { return mMemory; } jbyteArray JMediaHTTPConnection::getByteArrayObj() { return mByteArrayObj; } } // namespace android using namespace android; struct fields_t { jfieldID context; jmethodID readAtMethodID; }; static fields_t gFields; static sp setObject( JNIEnv *env, jobject thiz, const sp &conn) { sp old = (JMediaHTTPConnection *)env->GetLongField(thiz, gFields.context); if (conn != NULL) { conn->incStrong(thiz); } if (old != NULL) { old->decStrong(thiz); } env->SetLongField(thiz, gFields.context, (jlong)conn.get()); return old; } static sp getObject(JNIEnv *env, jobject thiz) { return (JMediaHTTPConnection *)env->GetLongField(thiz, gFields.context); } static void android_media_MediaHTTPConnection_native_init(JNIEnv *env) { ScopedLocalRef clazz( env, env->FindClass("android/media/MediaHTTPConnection")); CHECK(clazz.get() != NULL); gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J"); CHECK(gFields.context != NULL); gFields.readAtMethodID = env->GetMethodID(clazz.get(), "readAt", "(J[BI)I"); } static void android_media_MediaHTTPConnection_native_setup( JNIEnv *env, jobject thiz) { sp conn = new JMediaHTTPConnection(env, thiz); setObject(env, thiz, conn); } static void android_media_MediaHTTPConnection_native_finalize( JNIEnv *env, jobject thiz) { setObject(env, thiz, NULL); } static jobject android_media_MediaHTTPConnection_native_getIMemory( JNIEnv *env, jobject thiz) { sp conn = getObject(env, thiz); return javaObjectForIBinder(env, IInterface::asBinder(conn->getIMemory())); } static jint android_media_MediaHTTPConnection_native_readAt( JNIEnv *env, jobject thiz, jlong offset, jint size) { sp conn = getObject(env, thiz); if (size > JMediaHTTPConnection::kBufferSize) { size = JMediaHTTPConnection::kBufferSize; } jbyteArray byteArrayObj = conn->getByteArrayObj(); jint n = env->CallIntMethod( thiz, gFields.readAtMethodID, offset, byteArrayObj, size); if (n > 0) { env->GetByteArrayRegion( byteArrayObj, 0, n, (jbyte *)conn->getIMemory()->pointer()); } return n; } static const JNINativeMethod gMethods[] = { { "native_getIMemory", "()Landroid/os/IBinder;", (void *)android_media_MediaHTTPConnection_native_getIMemory }, { "native_readAt", "(JI)I", (void *)android_media_MediaHTTPConnection_native_readAt }, { "native_init", "()V", (void *)android_media_MediaHTTPConnection_native_init }, { "native_setup", "()V", (void *)android_media_MediaHTTPConnection_native_setup }, { "native_finalize", "()V", (void *)android_media_MediaHTTPConnection_native_finalize }, }; int register_android_media_MediaHTTPConnection(JNIEnv *env) { return AndroidRuntime::registerNativeMethods(env, "android/media/MediaHTTPConnection", gMethods, NELEM(gMethods)); }