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 std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create()); 668 item->readFromParcel(reply); 669 jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item.get(), NULL); 670 671 return mybundle; 672 } 673 674 static jboolean 675 android_media_MediaRecorder_setInputDevice(JNIEnv *env, jobject thiz, jint device_id) 676 { 677 ALOGV("android_media_MediaRecorder_setInputDevice"); 678 679 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 680 if (mr == NULL) { 681 jniThrowException(env, "java/lang/IllegalStateException", NULL); 682 return false; 683 } 684 685 if (process_media_recorder_call(env, mr->setInputDevice(device_id), 686 "java/lang/RuntimeException", "setInputDevice failed.")) { 687 return false; 688 } 689 return true; 690 } 691 692 static jint 693 android_media_MediaRecorder_getRoutedDeviceId(JNIEnv *env, jobject thiz) 694 { 695 ALOGV("android_media_MediaRecorder_getRoutedDeviceId"); 696 697 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 698 if (mr == NULL) { 699 jniThrowException(env, "java/lang/IllegalStateException", NULL); 700 return AUDIO_PORT_HANDLE_NONE; 701 } 702 703 audio_port_handle_t deviceId; 704 process_media_recorder_call(env, mr->getRoutedDeviceId(&deviceId), 705 "java/lang/RuntimeException", "getRoutedDeviceId failed."); 706 return (jint) deviceId; 707 } 708 709 static void 710 android_media_MediaRecorder_enableDeviceCallback(JNIEnv *env, jobject thiz, jboolean enabled) 711 { 712 ALOGV("android_media_MediaRecorder_enableDeviceCallback %d", enabled); 713 714 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 715 if (mr == NULL) { 716 jniThrowException(env, "java/lang/IllegalStateException", NULL); 717 return; 718 } 719 720 process_media_recorder_call(env, mr->enableAudioDeviceCallback(enabled), 721 "java/lang/RuntimeException", "enableDeviceCallback failed."); 722 } 723 724 static jint 725 android_media_MediaRecord_getActiveMicrophones(JNIEnv *env, 726 jobject thiz, jobject jActiveMicrophones) { 727 if (jActiveMicrophones == NULL) { 728 ALOGE("jActiveMicrophones is null"); 729 return (jint)AUDIO_JAVA_BAD_VALUE; 730 } 731 if (!env->IsInstanceOf(jActiveMicrophones, gArrayListFields.classId)) { 732 ALOGE("getActiveMicrophones not an arraylist"); 733 return (jint)AUDIO_JAVA_BAD_VALUE; 734 } 735 736 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 737 if (mr == NULL) { 738 jniThrowException(env, "java/lang/IllegalStateException", NULL); 739 return (jint)AUDIO_JAVA_NO_INIT; 740 } 741 742 jint jStatus = AUDIO_JAVA_SUCCESS; 743 std::vector<media::MicrophoneInfo> activeMicrophones; 744 status_t status = mr->getActiveMicrophones(&activeMicrophones); 745 if (status != NO_ERROR) { 746 ALOGE_IF(status != NO_ERROR, "MediaRecorder::getActiveMicrophones error %d", status); 747 jStatus = nativeToJavaStatus(status); 748 return jStatus; 749 } 750 751 for (size_t i = 0; i < activeMicrophones.size(); i++) { 752 jobject jMicrophoneInfo; 753 jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &activeMicrophones[i]); 754 if (jStatus != AUDIO_JAVA_SUCCESS) { 755 return jStatus; 756 } 757 env->CallBooleanMethod(jActiveMicrophones, gArrayListFields.add, jMicrophoneInfo); 758 env->DeleteLocalRef(jMicrophoneInfo); 759 } 760 return jStatus; 761 } 762 763 static jint android_media_MediaRecord_setPreferredMicrophoneDirection( 764 JNIEnv *env, jobject thiz, jint direction) { 765 ALOGV("setPreferredMicrophoneDirection(%d)", direction); 766 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 767 if (mr == NULL) { 768 jniThrowException(env, "java/lang/IllegalStateException", NULL); 769 return (jint)AUDIO_JAVA_NO_INIT; 770 } 771 772 jint jStatus = AUDIO_JAVA_SUCCESS; 773 status_t status = 774 mr->setPreferredMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction)); 775 if (status != NO_ERROR) { 776 jStatus = nativeToJavaStatus(status); 777 } 778 779 return jStatus; 780 } 781 782 static jint android_media_MediaRecord_setPreferredMicrophoneFieldDimension( 783 JNIEnv *env, jobject thiz, jfloat zoom) { 784 ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom); 785 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 786 if (mr == NULL) { 787 jniThrowException(env, "java/lang/IllegalStateException", NULL); 788 return (jint)AUDIO_JAVA_NO_INIT; 789 } 790 791 jint jStatus = AUDIO_JAVA_SUCCESS; 792 status_t status = mr->setPreferredMicrophoneFieldDimension(zoom); 793 if (status != NO_ERROR) { 794 jStatus = nativeToJavaStatus(status); 795 } 796 797 return jStatus; 798 799 } 800 801 static jint android_media_MediaRecord_getPortId(JNIEnv *env, jobject thiz) { 802 sp<MediaRecorder> mr = getMediaRecorder(env, thiz); 803 if (mr == NULL) { 804 jniThrowException(env, "java/lang/IllegalStateException", NULL); 805 return (jint)AUDIO_PORT_HANDLE_NONE; 806 } 807 808 audio_port_handle_t portId; 809 process_media_recorder_call(env, mr->getPortId(&portId), 810 "java/lang/RuntimeException", "getPortId failed."); 811 return (jint)portId; 812 } 813 814 // ---------------------------------------------------------------------------- 815 816 static const JNINativeMethod gMethods[] = { 817 {"setCamera", "(Landroid/hardware/Camera;)V", (void *)android_media_MediaRecorder_setCamera}, 818 {"setVideoSource", "(I)V", (void *)android_media_MediaRecorder_setVideoSource}, 819 {"setAudioSource", "(I)V", (void *)android_media_MediaRecorder_setAudioSource}, 820 {"setOutputFormat", "(I)V", (void *)android_media_MediaRecorder_setOutputFormat}, 821 {"setVideoEncoder", "(I)V", (void *)android_media_MediaRecorder_setVideoEncoder}, 822 {"setAudioEncoder", "(I)V", (void *)android_media_MediaRecorder_setAudioEncoder}, 823 {"setParameter", "(Ljava/lang/String;)V", (void *)android_media_MediaRecorder_setParameter}, 824 {"_setOutputFile", "(Ljava/io/FileDescriptor;)V", (void *)android_media_MediaRecorder_setOutputFileFD}, 825 {"_setNextOutputFile", "(Ljava/io/FileDescriptor;)V", (void *)android_media_MediaRecorder_setNextOutputFileFD}, 826 {"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize}, 827 {"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate}, 828 {"setMaxDuration", "(I)V", (void *)android_media_MediaRecorder_setMaxDuration}, 829 {"setMaxFileSize", "(J)V", (void *)android_media_MediaRecorder_setMaxFileSize}, 830 {"_prepare", "()V", (void *)android_media_MediaRecorder_prepare}, 831 {"getSurface", "()Landroid/view/Surface;", (void *)android_media_MediaRecorder_getSurface}, 832 {"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude}, 833 {"start", "()V", (void *)android_media_MediaRecorder_start}, 834 {"stop", "()V", (void *)android_media_MediaRecorder_stop}, 835 {"pause", "()V", (void *)android_media_MediaRecorder_pause}, 836 {"resume", "()V", (void *)android_media_MediaRecorder_resume}, 837 {"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset}, 838 {"release", "()V", (void *)android_media_MediaRecorder_release}, 839 {"native_init", "()V", (void *)android_media_MediaRecorder_native_init}, 840 {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", 841 (void *)android_media_MediaRecorder_native_setup}, 842 {"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize}, 843 {"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface }, 844 845 {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics}, 846 847 {"native_setInputDevice", "(I)Z", (void *)android_media_MediaRecorder_setInputDevice}, 848 {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaRecorder_getRoutedDeviceId}, 849 {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaRecorder_enableDeviceCallback}, 850 851 {"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones}, 852 {"native_getPortId", "()I", (void *)android_media_MediaRecord_getPortId}, 853 {"native_setPreferredMicrophoneDirection", "(I)I", 854 (void *)android_media_MediaRecord_setPreferredMicrophoneDirection}, 855 {"native_setPreferredMicrophoneFieldDimension", "(F)I", 856 (void *)android_media_MediaRecord_setPreferredMicrophoneFieldDimension}, 857 }; 858 859 // This function only registers the native methods, and is called from 860 // JNI_OnLoad in android_media_MediaPlayer.cpp 861 int register_android_media_MediaRecorder(JNIEnv *env) 862 { 863 return AndroidRuntime::registerNativeMethods(env, 864 "android/media/MediaRecorder", gMethods, NELEM(gMethods)); 865 } 866