1 /* 2 ** 3 ** Copyright 2007, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 //#define LOG_NDEBUG 0 19 #define LOG_TAG "MediaPlayer-JNI" 20 #include "utils/Log.h" 21 22 #include <media/mediaplayer.h> 23 #include <media/AudioResamplerPublic.h> 24 #include <media/IMediaHTTPService.h> 25 #include <media/MediaPlayerInterface.h> 26 #include <stdio.h> 27 #include <assert.h> 28 #include <limits.h> 29 #include <unistd.h> 30 #include <fcntl.h> 31 #include <utils/threads.h> 32 #include "jni.h" 33 #include "JNIHelp.h" 34 #include "android_runtime/AndroidRuntime.h" 35 #include "android_runtime/android_view_Surface.h" 36 #include "android_runtime/Log.h" 37 #include "utils/Errors.h" // for status_t 38 #include "utils/KeyedVector.h" 39 #include "utils/String8.h" 40 #include "android_media_MediaDataSource.h" 41 #include "android_media_PlaybackParams.h" 42 #include "android_media_SyncParams.h" 43 #include "android_media_Utils.h" 44 45 #include "android_os_Parcel.h" 46 #include "android_util_Binder.h" 47 #include <binder/Parcel.h> 48 #include <gui/IGraphicBufferProducer.h> 49 #include <gui/Surface.h> 50 #include <binder/IPCThreadState.h> 51 #include <binder/IServiceManager.h> 52 53 #include "android_util_Binder.h" 54 // ---------------------------------------------------------------------------- 55 56 using namespace android; 57 58 // ---------------------------------------------------------------------------- 59 60 struct fields_t { 61 jfieldID context; 62 jfieldID surface_texture; 63 64 jmethodID post_event; 65 66 jmethodID proxyConfigGetHost; 67 jmethodID proxyConfigGetPort; 68 jmethodID proxyConfigGetExclusionList; 69 }; 70 static fields_t fields; 71 72 static PlaybackParams::fields_t gPlaybackParamsFields; 73 static SyncParams::fields_t gSyncParamsFields; 74 75 static Mutex sLock; 76 77 // ---------------------------------------------------------------------------- 78 // ref-counted object for callbacks 79 class JNIMediaPlayerListener: public MediaPlayerListener 80 { 81 public: 82 JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz); 83 ~JNIMediaPlayerListener(); 84 virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL); 85 private: 86 JNIMediaPlayerListener(); 87 jclass mClass; // Reference to MediaPlayer class 88 jobject mObject; // Weak ref to MediaPlayer Java object to call on 89 }; 90 91 JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz) 92 { 93 94 // Hold onto the MediaPlayer class for use in calling the static method 95 // that posts events to the application thread. 96 jclass clazz = env->GetObjectClass(thiz); 97 if (clazz == NULL) { 98 ALOGE("Can't find android/media/MediaPlayer"); 99 jniThrowException(env, "java/lang/Exception", NULL); 100 return; 101 } 102 mClass = (jclass)env->NewGlobalRef(clazz); 103 104 // We use a weak reference so the MediaPlayer object can be garbage collected. 105 // The reference is only used as a proxy for callbacks. 106 mObject = env->NewGlobalRef(weak_thiz); 107 } 108 109 JNIMediaPlayerListener::~JNIMediaPlayerListener() 110 { 111 // remove global references 112 JNIEnv *env = AndroidRuntime::getJNIEnv(); 113 env->DeleteGlobalRef(mObject); 114 env->DeleteGlobalRef(mClass); 115 } 116 117 void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj) 118 { 119 JNIEnv *env = AndroidRuntime::getJNIEnv(); 120 if (obj && obj->dataSize() > 0) { 121 jobject jParcel = createJavaParcelObject(env); 122 if (jParcel != NULL) { 123 Parcel* nativeParcel = parcelForJavaObject(env, jParcel); 124 nativeParcel->setData(obj->data(), obj->dataSize()); 125 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, 126 msg, ext1, ext2, jParcel); 127 env->DeleteLocalRef(jParcel); 128 } 129 } else { 130 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, 131 msg, ext1, ext2, NULL); 132 } 133 if (env->ExceptionCheck()) { 134 ALOGW("An exception occurred while notifying an event."); 135 LOGW_EX(env); 136 env->ExceptionClear(); 137 } 138 } 139 140 // ---------------------------------------------------------------------------- 141 142 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) 143 { 144 Mutex::Autolock l(sLock); 145 MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context); 146 return sp<MediaPlayer>(p); 147 } 148 149 static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player) 150 { 151 Mutex::Autolock l(sLock); 152 sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context); 153 if (player.get()) { 154 player->incStrong((void*)setMediaPlayer); 155 } 156 if (old != 0) { 157 old->decStrong((void*)setMediaPlayer); 158 } 159 env->SetLongField(thiz, fields.context, (jlong)player.get()); 160 return old; 161 } 162 163 // If exception is NULL and opStatus is not OK, this method sends an error 164 // event to the client application; otherwise, if exception is not NULL and 165 // opStatus is not OK, this method throws the given exception to the client 166 // application. 167 static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message) 168 { 169 if (exception == NULL) { // Don't throw exception. Instead, send an event. 170 if (opStatus != (status_t) OK) { 171 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 172 if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0); 173 } 174 } else { // Throw exception! 175 if ( opStatus == (status_t) INVALID_OPERATION ) { 176 jniThrowException(env, "java/lang/IllegalStateException", NULL); 177 } else if ( opStatus == (status_t) BAD_VALUE ) { 178 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 179 } else if ( opStatus == (status_t) PERMISSION_DENIED ) { 180 jniThrowException(env, "java/lang/SecurityException", NULL); 181 } else if ( opStatus != (status_t) OK ) { 182 if (strlen(message) > 230) { 183 // if the message is too long, don't bother displaying the status code 184 jniThrowException( env, exception, message); 185 } else { 186 char msg[256]; 187 // append the status code to the message 188 sprintf(msg, "%s: status=0x%X", message, opStatus); 189 jniThrowException( env, exception, msg); 190 } 191 } 192 } 193 } 194 195 static void 196 android_media_MediaPlayer_setDataSourceAndHeaders( 197 JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path, 198 jobjectArray keys, jobjectArray values) { 199 200 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 201 if (mp == NULL ) { 202 jniThrowException(env, "java/lang/IllegalStateException", NULL); 203 return; 204 } 205 206 if (path == NULL) { 207 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 208 return; 209 } 210 211 const char *tmp = env->GetStringUTFChars(path, NULL); 212 if (tmp == NULL) { // Out of memory 213 return; 214 } 215 ALOGV("setDataSource: path %s", tmp); 216 217 String8 pathStr(tmp); 218 env->ReleaseStringUTFChars(path, tmp); 219 tmp = NULL; 220 221 // We build a KeyedVector out of the key and val arrays 222 KeyedVector<String8, String8> headersVector; 223 if (!ConvertKeyValueArraysToKeyedVector( 224 env, keys, values, &headersVector)) { 225 return; 226 } 227 228 sp<IMediaHTTPService> httpService; 229 if (httpServiceBinderObj != NULL) { 230 sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj); 231 httpService = interface_cast<IMediaHTTPService>(binder); 232 } 233 234 status_t opStatus = 235 mp->setDataSource( 236 httpService, 237 pathStr, 238 headersVector.size() > 0? &headersVector : NULL); 239 240 process_media_player_call( 241 env, thiz, opStatus, "java/io/IOException", 242 "setDataSource failed." ); 243 } 244 245 static void 246 android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) 247 { 248 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 249 if (mp == NULL ) { 250 jniThrowException(env, "java/lang/IllegalStateException", NULL); 251 return; 252 } 253 254 if (fileDescriptor == NULL) { 255 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 256 return; 257 } 258 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 259 ALOGV("setDataSourceFD: fd %d", fd); 260 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); 261 } 262 263 static void 264 android_media_MediaPlayer_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource) 265 { 266 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 267 if (mp == NULL ) { 268 jniThrowException(env, "java/lang/IllegalStateException", NULL); 269 return; 270 } 271 272 if (dataSource == NULL) { 273 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 274 return; 275 } 276 sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource); 277 process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." ); 278 } 279 280 static sp<IGraphicBufferProducer> 281 getVideoSurfaceTexture(JNIEnv* env, jobject thiz) { 282 IGraphicBufferProducer * const p = (IGraphicBufferProducer*)env->GetLongField(thiz, fields.surface_texture); 283 return sp<IGraphicBufferProducer>(p); 284 } 285 286 static void 287 decVideoSurfaceRef(JNIEnv *env, jobject thiz) 288 { 289 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 290 if (mp == NULL) { 291 return; 292 } 293 294 sp<IGraphicBufferProducer> old_st = getVideoSurfaceTexture(env, thiz); 295 if (old_st != NULL) { 296 old_st->decStrong((void*)decVideoSurfaceRef); 297 } 298 } 299 300 static void 301 setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive) 302 { 303 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 304 if (mp == NULL) { 305 if (mediaPlayerMustBeAlive) { 306 jniThrowException(env, "java/lang/IllegalStateException", NULL); 307 } 308 return; 309 } 310 311 decVideoSurfaceRef(env, thiz); 312 313 sp<IGraphicBufferProducer> new_st; 314 if (jsurface) { 315 sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 316 if (surface != NULL) { 317 new_st = surface->getIGraphicBufferProducer(); 318 if (new_st == NULL) { 319 jniThrowException(env, "java/lang/IllegalArgumentException", 320 "The surface does not have a binding SurfaceTexture!"); 321 return; 322 } 323 new_st->incStrong((void*)decVideoSurfaceRef); 324 } else { 325 jniThrowException(env, "java/lang/IllegalArgumentException", 326 "The surface has been released"); 327 return; 328 } 329 } 330 331 env->SetLongField(thiz, fields.surface_texture, (jlong)new_st.get()); 332 333 // This will fail if the media player has not been initialized yet. This 334 // can be the case if setDisplay() on MediaPlayer.java has been called 335 // before setDataSource(). The redundant call to setVideoSurfaceTexture() 336 // in prepare/prepareAsync covers for this case. 337 mp->setVideoSurfaceTexture(new_st); 338 } 339 340 static void 341 android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface) 342 { 343 setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */); 344 } 345 346 static void 347 android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) 348 { 349 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 350 if (mp == NULL ) { 351 jniThrowException(env, "java/lang/IllegalStateException", NULL); 352 return; 353 } 354 355 // Handle the case where the display surface was set before the mp was 356 // initialized. We try again to make it stick. 357 sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz); 358 mp->setVideoSurfaceTexture(st); 359 360 process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." ); 361 } 362 363 static void 364 android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz) 365 { 366 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 367 if (mp == NULL ) { 368 jniThrowException(env, "java/lang/IllegalStateException", NULL); 369 return; 370 } 371 372 // Handle the case where the display surface was set before the mp was 373 // initialized. We try again to make it stick. 374 sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz); 375 mp->setVideoSurfaceTexture(st); 376 377 process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." ); 378 } 379 380 static void 381 android_media_MediaPlayer_start(JNIEnv *env, jobject thiz) 382 { 383 ALOGV("start"); 384 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 385 if (mp == NULL ) { 386 jniThrowException(env, "java/lang/IllegalStateException", NULL); 387 return; 388 } 389 process_media_player_call( env, thiz, mp->start(), NULL, NULL ); 390 } 391 392 static void 393 android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz) 394 { 395 ALOGV("stop"); 396 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 397 if (mp == NULL ) { 398 jniThrowException(env, "java/lang/IllegalStateException", NULL); 399 return; 400 } 401 process_media_player_call( env, thiz, mp->stop(), NULL, NULL ); 402 } 403 404 static void 405 android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz) 406 { 407 ALOGV("pause"); 408 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 409 if (mp == NULL ) { 410 jniThrowException(env, "java/lang/IllegalStateException", NULL); 411 return; 412 } 413 process_media_player_call( env, thiz, mp->pause(), NULL, NULL ); 414 } 415 416 static jboolean 417 android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz) 418 { 419 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 420 if (mp == NULL ) { 421 jniThrowException(env, "java/lang/IllegalStateException", NULL); 422 return JNI_FALSE; 423 } 424 const jboolean is_playing = mp->isPlaying(); 425 426 ALOGV("isPlaying: %d", is_playing); 427 return is_playing; 428 } 429 430 static void 431 android_media_MediaPlayer_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params) 432 { 433 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 434 if (mp == NULL) { 435 jniThrowException(env, "java/lang/IllegalStateException", NULL); 436 return; 437 } 438 439 PlaybackParams pbp; 440 pbp.fillFromJobject(env, gPlaybackParamsFields, params); 441 ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u", 442 pbp.speedSet, pbp.audioRate.mSpeed, 443 pbp.pitchSet, pbp.audioRate.mPitch, 444 pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode, 445 pbp.audioStretchModeSet, pbp.audioRate.mStretchMode); 446 447 AudioPlaybackRate rate; 448 status_t err = mp->getPlaybackSettings(&rate); 449 if (err == OK) { 450 bool updatedRate = false; 451 if (pbp.speedSet) { 452 rate.mSpeed = pbp.audioRate.mSpeed; 453 updatedRate = true; 454 } 455 if (pbp.pitchSet) { 456 rate.mPitch = pbp.audioRate.mPitch; 457 updatedRate = true; 458 } 459 if (pbp.audioFallbackModeSet) { 460 rate.mFallbackMode = pbp.audioRate.mFallbackMode; 461 updatedRate = true; 462 } 463 if (pbp.audioStretchModeSet) { 464 rate.mStretchMode = pbp.audioRate.mStretchMode; 465 updatedRate = true; 466 } 467 if (updatedRate) { 468 err = mp->setPlaybackSettings(rate); 469 } 470 } 471 process_media_player_call( 472 env, thiz, err, 473 "java/lang/IllegalStateException", "unexpected error"); 474 } 475 476 static jobject 477 android_media_MediaPlayer_getPlaybackParams(JNIEnv *env, jobject thiz) 478 { 479 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 480 if (mp == NULL) { 481 jniThrowException(env, "java/lang/IllegalStateException", NULL); 482 return NULL; 483 } 484 485 PlaybackParams pbp; 486 AudioPlaybackRate &audioRate = pbp.audioRate; 487 process_media_player_call( 488 env, thiz, mp->getPlaybackSettings(&audioRate), 489 "java/lang/IllegalStateException", "unexpected error"); 490 ALOGV("getPlaybackSettings: %f %f %d %d", 491 audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode); 492 493 pbp.speedSet = true; 494 pbp.pitchSet = true; 495 pbp.audioFallbackModeSet = true; 496 pbp.audioStretchModeSet = true; 497 498 return pbp.asJobject(env, gPlaybackParamsFields); 499 } 500 501 static void 502 android_media_MediaPlayer_setSyncParams(JNIEnv *env, jobject thiz, jobject params) 503 { 504 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 505 if (mp == NULL) { 506 jniThrowException(env, "java/lang/IllegalStateException", NULL); 507 return; 508 } 509 510 SyncParams scp; 511 scp.fillFromJobject(env, gSyncParamsFields, params); 512 ALOGV("setSyncParams: %d:%d %d:%d %d:%f %d:%f", 513 scp.syncSourceSet, scp.sync.mSource, 514 scp.audioAdjustModeSet, scp.sync.mAudioAdjustMode, 515 scp.toleranceSet, scp.sync.mTolerance, 516 scp.frameRateSet, scp.frameRate); 517 518 AVSyncSettings avsync; 519 float videoFrameRate; 520 status_t err = mp->getSyncSettings(&avsync, &videoFrameRate); 521 if (err == OK) { 522 bool updatedSync = scp.frameRateSet; 523 if (scp.syncSourceSet) { 524 avsync.mSource = scp.sync.mSource; 525 updatedSync = true; 526 } 527 if (scp.audioAdjustModeSet) { 528 avsync.mAudioAdjustMode = scp.sync.mAudioAdjustMode; 529 updatedSync = true; 530 } 531 if (scp.toleranceSet) { 532 avsync.mTolerance = scp.sync.mTolerance; 533 updatedSync = true; 534 } 535 if (updatedSync) { 536 err = mp->setSyncSettings(avsync, scp.frameRateSet ? scp.frameRate : -1.f); 537 } 538 } 539 process_media_player_call( 540 env, thiz, err, 541 "java/lang/IllegalStateException", "unexpected error"); 542 } 543 544 static jobject 545 android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz) 546 { 547 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 548 if (mp == NULL) { 549 jniThrowException(env, "java/lang/IllegalStateException", NULL); 550 return NULL; 551 } 552 553 SyncParams scp; 554 scp.frameRate = -1.f; 555 process_media_player_call( 556 env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate), 557 "java/lang/IllegalStateException", "unexpected error"); 558 559 ALOGV("getSyncSettings: %d %d %f %f", 560 scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate); 561 562 // sanity check params 563 if (scp.sync.mSource >= AVSYNC_SOURCE_MAX 564 || scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX 565 || scp.sync.mTolerance < 0.f 566 || scp.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) { 567 jniThrowException(env, "java/lang/IllegalStateException", NULL); 568 return NULL; 569 } 570 571 scp.syncSourceSet = true; 572 scp.audioAdjustModeSet = true; 573 scp.toleranceSet = true; 574 scp.frameRateSet = scp.frameRate >= 0.f; 575 576 return scp.asJobject(env, gSyncParamsFields); 577 } 578 579 static void 580 android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jint msec) 581 { 582 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 583 if (mp == NULL ) { 584 jniThrowException(env, "java/lang/IllegalStateException", NULL); 585 return; 586 } 587 ALOGV("seekTo: %d(msec)", msec); 588 process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL ); 589 } 590 591 static jint 592 android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz) 593 { 594 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 595 if (mp == NULL ) { 596 jniThrowException(env, "java/lang/IllegalStateException", NULL); 597 return 0; 598 } 599 int w; 600 if (0 != mp->getVideoWidth(&w)) { 601 ALOGE("getVideoWidth failed"); 602 w = 0; 603 } 604 ALOGV("getVideoWidth: %d", w); 605 return (jint) w; 606 } 607 608 static jint 609 android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz) 610 { 611 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 612 if (mp == NULL ) { 613 jniThrowException(env, "java/lang/IllegalStateException", NULL); 614 return 0; 615 } 616 int h; 617 if (0 != mp->getVideoHeight(&h)) { 618 ALOGE("getVideoHeight failed"); 619 h = 0; 620 } 621 ALOGV("getVideoHeight: %d", h); 622 return (jint) h; 623 } 624 625 626 static jint 627 android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz) 628 { 629 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 630 if (mp == NULL ) { 631 jniThrowException(env, "java/lang/IllegalStateException", NULL); 632 return 0; 633 } 634 int msec; 635 process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL ); 636 ALOGV("getCurrentPosition: %d (msec)", msec); 637 return (jint) msec; 638 } 639 640 static jint 641 android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz) 642 { 643 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 644 if (mp == NULL ) { 645 jniThrowException(env, "java/lang/IllegalStateException", NULL); 646 return 0; 647 } 648 int msec; 649 process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL ); 650 ALOGV("getDuration: %d (msec)", msec); 651 return (jint) msec; 652 } 653 654 static void 655 android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz) 656 { 657 ALOGV("reset"); 658 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 659 if (mp == NULL ) { 660 jniThrowException(env, "java/lang/IllegalStateException", NULL); 661 return; 662 } 663 process_media_player_call( env, thiz, mp->reset(), NULL, NULL ); 664 } 665 666 static void 667 android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, jint streamtype) 668 { 669 ALOGV("setAudioStreamType: %d", streamtype); 670 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 671 if (mp == NULL ) { 672 jniThrowException(env, "java/lang/IllegalStateException", NULL); 673 return; 674 } 675 process_media_player_call( env, thiz, mp->setAudioStreamType((audio_stream_type_t) streamtype) , NULL, NULL ); 676 } 677 678 static jint 679 android_media_MediaPlayer_getAudioStreamType(JNIEnv *env, jobject thiz) 680 { 681 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 682 if (mp == NULL ) { 683 jniThrowException(env, "java/lang/IllegalStateException", NULL); 684 return 0; 685 } 686 audio_stream_type_t streamtype; 687 process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL ); 688 ALOGV("getAudioStreamType: %d (streamtype)", streamtype); 689 return (jint) streamtype; 690 } 691 692 static jboolean 693 android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request) 694 { 695 ALOGV("setParameter: key %d", key); 696 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 697 if (mp == NULL ) { 698 jniThrowException(env, "java/lang/IllegalStateException", NULL); 699 return false; 700 } 701 702 Parcel *request = parcelForJavaObject(env, java_request); 703 status_t err = mp->setParameter(key, *request); 704 if (err == OK) { 705 return true; 706 } else { 707 return false; 708 } 709 } 710 711 static void 712 android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping) 713 { 714 ALOGV("setLooping: %d", looping); 715 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 716 if (mp == NULL ) { 717 jniThrowException(env, "java/lang/IllegalStateException", NULL); 718 return; 719 } 720 process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL ); 721 } 722 723 static jboolean 724 android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz) 725 { 726 ALOGV("isLooping"); 727 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 728 if (mp == NULL ) { 729 jniThrowException(env, "java/lang/IllegalStateException", NULL); 730 return JNI_FALSE; 731 } 732 return mp->isLooping() ? JNI_TRUE : JNI_FALSE; 733 } 734 735 static void 736 android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, jfloat leftVolume, jfloat rightVolume) 737 { 738 ALOGV("setVolume: left %f right %f", (float) leftVolume, (float) rightVolume); 739 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 740 if (mp == NULL ) { 741 jniThrowException(env, "java/lang/IllegalStateException", NULL); 742 return; 743 } 744 process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL ); 745 } 746 747 // Sends the request and reply parcels to the media player via the 748 // binder interface. 749 static jint 750 android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz, 751 jobject java_request, jobject java_reply) 752 { 753 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 754 if (media_player == NULL ) { 755 jniThrowException(env, "java/lang/IllegalStateException", NULL); 756 return UNKNOWN_ERROR; 757 } 758 759 Parcel *request = parcelForJavaObject(env, java_request); 760 Parcel *reply = parcelForJavaObject(env, java_reply); 761 762 // Don't use process_media_player_call which use the async loop to 763 // report errors, instead returns the status. 764 return (jint) media_player->invoke(*request, reply); 765 } 766 767 // Sends the new filter to the client. 768 static jint 769 android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request) 770 { 771 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 772 if (media_player == NULL ) { 773 jniThrowException(env, "java/lang/IllegalStateException", NULL); 774 return UNKNOWN_ERROR; 775 } 776 777 Parcel *filter = parcelForJavaObject(env, request); 778 779 if (filter == NULL ) { 780 jniThrowException(env, "java/lang/RuntimeException", "Filter is null"); 781 return UNKNOWN_ERROR; 782 } 783 784 return (jint) media_player->setMetadataFilter(*filter); 785 } 786 787 static jboolean 788 android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only, 789 jboolean apply_filter, jobject reply) 790 { 791 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 792 if (media_player == NULL ) { 793 jniThrowException(env, "java/lang/IllegalStateException", NULL); 794 return JNI_FALSE; 795 } 796 797 Parcel *metadata = parcelForJavaObject(env, reply); 798 799 if (metadata == NULL ) { 800 jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null"); 801 return JNI_FALSE; 802 } 803 804 metadata->freeData(); 805 // On return metadata is positioned at the beginning of the 806 // metadata. Note however that the parcel actually starts with the 807 // return code so you should not rewind the parcel using 808 // setDataPosition(0). 809 if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) { 810 return JNI_TRUE; 811 } else { 812 return JNI_FALSE; 813 } 814 } 815 816 // This function gets some field IDs, which in turn causes class initialization. 817 // It is called from a static block in MediaPlayer, which won't run until the 818 // first time an instance of this class is used. 819 static void 820 android_media_MediaPlayer_native_init(JNIEnv *env) 821 { 822 jclass clazz; 823 824 clazz = env->FindClass("android/media/MediaPlayer"); 825 if (clazz == NULL) { 826 return; 827 } 828 829 fields.context = env->GetFieldID(clazz, "mNativeContext", "J"); 830 if (fields.context == NULL) { 831 return; 832 } 833 834 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", 835 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 836 if (fields.post_event == NULL) { 837 return; 838 } 839 840 fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "J"); 841 if (fields.surface_texture == NULL) { 842 return; 843 } 844 845 env->DeleteLocalRef(clazz); 846 847 clazz = env->FindClass("android/net/ProxyInfo"); 848 if (clazz == NULL) { 849 return; 850 } 851 852 fields.proxyConfigGetHost = 853 env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;"); 854 855 fields.proxyConfigGetPort = 856 env->GetMethodID(clazz, "getPort", "()I"); 857 858 fields.proxyConfigGetExclusionList = 859 env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;"); 860 861 env->DeleteLocalRef(clazz); 862 863 gPlaybackParamsFields.init(env); 864 gSyncParamsFields.init(env); 865 } 866 867 static void 868 android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) 869 { 870 ALOGV("native_setup"); 871 sp<MediaPlayer> mp = new MediaPlayer(); 872 if (mp == NULL) { 873 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 874 return; 875 } 876 877 // create new listener and give it to MediaPlayer 878 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); 879 mp->setListener(listener); 880 881 // Stow our new C++ MediaPlayer in an opaque field in the Java object. 882 setMediaPlayer(env, thiz, mp); 883 } 884 885 static void 886 android_media_MediaPlayer_release(JNIEnv *env, jobject thiz) 887 { 888 ALOGV("release"); 889 decVideoSurfaceRef(env, thiz); 890 sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0); 891 if (mp != NULL) { 892 // this prevents native callbacks after the object is released 893 mp->setListener(0); 894 mp->disconnect(); 895 } 896 } 897 898 static void 899 android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) 900 { 901 ALOGV("native_finalize"); 902 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 903 if (mp != NULL) { 904 ALOGW("MediaPlayer finalized without being released"); 905 } 906 android_media_MediaPlayer_release(env, thiz); 907 } 908 909 static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, 910 jint sessionId) { 911 ALOGV("set_session_id(): %d", sessionId); 912 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 913 if (mp == NULL ) { 914 jniThrowException(env, "java/lang/IllegalStateException", NULL); 915 return; 916 } 917 process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL, 918 NULL); 919 } 920 921 static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) { 922 ALOGV("get_session_id()"); 923 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 924 if (mp == NULL ) { 925 jniThrowException(env, "java/lang/IllegalStateException", NULL); 926 return 0; 927 } 928 929 return (jint) mp->getAudioSessionId(); 930 } 931 932 static void 933 android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level) 934 { 935 ALOGV("setAuxEffectSendLevel: level %f", level); 936 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 937 if (mp == NULL ) { 938 jniThrowException(env, "java/lang/IllegalStateException", NULL); 939 return; 940 } 941 process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL ); 942 } 943 944 static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz, jint effectId) { 945 ALOGV("attachAuxEffect(): %d", effectId); 946 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 947 if (mp == NULL ) { 948 jniThrowException(env, "java/lang/IllegalStateException", NULL); 949 return; 950 } 951 process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL ); 952 } 953 954 static jint 955 android_media_MediaPlayer_pullBatteryData( 956 JNIEnv *env, jobject /* thiz */, jobject java_reply) 957 { 958 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player")); 959 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 960 if (service.get() == NULL) { 961 jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService"); 962 return UNKNOWN_ERROR; 963 } 964 965 Parcel *reply = parcelForJavaObject(env, java_reply); 966 967 return (jint) service->pullBatteryData(reply); 968 } 969 970 static jint 971 android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz, 972 jstring addrString, jint port) { 973 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 974 if (mp == NULL ) { 975 jniThrowException(env, "java/lang/IllegalStateException", NULL); 976 return INVALID_OPERATION; 977 } 978 979 const char *cAddrString = NULL; 980 981 if (NULL != addrString) { 982 cAddrString = env->GetStringUTFChars(addrString, NULL); 983 if (cAddrString == NULL) { // Out of memory 984 return NO_MEMORY; 985 } 986 } 987 ALOGV("setRetransmitEndpoint: %s:%d", 988 cAddrString ? cAddrString : "(null)", port); 989 990 status_t ret; 991 if (cAddrString && (port > 0xFFFF)) { 992 ret = BAD_VALUE; 993 } else { 994 ret = mp->setRetransmitEndpoint(cAddrString, 995 static_cast<uint16_t>(port)); 996 } 997 998 if (NULL != addrString) { 999 env->ReleaseStringUTFChars(addrString, cAddrString); 1000 } 1001 1002 if (ret == INVALID_OPERATION ) { 1003 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1004 } 1005 1006 return (jint) ret; 1007 } 1008 1009 static void 1010 android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player) 1011 { 1012 ALOGV("setNextMediaPlayer"); 1013 sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz); 1014 if (thisplayer == NULL) { 1015 jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized"); 1016 return; 1017 } 1018 sp<MediaPlayer> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player); 1019 if (nextplayer == NULL && java_player != NULL) { 1020 jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized"); 1021 return; 1022 } 1023 1024 if (nextplayer == thisplayer) { 1025 jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self"); 1026 return; 1027 } 1028 // tie the two players together 1029 process_media_player_call( 1030 env, thiz, thisplayer->setNextMediaPlayer(nextplayer), 1031 "java/lang/IllegalArgumentException", 1032 "setNextMediaPlayer failed." ); 1033 ; 1034 } 1035 1036 // ---------------------------------------------------------------------------- 1037 1038 static const JNINativeMethod gMethods[] = { 1039 { 1040 "nativeSetDataSource", 1041 "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;" 1042 "[Ljava/lang/String;)V", 1043 (void *)android_media_MediaPlayer_setDataSourceAndHeaders 1044 }, 1045 1046 {"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, 1047 {"_setDataSource", "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback }, 1048 {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface}, 1049 {"_prepare", "()V", (void *)android_media_MediaPlayer_prepare}, 1050 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, 1051 {"_start", "()V", (void *)android_media_MediaPlayer_start}, 1052 {"_stop", "()V", (void *)android_media_MediaPlayer_stop}, 1053 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth}, 1054 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight}, 1055 {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams}, 1056 {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams}, 1057 {"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer_setSyncParams}, 1058 {"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer_getSyncParams}, 1059 {"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo}, 1060 {"_pause", "()V", (void *)android_media_MediaPlayer_pause}, 1061 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying}, 1062 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition}, 1063 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration}, 1064 {"_release", "()V", (void *)android_media_MediaPlayer_release}, 1065 {"_reset", "()V", (void *)android_media_MediaPlayer_reset}, 1066 {"_setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType}, 1067 {"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer_getAudioStreamType}, 1068 {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter}, 1069 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping}, 1070 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping}, 1071 {"_setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume}, 1072 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke}, 1073 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter}, 1074 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata}, 1075 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init}, 1076 {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup}, 1077 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize}, 1078 {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id}, 1079 {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id}, 1080 {"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel}, 1081 {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect}, 1082 {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData}, 1083 {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint}, 1084 {"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer}, 1085 }; 1086 1087 // This function only registers the native methods 1088 static int register_android_media_MediaPlayer(JNIEnv *env) 1089 { 1090 return AndroidRuntime::registerNativeMethods(env, 1091 "android/media/MediaPlayer", gMethods, NELEM(gMethods)); 1092 } 1093 extern int register_android_media_ExifInterface(JNIEnv *env); 1094 extern int register_android_media_ImageReader(JNIEnv *env); 1095 extern int register_android_media_ImageWriter(JNIEnv *env); 1096 extern int register_android_media_Crypto(JNIEnv *env); 1097 extern int register_android_media_Drm(JNIEnv *env); 1098 extern int register_android_media_MediaCodec(JNIEnv *env); 1099 extern int register_android_media_MediaExtractor(JNIEnv *env); 1100 extern int register_android_media_MediaCodecList(JNIEnv *env); 1101 extern int register_android_media_MediaHTTPConnection(JNIEnv *env); 1102 extern int register_android_media_MediaMetadataRetriever(JNIEnv *env); 1103 extern int register_android_media_MediaMuxer(JNIEnv *env); 1104 extern int register_android_media_MediaRecorder(JNIEnv *env); 1105 extern int register_android_media_MediaScanner(JNIEnv *env); 1106 extern int register_android_media_MediaSync(JNIEnv *env); 1107 extern int register_android_media_ResampleInputStream(JNIEnv *env); 1108 extern int register_android_media_MediaProfiles(JNIEnv *env); 1109 extern int register_android_media_AmrInputStream(JNIEnv *env); 1110 extern int register_android_mtp_MtpDatabase(JNIEnv *env); 1111 extern int register_android_mtp_MtpDevice(JNIEnv *env); 1112 extern int register_android_mtp_MtpServer(JNIEnv *env); 1113 1114 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) 1115 { 1116 JNIEnv* env = NULL; 1117 jint result = -1; 1118 1119 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 1120 ALOGE("ERROR: GetEnv failed\n"); 1121 goto bail; 1122 } 1123 assert(env != NULL); 1124 1125 if (register_android_media_ImageWriter(env) != JNI_OK) { 1126 ALOGE("ERROR: ImageWriter native registration failed"); 1127 goto bail; 1128 } 1129 1130 if (register_android_media_ImageReader(env) < 0) { 1131 ALOGE("ERROR: ImageReader native registration failed"); 1132 goto bail; 1133 } 1134 1135 if (register_android_media_MediaPlayer(env) < 0) { 1136 ALOGE("ERROR: MediaPlayer native registration failed\n"); 1137 goto bail; 1138 } 1139 1140 if (register_android_media_MediaRecorder(env) < 0) { 1141 ALOGE("ERROR: MediaRecorder native registration failed\n"); 1142 goto bail; 1143 } 1144 1145 if (register_android_media_MediaScanner(env) < 0) { 1146 ALOGE("ERROR: MediaScanner native registration failed\n"); 1147 goto bail; 1148 } 1149 1150 if (register_android_media_MediaMetadataRetriever(env) < 0) { 1151 ALOGE("ERROR: MediaMetadataRetriever native registration failed\n"); 1152 goto bail; 1153 } 1154 1155 if (register_android_media_AmrInputStream(env) < 0) { 1156 ALOGE("ERROR: AmrInputStream native registration failed\n"); 1157 goto bail; 1158 } 1159 1160 if (register_android_media_ResampleInputStream(env) < 0) { 1161 ALOGE("ERROR: ResampleInputStream native registration failed\n"); 1162 goto bail; 1163 } 1164 1165 if (register_android_media_MediaProfiles(env) < 0) { 1166 ALOGE("ERROR: MediaProfiles native registration failed"); 1167 goto bail; 1168 } 1169 1170 if (register_android_mtp_MtpDatabase(env) < 0) { 1171 ALOGE("ERROR: MtpDatabase native registration failed"); 1172 goto bail; 1173 } 1174 1175 if (register_android_mtp_MtpDevice(env) < 0) { 1176 ALOGE("ERROR: MtpDevice native registration failed"); 1177 goto bail; 1178 } 1179 1180 if (register_android_mtp_MtpServer(env) < 0) { 1181 ALOGE("ERROR: MtpServer native registration failed"); 1182 goto bail; 1183 } 1184 1185 if (register_android_media_MediaCodec(env) < 0) { 1186 ALOGE("ERROR: MediaCodec native registration failed"); 1187 goto bail; 1188 } 1189 1190 if (register_android_media_MediaSync(env) < 0) { 1191 ALOGE("ERROR: MediaSync native registration failed"); 1192 goto bail; 1193 } 1194 1195 if (register_android_media_MediaExtractor(env) < 0) { 1196 ALOGE("ERROR: MediaCodec native registration failed"); 1197 goto bail; 1198 } 1199 1200 if (register_android_media_MediaMuxer(env) < 0) { 1201 ALOGE("ERROR: MediaMuxer native registration failed"); 1202 goto bail; 1203 } 1204 1205 if (register_android_media_MediaCodecList(env) < 0) { 1206 ALOGE("ERROR: MediaCodec native registration failed"); 1207 goto bail; 1208 } 1209 1210 if (register_android_media_Crypto(env) < 0) { 1211 ALOGE("ERROR: MediaCodec native registration failed"); 1212 goto bail; 1213 } 1214 1215 if (register_android_media_Drm(env) < 0) { 1216 ALOGE("ERROR: MediaDrm native registration failed"); 1217 goto bail; 1218 } 1219 1220 if (register_android_media_MediaHTTPConnection(env) < 0) { 1221 ALOGE("ERROR: MediaHTTPConnection native registration failed"); 1222 goto bail; 1223 } 1224 1225 if (register_android_media_ExifInterface(env) < 0) { 1226 ALOGE("ERROR: ExifInterface native registration failed"); 1227 goto bail; 1228 } 1229 1230 /* success -- return valid version number */ 1231 result = JNI_VERSION_1_4; 1232 1233 bail: 1234 return result; 1235 } 1236 1237 // KTHXBYE 1238