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