• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
JNIMediaRecorderListener(JNIEnv * env,jobject thiz,jobject weak_thiz)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 
~JNIMediaRecorderListener()108 JNIMediaRecorderListener::~JNIMediaRecorderListener()
109 {
110     // remove global references
111     JNIEnv *env = AndroidRuntime::getJNIEnv();
112     env->DeleteGlobalRef(mObject);
113     env->DeleteGlobalRef(mClass);
114 }
115 
notify(int msg,int ext1,int ext2)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 
get_surface(JNIEnv * env,jobject clazz)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 
get_persistentSurface(JNIEnv * env,jobject object)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.
process_media_recorder_call(JNIEnv * env,status_t opStatus,const char * exception,const char * message)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 
getMediaRecorder(JNIEnv * env,jobject thiz)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 
setMediaRecorder(JNIEnv * env,jobject thiz,const sp<MediaRecorder> & recorder)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 
android_media_MediaRecorder_setCamera(JNIEnv * env,jobject thiz,jobject camera)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
android_media_MediaRecorder_setVideoSource(JNIEnv * env,jobject thiz,jint vs)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
android_media_MediaRecorder_setAudioSource(JNIEnv * env,jobject thiz,jint as)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
android_media_MediaRecorder_setOutputFormat(JNIEnv * env,jobject thiz,jint of)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
android_media_MediaRecorder_setVideoEncoder(JNIEnv * env,jobject thiz,jint ve)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
android_media_MediaRecorder_setAudioEncoder(JNIEnv * env,jobject thiz,jint ae)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
android_media_MediaRecorder_setParameter(JNIEnv * env,jobject thiz,jstring params)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
android_media_MediaRecorder_setOutputFileFD(JNIEnv * env,jobject thiz,jobject fileDescriptor)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
android_media_MediaRecorder_setNextOutputFileFD(JNIEnv * env,jobject thiz,jobject fileDescriptor)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
android_media_MediaRecorder_setVideoSize(JNIEnv * env,jobject thiz,jint width,jint height)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
android_media_MediaRecorder_setVideoFrameRate(JNIEnv * env,jobject thiz,jint rate)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
android_media_MediaRecorder_setMaxDuration(JNIEnv * env,jobject thiz,jint max_duration_ms)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
android_media_MediaRecorder_setMaxFileSize(JNIEnv * env,jobject thiz,jlong max_filesize_bytes)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
android_media_MediaRecorder_prepare(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_native_getMaxAmplitude(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_getSurface(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_start(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_stop(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_pause(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_resume(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_native_reset(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_release(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_native_init(JNIEnv * env)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
android_media_MediaRecorder_native_setup(JNIEnv * env,jobject thiz,jobject weak_this,jstring packageName,jstring opPackageName)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
android_media_MediaRecorder_native_finalize(JNIEnv * env,jobject thiz)625 android_media_MediaRecorder_native_finalize(JNIEnv *env, jobject thiz)
626 {
627     ALOGV("finalize");
628     android_media_MediaRecorder_release(env, thiz);
629 }
630 
android_media_MediaRecorder_setInputSurface(JNIEnv * env,jobject thiz,jobject object)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
android_media_MediaRecorder_native_getMetrics(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_setInputDevice(JNIEnv * env,jobject thiz,jint device_id)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
android_media_MediaRecorder_getRoutedDeviceId(JNIEnv * env,jobject thiz)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
android_media_MediaRecorder_enableDeviceCallback(JNIEnv * env,jobject thiz,jboolean enabled)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
android_media_MediaRecord_getActiveMicrophones(JNIEnv * env,jobject thiz,jobject jActiveMicrophones)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
register_android_media_MediaRecorder(JNIEnv * env)808 int register_android_media_MediaRecorder(JNIEnv *env)
809 {
810     return AndroidRuntime::registerNativeMethods(env,
811                 "android/media/MediaRecorder", gMethods, NELEM(gMethods));
812 }
813