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