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