android_media_MediaPlayer.cpp revision bfb9fb143b67c2d0307af2bce9af3c08f362b29a
1/* //device/libs/android_runtime/android_media_MediaPlayer.cpp 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/MediaPlayerInterface.h> 24#include <stdio.h> 25#include <assert.h> 26#include <limits.h> 27#include <unistd.h> 28#include <fcntl.h> 29#include <utils/threads.h> 30#include "jni.h" 31#include "JNIHelp.h" 32#include "android_runtime/AndroidRuntime.h" 33#include "utils/Errors.h" // for status_t 34#include "android_util_Binder.h" 35#include <binder/Parcel.h> 36 37 38// ---------------------------------------------------------------------------- 39 40using namespace android; 41 42// ---------------------------------------------------------------------------- 43 44struct fields_t { 45 jfieldID context; 46 jfieldID surface; 47 /* actually in android.view.Surface XXX */ 48 jfieldID surface_native; 49 50 jmethodID post_event; 51}; 52static fields_t fields; 53 54static Mutex sLock; 55 56// ---------------------------------------------------------------------------- 57// ref-counted object for callbacks 58class JNIMediaPlayerListener: public MediaPlayerListener 59{ 60public: 61 JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz); 62 ~JNIMediaPlayerListener(); 63 void notify(int msg, int ext1, int ext2); 64private: 65 JNIMediaPlayerListener(); 66 jclass mClass; // Reference to MediaPlayer class 67 jobject mObject; // Weak ref to MediaPlayer Java object to call on 68}; 69 70JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz) 71{ 72 73 // Hold onto the MediaPlayer class for use in calling the static method 74 // that posts events to the application thread. 75 jclass clazz = env->GetObjectClass(thiz); 76 if (clazz == NULL) { 77 LOGE("Can't find android/media/MediaPlayer"); 78 jniThrowException(env, "java/lang/Exception", NULL); 79 return; 80 } 81 mClass = (jclass)env->NewGlobalRef(clazz); 82 83 // We use a weak reference so the MediaPlayer object can be garbage collected. 84 // The reference is only used as a proxy for callbacks. 85 mObject = env->NewGlobalRef(weak_thiz); 86} 87 88JNIMediaPlayerListener::~JNIMediaPlayerListener() 89{ 90 // remove global references 91 JNIEnv *env = AndroidRuntime::getJNIEnv(); 92 env->DeleteGlobalRef(mObject); 93 env->DeleteGlobalRef(mClass); 94} 95 96void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2) 97{ 98 JNIEnv *env = AndroidRuntime::getJNIEnv(); 99 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, 0); 100} 101 102// ---------------------------------------------------------------------------- 103 104static Surface* get_surface(JNIEnv* env, jobject clazz) 105{ 106 return (Surface*)env->GetIntField(clazz, fields.surface_native); 107} 108 109static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) 110{ 111 Mutex::Autolock l(sLock); 112 MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context); 113 return sp<MediaPlayer>(p); 114} 115 116static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player) 117{ 118 Mutex::Autolock l(sLock); 119 sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context); 120 if (player.get()) { 121 player->incStrong(thiz); 122 } 123 if (old != 0) { 124 old->decStrong(thiz); 125 } 126 env->SetIntField(thiz, fields.context, (int)player.get()); 127 return old; 128} 129 130// If exception is NULL and opStatus is not OK, this method sends an error 131// event to the client application; otherwise, if exception is not NULL and 132// opStatus is not OK, this method throws the given exception to the client 133// application. 134static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message) 135{ 136 if (exception == NULL) { // Don't throw exception. Instead, send an event. 137 if (opStatus != (status_t) OK) { 138 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 139 if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0); 140 } 141 } else { // Throw exception! 142 if ( opStatus == (status_t) INVALID_OPERATION ) { 143 jniThrowException(env, "java/lang/IllegalStateException", NULL); 144 } else if ( opStatus != (status_t) OK ) { 145 if (strlen(message) > 230) { 146 // if the message is too long, don't bother displaying the status code 147 jniThrowException( env, exception, message); 148 } else { 149 char msg[256]; 150 // append the status code to the message 151 sprintf(msg, "%s: status=0x%X", message, opStatus); 152 jniThrowException( env, exception, msg); 153 } 154 } 155 } 156} 157 158static void 159android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path) 160{ 161 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 162 if (mp == NULL ) { 163 jniThrowException(env, "java/lang/IllegalStateException", NULL); 164 return; 165 } 166 167 if (path == NULL) { 168 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 169 return; 170 } 171 172 const char *pathStr = env->GetStringUTFChars(path, NULL); 173 if (pathStr == NULL) { // Out of memory 174 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 175 return; 176 } 177 LOGV("setDataSource: path %s", pathStr); 178 status_t opStatus = mp->setDataSource(pathStr); 179 180 // Make sure that local ref is released before a potential exception 181 env->ReleaseStringUTFChars(path, pathStr); 182 process_media_player_call( env, thiz, opStatus, "java/io/IOException", "setDataSource failed." ); 183} 184 185static void 186android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) 187{ 188 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 189 if (mp == NULL ) { 190 jniThrowException(env, "java/lang/IllegalStateException", NULL); 191 return; 192 } 193 194 if (fileDescriptor == NULL) { 195 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 196 return; 197 } 198 int fd = getParcelFileDescriptorFD(env, fileDescriptor); 199 LOGV("setDataSourceFD: fd %d", fd); 200 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); 201} 202 203static void setVideoSurface(const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz) 204{ 205 jobject surface = env->GetObjectField(thiz, fields.surface); 206 if (surface != NULL) { 207 const sp<Surface> native_surface = get_surface(env, surface); 208 LOGV("prepare: surface=%p (id=%d)", 209 native_surface.get(), native_surface->ID()); 210 mp->setVideoSurface(native_surface); 211 } 212} 213 214static void 215android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz) 216{ 217 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 218 if (mp == NULL ) { 219 jniThrowException(env, "java/lang/IllegalStateException", NULL); 220 return; 221 } 222 setVideoSurface(mp, env, thiz); 223} 224 225static void 226android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) 227{ 228 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 229 if (mp == NULL ) { 230 jniThrowException(env, "java/lang/IllegalStateException", NULL); 231 return; 232 } 233 setVideoSurface(mp, env, thiz); 234 process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." ); 235} 236 237static void 238android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz) 239{ 240 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 241 if (mp == NULL ) { 242 jniThrowException(env, "java/lang/IllegalStateException", NULL); 243 return; 244 } 245 jobject surface = env->GetObjectField(thiz, fields.surface); 246 if (surface != NULL) { 247 const sp<Surface> native_surface = get_surface(env, surface); 248 LOGV("prepareAsync: surface=%p (id=%d)", 249 native_surface.get(), native_surface->ID()); 250 mp->setVideoSurface(native_surface); 251 } 252 process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." ); 253} 254 255static void 256android_media_MediaPlayer_start(JNIEnv *env, jobject thiz) 257{ 258 LOGV("start"); 259 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 260 if (mp == NULL ) { 261 jniThrowException(env, "java/lang/IllegalStateException", NULL); 262 return; 263 } 264 process_media_player_call( env, thiz, mp->start(), NULL, NULL ); 265} 266 267static void 268android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz) 269{ 270 LOGV("stop"); 271 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 272 if (mp == NULL ) { 273 jniThrowException(env, "java/lang/IllegalStateException", NULL); 274 return; 275 } 276 process_media_player_call( env, thiz, mp->stop(), NULL, NULL ); 277} 278 279static void 280android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz) 281{ 282 LOGV("pause"); 283 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 284 if (mp == NULL ) { 285 jniThrowException(env, "java/lang/IllegalStateException", NULL); 286 return; 287 } 288 process_media_player_call( env, thiz, mp->pause(), NULL, NULL ); 289} 290 291static jboolean 292android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz) 293{ 294 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 295 if (mp == NULL ) { 296 jniThrowException(env, "java/lang/IllegalStateException", NULL); 297 return false; 298 } 299 const jboolean is_playing = mp->isPlaying(); 300 301 LOGV("isPlaying: %d", is_playing); 302 return is_playing; 303} 304 305static void 306android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, int msec) 307{ 308 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 309 if (mp == NULL ) { 310 jniThrowException(env, "java/lang/IllegalStateException", NULL); 311 return; 312 } 313 LOGV("seekTo: %d(msec)", msec); 314 process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL ); 315} 316 317static int 318android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz) 319{ 320 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 321 if (mp == NULL ) { 322 jniThrowException(env, "java/lang/IllegalStateException", NULL); 323 return 0; 324 } 325 int w; 326 if (0 != mp->getVideoWidth(&w)) { 327 LOGE("getVideoWidth failed"); 328 w = 0; 329 } 330 LOGV("getVideoWidth: %d", w); 331 return w; 332} 333 334static int 335android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz) 336{ 337 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 338 if (mp == NULL ) { 339 jniThrowException(env, "java/lang/IllegalStateException", NULL); 340 return 0; 341 } 342 int h; 343 if (0 != mp->getVideoHeight(&h)) { 344 LOGE("getVideoHeight failed"); 345 h = 0; 346 } 347 LOGV("getVideoHeight: %d", h); 348 return h; 349} 350 351 352static int 353android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz) 354{ 355 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 356 if (mp == NULL ) { 357 jniThrowException(env, "java/lang/IllegalStateException", NULL); 358 return 0; 359 } 360 int msec; 361 process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL ); 362 LOGV("getCurrentPosition: %d (msec)", msec); 363 return msec; 364} 365 366static int 367android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz) 368{ 369 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 370 if (mp == NULL ) { 371 jniThrowException(env, "java/lang/IllegalStateException", NULL); 372 return 0; 373 } 374 int msec; 375 process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL ); 376 LOGV("getDuration: %d (msec)", msec); 377 return msec; 378} 379 380static void 381android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz) 382{ 383 LOGV("reset"); 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->reset(), NULL, NULL ); 390} 391 392static void 393android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, int streamtype) 394{ 395 LOGV("setAudioStreamType: %d", streamtype); 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->setAudioStreamType(streamtype) , NULL, NULL ); 402} 403 404static void 405android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping) 406{ 407 LOGV("setLooping: %d", looping); 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->setLooping(looping), NULL, NULL ); 414} 415 416static jboolean 417android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz) 418{ 419 LOGV("isLooping"); 420 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 421 if (mp == NULL ) { 422 jniThrowException(env, "java/lang/IllegalStateException", NULL); 423 return false; 424 } 425 return mp->isLooping(); 426} 427 428static void 429android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, float leftVolume, float rightVolume) 430{ 431 LOGV("setVolume: left %f right %f", leftVolume, rightVolume); 432 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 433 if (mp == NULL ) { 434 jniThrowException(env, "java/lang/IllegalStateException", NULL); 435 return; 436 } 437 process_media_player_call( env, thiz, mp->setVolume(leftVolume, rightVolume), NULL, NULL ); 438} 439 440// FIXME: deprecated 441static jobject 442android_media_MediaPlayer_getFrameAt(JNIEnv *env, jobject thiz, jint msec) 443{ 444 return NULL; 445} 446 447 448// Sends the request and reply parcels to the media player via the 449// binder interface. 450static jint 451android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz, 452 jobject java_request, jobject java_reply) 453{ 454 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 455 if (media_player == NULL ) { 456 jniThrowException(env, "java/lang/IllegalStateException", NULL); 457 return UNKNOWN_ERROR; 458 } 459 460 461 Parcel *request = parcelForJavaObject(env, java_request); 462 Parcel *reply = parcelForJavaObject(env, java_reply); 463 464 // Don't use process_media_player_call which use the async loop to 465 // report errors, instead returns the status. 466 return media_player->invoke(*request, reply); 467} 468 469// Sends the new filter to the client. 470static jint 471android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request) 472{ 473 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 474 if (media_player == NULL ) { 475 jniThrowException(env, "java/lang/IllegalStateException", NULL); 476 return UNKNOWN_ERROR; 477 } 478 479 Parcel *filter = parcelForJavaObject(env, request); 480 481 if (filter == NULL ) { 482 jniThrowException(env, "java/lang/RuntimeException", "Filter is null"); 483 return UNKNOWN_ERROR; 484 } 485 486 return media_player->setMetadataFilter(*filter); 487} 488 489static jboolean 490android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only, 491 jboolean apply_filter, jobject reply) 492{ 493 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 494 if (media_player == NULL ) { 495 jniThrowException(env, "java/lang/IllegalStateException", NULL); 496 return false; 497 } 498 499 Parcel *metadata = parcelForJavaObject(env, reply); 500 501 if (metadata == NULL ) { 502 jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null"); 503 return false; 504 } 505 506 metadata->freeData(); 507 // On return metadata is positioned at the beginning of the 508 // metadata. Note however that the parcel actually starts with the 509 // return code so you should not rewind the parcel using 510 // setDataPosition(0). 511 return media_player->getMetadata(update_only, apply_filter, metadata) == OK; 512} 513 514// This function gets some field IDs, which in turn causes class initialization. 515// It is called from a static block in MediaPlayer, which won't run until the 516// first time an instance of this class is used. 517static void 518android_media_MediaPlayer_native_init(JNIEnv *env) 519{ 520 jclass clazz; 521 522 clazz = env->FindClass("android/media/MediaPlayer"); 523 if (clazz == NULL) { 524 jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaPlayer"); 525 return; 526 } 527 528 fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 529 if (fields.context == NULL) { 530 jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.mNativeContext"); 531 return; 532 } 533 534 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", 535 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 536 if (fields.post_event == NULL) { 537 jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.postEventFromNative"); 538 return; 539 } 540 541 fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;"); 542 if (fields.surface == NULL) { 543 jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.mSurface"); 544 return; 545 } 546 547 jclass surface = env->FindClass("android/view/Surface"); 548 if (surface == NULL) { 549 jniThrowException(env, "java/lang/RuntimeException", "Can't find android/view/Surface"); 550 return; 551 } 552 553 fields.surface_native = env->GetFieldID(surface, "mSurface", "I"); 554 if (fields.surface_native == NULL) { 555 jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface"); 556 return; 557 } 558} 559 560static void 561android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) 562{ 563 LOGV("native_setup"); 564 sp<MediaPlayer> mp = new MediaPlayer(); 565 if (mp == NULL) { 566 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 567 return; 568 } 569 570 // create new listener and give it to MediaPlayer 571 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); 572 mp->setListener(listener); 573 574 // Stow our new C++ MediaPlayer in an opaque field in the Java object. 575 setMediaPlayer(env, thiz, mp); 576} 577 578static void 579android_media_MediaPlayer_release(JNIEnv *env, jobject thiz) 580{ 581 LOGV("release"); 582 sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0); 583 if (mp != NULL) { 584 // this prevents native callbacks after the object is released 585 mp->setListener(0); 586 mp->disconnect(); 587 } 588} 589 590static void 591android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) 592{ 593 LOGV("native_finalize"); 594 android_media_MediaPlayer_release(env, thiz); 595} 596 597static jint 598android_media_MediaPlayer_snoop(JNIEnv* env, jobject thiz, jobject data, jint kind) { 599 jshort* ar = (jshort*)env->GetPrimitiveArrayCritical((jarray)data, 0); 600 jsize len = env->GetArrayLength((jarray)data); 601 int ret = 0; 602 if (ar) { 603 ret = MediaPlayer::snoop(ar, len, kind); 604 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 605 } 606 return ret; 607} 608 609// ---------------------------------------------------------------------------- 610 611static JNINativeMethod gMethods[] = { 612 {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource}, 613 {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, 614 {"_setVideoSurface", "()V", (void *)android_media_MediaPlayer_setVideoSurface}, 615 {"prepare", "()V", (void *)android_media_MediaPlayer_prepare}, 616 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, 617 {"_start", "()V", (void *)android_media_MediaPlayer_start}, 618 {"_stop", "()V", (void *)android_media_MediaPlayer_stop}, 619 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth}, 620 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight}, 621 {"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo}, 622 {"_pause", "()V", (void *)android_media_MediaPlayer_pause}, 623 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying}, 624 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition}, 625 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration}, 626 {"_release", "()V", (void *)android_media_MediaPlayer_release}, 627 {"_reset", "()V", (void *)android_media_MediaPlayer_reset}, 628 {"setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType}, 629 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping}, 630 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping}, 631 {"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume}, 632 {"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt}, 633 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke}, 634 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter}, 635 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata}, 636 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init}, 637 {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup}, 638 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize}, 639 {"snoop", "([SI)I", (void *)android_media_MediaPlayer_snoop}, 640}; 641 642static const char* const kClassPathName = "android/media/MediaPlayer"; 643 644// This function only registers the native methods 645static int register_android_media_MediaPlayer(JNIEnv *env) 646{ 647 return AndroidRuntime::registerNativeMethods(env, 648 "android/media/MediaPlayer", gMethods, NELEM(gMethods)); 649} 650 651extern int register_android_media_MediaMetadataRetriever(JNIEnv *env); 652extern int register_android_media_MediaRecorder(JNIEnv *env); 653extern int register_android_media_MediaScanner(JNIEnv *env); 654extern int register_android_media_ResampleInputStream(JNIEnv *env); 655 656#ifndef NO_OPENCORE 657extern int register_android_media_AmrInputStream(JNIEnv *env); 658#endif 659 660jint JNI_OnLoad(JavaVM* vm, void* reserved) 661{ 662 JNIEnv* env = NULL; 663 jint result = -1; 664 665 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 666 LOGE("ERROR: GetEnv failed\n"); 667 goto bail; 668 } 669 assert(env != NULL); 670 671 if (register_android_media_MediaPlayer(env) < 0) { 672 LOGE("ERROR: MediaPlayer native registration failed\n"); 673 goto bail; 674 } 675 676 if (register_android_media_MediaRecorder(env) < 0) { 677 LOGE("ERROR: MediaRecorder native registration failed\n"); 678 goto bail; 679 } 680 681 if (register_android_media_MediaScanner(env) < 0) { 682 LOGE("ERROR: MediaScanner native registration failed\n"); 683 goto bail; 684 } 685 686 if (register_android_media_MediaMetadataRetriever(env) < 0) { 687 LOGE("ERROR: MediaMetadataRetriever native registration failed\n"); 688 goto bail; 689 } 690 691#ifndef NO_OPENCORE 692 if (register_android_media_AmrInputStream(env) < 0) { 693 LOGE("ERROR: AmrInputStream native registration failed\n"); 694 goto bail; 695 } 696#endif 697 698 if (register_android_media_ResampleInputStream(env) < 0) { 699 LOGE("ERROR: ResampleInputStream native registration failed\n"); 700 goto bail; 701 } 702 703 /* success -- return valid version number */ 704 result = JNI_VERSION_1_4; 705 706bail: 707 return result; 708} 709 710// KTHXBYE 711