Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2008 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 #include <assert.h>
     18 #include <fcntl.h>
     19 #include <inttypes.h>
     20 #include <limits.h>
     21 #include <stdio.h>
     22 #include <unistd.h>
     23 
     24 //#define LOG_NDEBUG 0
     25 #define LOG_TAG "MediaRecorderJNI"
     26 #include <utils/Log.h>
     27 
     28 #include <gui/Surface.h>
     29 #include <camera/Camera.h>
     30 #include <media/mediarecorder.h>
     31 #include <media/MediaAnalyticsItem.h>
     32 #include <media/stagefright/PersistentSurface.h>
     33 #include <utils/threads.h>
     34 
     35 #include <ScopedUtfChars.h>
     36 
     37 #include "jni.h"
     38 #include "JNIHelp.h"
     39 #include "android_media_MediaMetricsJNI.h"
     40 #include "android_runtime/AndroidRuntime.h"
     41 
     42 #include <system/audio.h>
     43 #include <android_runtime/android_view_Surface.h>
     44 
     45 // ----------------------------------------------------------------------------
     46 
     47 using namespace android;
     48 
     49 // ----------------------------------------------------------------------------
     50 
     51 // helper function to extract a native Camera object from a Camera Java object
     52 extern sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, struct JNICameraContext** context);
     53 extern sp<PersistentSurface>
     54 android_media_MediaCodec_getPersistentInputSurface(JNIEnv* env, jobject object);
     55 
     56 struct fields_t {
     57     jfieldID    context;
     58     jfieldID    surface;
     59 
     60     jmethodID   post_event;
     61 };
     62 static fields_t fields;
     63 
     64 static Mutex sLock;
     65 
     66 // ----------------------------------------------------------------------------
     67 // ref-counted object for callbacks
     68 class JNIMediaRecorderListener: public MediaRecorderListener
     69 {
     70 public:
     71     JNIMediaRecorderListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
     72     ~JNIMediaRecorderListener();
     73     void notify(int msg, int ext1, int ext2);
     74 private:
     75     JNIMediaRecorderListener();
     76     jclass      mClass;     // Reference to MediaRecorder class
     77     jobject     mObject;    // Weak ref to MediaRecorder Java object to call on
     78 };
     79 
     80 JNIMediaRecorderListener::JNIMediaRecorderListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
     81 {
     82 
     83     // Hold onto the MediaRecorder class for use in calling the static method
     84     // that posts events to the application thread.
     85     jclass clazz = env->GetObjectClass(thiz);
     86     if (clazz == NULL) {
     87         ALOGE("Can't find android/media/MediaRecorder");
     88         jniThrowException(env, "java/lang/Exception", NULL);
     89         return;
     90     }
     91     mClass = (jclass)env->NewGlobalRef(clazz);
     92 
     93     // We use a weak reference so the MediaRecorder object can be garbage collected.
     94     // The reference is only used as a proxy for callbacks.
     95     mObject  = env->NewGlobalRef(weak_thiz);
     96 }
     97 
     98 JNIMediaRecorderListener::~JNIMediaRecorderListener()
     99 {
    100     // remove global references
    101     JNIEnv *env = AndroidRuntime::getJNIEnv();
    102     env->DeleteGlobalRef(mObject);
    103     env->DeleteGlobalRef(mClass);
    104 }
    105 
    106 void JNIMediaRecorderListener::notify(int msg, int ext1, int ext2)
    107 {
    108     ALOGV("JNIMediaRecorderListener::notify");
    109 
    110     JNIEnv *env = AndroidRuntime::getJNIEnv();
    111     env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, NULL);
    112 }
    113 
    114 // ----------------------------------------------------------------------------
    115 
    116 static sp<Surface> get_surface(JNIEnv* env, jobject clazz)
    117 {
    118     ALOGV("get_surface");
    119     return android_view_Surface_getSurface(env, clazz);
    120 }
    121 
    122 static sp<PersistentSurface> get_persistentSurface(JNIEnv* env, jobject object)
    123 {
    124     ALOGV("get_persistentSurface");
    125     return android_media_MediaCodec_getPersistentInputSurface(env, object);
    126 }
    127 
    128 // Returns true if it throws an exception.
    129 static bool process_media_recorder_call(JNIEnv *env, status_t opStatus, const char* exception, const char* message)
    130 {
    131     ALOGV("process_media_recorder_call");
    132     if (opStatus == (status_t)INVALID_OPERATION) {
    133         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    134         return true;
    135     } else if (opStatus != (status_t)OK) {
    136         jniThrowException(env, exception, message);
    137         return true;
    138     }
    139     return false;
    140 }
    141 
    142 static sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz)
    143 {
    144     Mutex::Autolock l(sLock);
    145     MediaRecorder* const p = (MediaRecorder*)env->GetLongField(thiz, fields.context);
    146     return sp<MediaRecorder>(p);
    147 }
    148 
    149 static sp<MediaRecorder> setMediaRecorder(JNIEnv* env, jobject thiz, const sp<MediaRecorder>& recorder)
    150 {
    151     Mutex::Autolock l(sLock);
    152     sp<MediaRecorder> old = (MediaRecorder*)env->GetLongField(thiz, fields.context);
    153     if (recorder.get()) {
    154         recorder->incStrong(thiz);
    155     }
    156     if (old != 0) {
    157         old->decStrong(thiz);
    158     }
    159     env->SetLongField(thiz, fields.context, (jlong)recorder.get());
    160     return old;
    161 }
    162 
    163 
    164 static void android_media_MediaRecorder_setCamera(JNIEnv* env, jobject thiz, jobject camera)
    165 {
    166     // we should not pass a null camera to get_native_camera() call.
    167     if (camera == NULL) {
    168         jniThrowNullPointerException(env, "camera object is a NULL pointer");
    169         return;
    170     }
    171     sp<Camera> c = get_native_camera(env, camera, NULL);
    172     if (c == NULL) {
    173         // get_native_camera will throw an exception in this case
    174         return;
    175     }
    176     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    177     if (mr == NULL) {
    178         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    179         return;
    180     }
    181     process_media_recorder_call(env, mr->setCamera(c->remote(), c->getRecordingProxy()),
    182             "java/lang/RuntimeException", "setCamera failed.");
    183 }
    184 
    185 static void
    186 android_media_MediaRecorder_setVideoSource(JNIEnv *env, jobject thiz, jint vs)
    187 {
    188     ALOGV("setVideoSource(%d)", vs);
    189     if (vs < VIDEO_SOURCE_DEFAULT || vs >= VIDEO_SOURCE_LIST_END) {
    190         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video source");
    191         return;
    192     }
    193     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    194     if (mr == NULL) {
    195         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    196         return;
    197     }
    198     process_media_recorder_call(env, mr->setVideoSource(vs), "java/lang/RuntimeException", "setVideoSource failed.");
    199 }
    200 
    201 static void
    202 android_media_MediaRecorder_setAudioSource(JNIEnv *env, jobject thiz, jint as)
    203 {
    204     ALOGV("setAudioSource(%d)", as);
    205     if (as < AUDIO_SOURCE_DEFAULT ||
    206         (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
    207         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid audio source");
    208         return;
    209     }
    210 
    211     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    212     if (mr == NULL) {
    213         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    214         return;
    215     }
    216     process_media_recorder_call(env, mr->setAudioSource(as), "java/lang/RuntimeException", "setAudioSource failed.");
    217 }
    218 
    219 static void
    220 android_media_MediaRecorder_setOutputFormat(JNIEnv *env, jobject thiz, jint of)
    221 {
    222     ALOGV("setOutputFormat(%d)", of);
    223     if (of < OUTPUT_FORMAT_DEFAULT || of >= OUTPUT_FORMAT_LIST_END) {
    224         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid output format");
    225         return;
    226     }
    227     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    228     if (mr == NULL) {
    229         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    230         return;
    231     }
    232     process_media_recorder_call(env, mr->setOutputFormat(of), "java/lang/RuntimeException", "setOutputFormat failed.");
    233 }
    234 
    235 static void
    236 android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve)
    237 {
    238     ALOGV("setVideoEncoder(%d)", ve);
    239     if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) {
    240         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video encoder");
    241         return;
    242     }
    243     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    244     if (mr == NULL) {
    245         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    246         return;
    247     }
    248     process_media_recorder_call(env, mr->setVideoEncoder(ve), "java/lang/RuntimeException", "setVideoEncoder failed.");
    249 }
    250 
    251 static void
    252 android_media_MediaRecorder_setAudioEncoder(JNIEnv *env, jobject thiz, jint ae)
    253 {
    254     ALOGV("setAudioEncoder(%d)", ae);
    255     if (ae < AUDIO_ENCODER_DEFAULT || ae >= AUDIO_ENCODER_LIST_END) {
    256         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid audio encoder");
    257         return;
    258     }
    259     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    260     if (mr == NULL) {
    261         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    262         return;
    263     }
    264     process_media_recorder_call(env, mr->setAudioEncoder(ae), "java/lang/RuntimeException", "setAudioEncoder failed.");
    265 }
    266 
    267 static void
    268 android_media_MediaRecorder_setParameter(JNIEnv *env, jobject thiz, jstring params)
    269 {
    270     ALOGV("setParameter()");
    271     if (params == NULL)
    272     {
    273         ALOGE("Invalid or empty params string.  This parameter will be ignored.");
    274         return;
    275     }
    276 
    277     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    278     if (mr == NULL) {
    279         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    280         return;
    281     }
    282 
    283     const char* params8 = env->GetStringUTFChars(params, NULL);
    284     if (params8 == NULL)
    285     {
    286         ALOGE("Failed to covert jstring to String8.  This parameter will be ignored.");
    287         return;
    288     }
    289 
    290     process_media_recorder_call(env, mr->setParameters(String8(params8)), "java/lang/RuntimeException", "setParameter failed.");
    291     env->ReleaseStringUTFChars(params,params8);
    292 }
    293 
    294 static void
    295 android_media_MediaRecorder_setOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor)
    296 {
    297     ALOGV("setOutputFile");
    298     if (fileDescriptor == NULL) {
    299         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    300         return;
    301     }
    302     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    303     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    304     if (mr == NULL) {
    305         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    306         return;
    307     }
    308     status_t opStatus = mr->setOutputFile(fd);
    309     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
    310 }
    311 
    312 static void
    313 android_media_MediaRecorder_setNextOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor)
    314 {
    315     ALOGV("setNextOutputFile");
    316     if (fileDescriptor == NULL) {
    317         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    318         return;
    319     }
    320     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    321     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    322     if (mr == NULL) {
    323         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    324         return;
    325     }
    326     status_t opStatus = mr->setNextOutputFile(fd);
    327     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
    328 }
    329 
    330 static void
    331 android_media_MediaRecorder_setVideoSize(JNIEnv *env, jobject thiz, jint width, jint height)
    332 {
    333     ALOGV("setVideoSize(%d, %d)", width, height);
    334     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    335     if (mr == NULL) {
    336         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    337         return;
    338     }
    339 
    340     if (width <= 0 || height <= 0) {
    341         jniThrowException(env, "java/lang/IllegalArgumentException", "invalid video size");
    342         return;
    343     }
    344     process_media_recorder_call(env, mr->setVideoSize(width, height), "java/lang/RuntimeException", "setVideoSize failed.");
    345 }
    346 
    347 static void
    348 android_media_MediaRecorder_setVideoFrameRate(JNIEnv *env, jobject thiz, jint rate)
    349 {
    350     ALOGV("setVideoFrameRate(%d)", rate);
    351     if (rate <= 0) {
    352         jniThrowException(env, "java/lang/IllegalArgumentException", "invalid frame rate");
    353         return;
    354     }
    355     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    356     if (mr == NULL) {
    357         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    358         return;
    359     }
    360     process_media_recorder_call(env, mr->setVideoFrameRate(rate), "java/lang/RuntimeException", "setVideoFrameRate failed.");
    361 }
    362 
    363 static void
    364 android_media_MediaRecorder_setMaxDuration(JNIEnv *env, jobject thiz, jint max_duration_ms)
    365 {
    366     ALOGV("setMaxDuration(%d)", max_duration_ms);
    367     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    368     if (mr == NULL) {
    369         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    370         return;
    371     }
    372 
    373     char params[64];
    374     sprintf(params, "max-duration=%d", max_duration_ms);
    375 
    376     process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxDuration failed.");
    377 }
    378 
    379 static void
    380 android_media_MediaRecorder_setMaxFileSize(
    381         JNIEnv *env, jobject thiz, jlong max_filesize_bytes)
    382 {
    383     ALOGV("setMaxFileSize(%lld)", (long long)max_filesize_bytes);
    384     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    385     if (mr == NULL) {
    386         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    387         return;
    388     }
    389 
    390     char params[64];
    391     sprintf(params, "max-filesize=%" PRId64, max_filesize_bytes);
    392 
    393     process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxFileSize failed.");
    394 }
    395 
    396 static void
    397 android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
    398 {
    399     ALOGV("prepare");
    400     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    401     if (mr == NULL) {
    402         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    403         return;
    404     }
    405 
    406     jobject surface = env->GetObjectField(thiz, fields.surface);
    407     if (surface != NULL) {
    408         const sp<Surface> native_surface = get_surface(env, surface);
    409 
    410         // The application may misbehave and
    411         // the preview surface becomes unavailable
    412         if (native_surface.get() == 0) {
    413             ALOGE("Application lost the surface");
    414             jniThrowException(env, "java/io/IOException", "invalid preview surface");
    415             return;
    416         }
    417 
    418         ALOGI("prepare: surface=%p", native_surface.get());
    419         if (process_media_recorder_call(env, mr->setPreviewSurface(native_surface->getIGraphicBufferProducer()), "java/lang/RuntimeException", "setPreviewSurface failed.")) {
    420             return;
    421         }
    422     }
    423     process_media_recorder_call(env, mr->prepare(), "java/io/IOException", "prepare failed.");
    424 }
    425 
    426 static jint
    427 android_media_MediaRecorder_native_getMaxAmplitude(JNIEnv *env, jobject thiz)
    428 {
    429     ALOGV("getMaxAmplitude");
    430     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    431     if (mr == NULL) {
    432         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    433         return 0;
    434     }
    435     int result = 0;
    436     process_media_recorder_call(env, mr->getMaxAmplitude(&result), "java/lang/RuntimeException", "getMaxAmplitude failed.");
    437     return (jint) result;
    438 }
    439 
    440 static jobject
    441 android_media_MediaRecorder_getSurface(JNIEnv *env, jobject thiz)
    442 {
    443     ALOGV("getSurface");
    444     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    445     if (mr == NULL) {
    446         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    447         return NULL;
    448     }
    449 
    450     sp<IGraphicBufferProducer> bufferProducer = mr->querySurfaceMediaSourceFromMediaServer();
    451     if (bufferProducer == NULL) {
    452         jniThrowException(
    453                 env,
    454                 "java/lang/IllegalStateException",
    455                 "failed to get surface");
    456         return NULL;
    457     }
    458 
    459     // Wrap the IGBP in a Java-language Surface.
    460     return android_view_Surface_createFromIGraphicBufferProducer(env,
    461             bufferProducer);
    462 }
    463 
    464 static void
    465 android_media_MediaRecorder_start(JNIEnv *env, jobject thiz)
    466 {
    467     ALOGV("start");
    468     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    469     if (mr == NULL) {
    470         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    471         return;
    472     }
    473     process_media_recorder_call(env, mr->start(), "java/lang/RuntimeException", "start failed.");
    474 }
    475 
    476 static void
    477 android_media_MediaRecorder_stop(JNIEnv *env, jobject thiz)
    478 {
    479     ALOGV("stop");
    480     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    481     if (mr == NULL) {
    482         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    483         return;
    484     }
    485     process_media_recorder_call(env, mr->stop(), "java/lang/RuntimeException", "stop failed.");
    486 }
    487 
    488 static void
    489 android_media_MediaRecorder_pause(JNIEnv *env, jobject thiz)
    490 {
    491     ALOGV("pause");
    492     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    493     if (mr == NULL) {
    494         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    495         return;
    496     }
    497     process_media_recorder_call(env, mr->pause(), "java/lang/RuntimeException", "pause failed.");
    498 }
    499 
    500 static void
    501 android_media_MediaRecorder_resume(JNIEnv *env, jobject thiz)
    502 {
    503     ALOGV("resume");
    504     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    505     if (mr == NULL) {
    506         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    507         return;
    508     }
    509     process_media_recorder_call(env, mr->resume(), "java/lang/RuntimeException", "resume failed.");
    510 }
    511 
    512 static void
    513 android_media_MediaRecorder_native_reset(JNIEnv *env, jobject thiz)
    514 {
    515     ALOGV("native_reset");
    516     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    517     if (mr == NULL) {
    518         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    519         return;
    520     }
    521     process_media_recorder_call(env, mr->reset(), "java/lang/RuntimeException", "native_reset failed.");
    522 }
    523 
    524 static void
    525 android_media_MediaRecorder_release(JNIEnv *env, jobject thiz)
    526 {
    527     ALOGV("release");
    528     sp<MediaRecorder> mr = setMediaRecorder(env, thiz, 0);
    529     if (mr != NULL) {
    530         mr->setListener(NULL);
    531         mr->release();
    532     }
    533 }
    534 
    535 // This function gets some field IDs, which in turn causes class initialization.
    536 // It is called from a static block in MediaRecorder, which won't run until the
    537 // first time an instance of this class is used.
    538 static void
    539 android_media_MediaRecorder_native_init(JNIEnv *env)
    540 {
    541     jclass clazz;
    542 
    543     clazz = env->FindClass("android/media/MediaRecorder");
    544     if (clazz == NULL) {
    545         return;
    546     }
    547 
    548     fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
    549     if (fields.context == NULL) {
    550         return;
    551     }
    552 
    553     fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
    554     if (fields.surface == NULL) {
    555         return;
    556     }
    557 
    558     jclass surface = env->FindClass("android/view/Surface");
    559     if (surface == NULL) {
    560         return;
    561     }
    562 
    563     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
    564                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
    565     if (fields.post_event == NULL) {
    566         return;
    567     }
    568 }
    569 
    570 
    571 static void
    572 android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
    573                                          jstring packageName, jstring opPackageName)
    574 {
    575     ALOGV("setup");
    576 
    577     ScopedUtfChars opPackageNameStr(env, opPackageName);
    578 
    579     sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str()));
    580     if (mr == NULL) {
    581         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
    582         return;
    583     }
    584     if (mr->initCheck() != NO_ERROR) {
    585         jniThrowException(env, "java/lang/RuntimeException", "Unable to initialize media recorder");
    586         return;
    587     }
    588 
    589     // create new listener and give it to MediaRecorder
    590     sp<JNIMediaRecorderListener> listener = new JNIMediaRecorderListener(env, thiz, weak_this);
    591     mr->setListener(listener);
    592 
    593     // Convert client name jstring to String16
    594     const char16_t *rawClientName = reinterpret_cast<const char16_t*>(
    595         env->GetStringChars(packageName, NULL));
    596     jsize rawClientNameLen = env->GetStringLength(packageName);
    597     String16 clientName(rawClientName, rawClientNameLen);
    598     env->ReleaseStringChars(packageName,
    599                             reinterpret_cast<const jchar*>(rawClientName));
    600 
    601     // pass client package name for permissions tracking
    602     mr->setClientName(clientName);
    603 
    604     setMediaRecorder(env, thiz, mr);
    605 }
    606 
    607 static void
    608 android_media_MediaRecorder_native_finalize(JNIEnv *env, jobject thiz)
    609 {
    610     ALOGV("finalize");
    611     android_media_MediaRecorder_release(env, thiz);
    612 }
    613 
    614 void android_media_MediaRecorder_setInputSurface(
    615         JNIEnv* env, jobject thiz, jobject object) {
    616     ALOGV("android_media_MediaRecorder_setInputSurface");
    617 
    618     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    619     if (mr == NULL) {
    620         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    621         return;
    622     }
    623 
    624     sp<PersistentSurface> persistentSurface = get_persistentSurface(env, object);
    625 
    626     process_media_recorder_call(env, mr->setInputSurface(persistentSurface),
    627             "java/lang/IllegalArgumentException", "native_setInputSurface failed.");
    628 }
    629 
    630 static jobject
    631 android_media_MediaRecorder_native_getMetrics(JNIEnv *env, jobject thiz)
    632 {
    633     ALOGV("android_media_MediaRecorder_native_getMetrics");
    634 
    635     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    636     if (mr == NULL) {
    637         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    638         return NULL;
    639     }
    640 
    641     // get what we have for the metrics from the codec
    642     Parcel reply;
    643     status_t err = mr->getMetrics(&reply);
    644     if (err != OK) {
    645         ALOGE("getMetrics failed");
    646         return (jobject) NULL;
    647     }
    648 
    649     // build and return the Bundle
    650     MediaAnalyticsItem *item = new MediaAnalyticsItem;
    651     item->readFromParcel(reply);
    652     jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
    653 
    654     // housekeeping
    655     delete item;
    656     item = NULL;
    657     return mybundle;
    658 
    659 }
    660 // ----------------------------------------------------------------------------
    661 
    662 static const JNINativeMethod gMethods[] = {
    663     {"setCamera",            "(Landroid/hardware/Camera;)V",    (void *)android_media_MediaRecorder_setCamera},
    664     {"setVideoSource",       "(I)V",                            (void *)android_media_MediaRecorder_setVideoSource},
    665     {"setAudioSource",       "(I)V",                            (void *)android_media_MediaRecorder_setAudioSource},
    666     {"setOutputFormat",      "(I)V",                            (void *)android_media_MediaRecorder_setOutputFormat},
    667     {"setVideoEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setVideoEncoder},
    668     {"setAudioEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setAudioEncoder},
    669     {"setParameter",         "(Ljava/lang/String;)V",           (void *)android_media_MediaRecorder_setParameter},
    670     {"_setOutputFile",       "(Ljava/io/FileDescriptor;)V",     (void *)android_media_MediaRecorder_setOutputFileFD},
    671     {"_setNextOutputFile",   "(Ljava/io/FileDescriptor;)V",     (void *)android_media_MediaRecorder_setNextOutputFileFD},
    672     {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
    673     {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
    674     {"setMaxDuration",       "(I)V",                            (void *)android_media_MediaRecorder_setMaxDuration},
    675     {"setMaxFileSize",       "(J)V",                            (void *)android_media_MediaRecorder_setMaxFileSize},
    676     {"_prepare",             "()V",                             (void *)android_media_MediaRecorder_prepare},
    677     {"getSurface",           "()Landroid/view/Surface;",        (void *)android_media_MediaRecorder_getSurface},
    678     {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
    679     {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
    680     {"stop",                 "()V",                             (void *)android_media_MediaRecorder_stop},
    681     {"pause",                "()V",                             (void *)android_media_MediaRecorder_pause},
    682     {"resume",               "()V",                             (void *)android_media_MediaRecorder_resume},
    683     {"native_reset",         "()V",                             (void *)android_media_MediaRecorder_native_reset},
    684     {"release",              "()V",                             (void *)android_media_MediaRecorder_release},
    685     {"native_init",          "()V",                             (void *)android_media_MediaRecorder_native_init},
    686     {"native_setup",         "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V",
    687                                                                 (void *)android_media_MediaRecorder_native_setup},
    688     {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
    689     {"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
    690 
    691     {"native_getMetrics",    "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics},
    692 };
    693 
    694 // This function only registers the native methods, and is called from
    695 // JNI_OnLoad in android_media_MediaPlayer.cpp
    696 int register_android_media_MediaRecorder(JNIEnv *env)
    697 {
    698     return AndroidRuntime::registerNativeMethods(env,
    699                 "android/media/MediaRecorder", gMethods, NELEM(gMethods));
    700 }
    701