android_media_MediaPlayer.cpp revision d59310d08637c8531dc7949fc166b0daeede53c0
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/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 "android_runtime/android_view_Surface.h" 34#include "utils/Errors.h" // for status_t 35#include "utils/KeyedVector.h" 36#include "utils/String8.h" 37#include "android_media_Utils.h" 38 39#include "android_util_Binder.h" 40#include <binder/Parcel.h> 41#include <gui/ISurfaceTexture.h> 42#include <surfaceflinger/Surface.h> 43#include <binder/IPCThreadState.h> 44#include <binder/IServiceManager.h> 45 46// ---------------------------------------------------------------------------- 47 48using namespace android; 49 50// ---------------------------------------------------------------------------- 51 52struct fields_t { 53 jfieldID context; 54 jfieldID surface_texture; 55 56 jmethodID post_event; 57}; 58static fields_t fields; 59 60static Mutex sLock; 61 62// ---------------------------------------------------------------------------- 63// ref-counted object for callbacks 64class JNIMediaPlayerListener: public MediaPlayerListener 65{ 66public: 67 JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz); 68 ~JNIMediaPlayerListener(); 69 virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL); 70private: 71 JNIMediaPlayerListener(); 72 jclass mClass; // Reference to MediaPlayer class 73 jobject mObject; // Weak ref to MediaPlayer Java object to call on 74}; 75 76JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz) 77{ 78 79 // Hold onto the MediaPlayer class for use in calling the static method 80 // that posts events to the application thread. 81 jclass clazz = env->GetObjectClass(thiz); 82 if (clazz == NULL) { 83 LOGE("Can't find android/media/MediaPlayer"); 84 jniThrowException(env, "java/lang/Exception", NULL); 85 return; 86 } 87 mClass = (jclass)env->NewGlobalRef(clazz); 88 89 // We use a weak reference so the MediaPlayer object can be garbage collected. 90 // The reference is only used as a proxy for callbacks. 91 mObject = env->NewGlobalRef(weak_thiz); 92} 93 94JNIMediaPlayerListener::~JNIMediaPlayerListener() 95{ 96 // remove global references 97 JNIEnv *env = AndroidRuntime::getJNIEnv(); 98 env->DeleteGlobalRef(mObject); 99 env->DeleteGlobalRef(mClass); 100} 101 102void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj) 103{ 104 JNIEnv *env = AndroidRuntime::getJNIEnv(); 105 if (obj && obj->dataSize() > 0) { 106 jbyteArray jArray = env->NewByteArray(obj->dataSize()); 107 if (jArray != NULL) { 108 jbyte *nArray = env->GetByteArrayElements(jArray, NULL); 109 memcpy(nArray, obj->data(), obj->dataSize()); 110 env->ReleaseByteArrayElements(jArray, nArray, 0); 111 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, 112 msg, ext1, ext2, jArray); 113 env->DeleteLocalRef(jArray); 114 } 115 } else { 116 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, 117 msg, ext1, ext2, NULL); 118 } 119} 120 121// ---------------------------------------------------------------------------- 122 123static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) 124{ 125 Mutex::Autolock l(sLock); 126 MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context); 127 return sp<MediaPlayer>(p); 128} 129 130static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player) 131{ 132 Mutex::Autolock l(sLock); 133 sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context); 134 if (player.get()) { 135 player->incStrong(thiz); 136 } 137 if (old != 0) { 138 old->decStrong(thiz); 139 } 140 env->SetIntField(thiz, fields.context, (int)player.get()); 141 return old; 142} 143 144// If exception is NULL and opStatus is not OK, this method sends an error 145// event to the client application; otherwise, if exception is not NULL and 146// opStatus is not OK, this method throws the given exception to the client 147// application. 148static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message) 149{ 150 if (exception == NULL) { // Don't throw exception. Instead, send an event. 151 if (opStatus != (status_t) OK) { 152 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 153 if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0); 154 } 155 } else { // Throw exception! 156 if ( opStatus == (status_t) INVALID_OPERATION ) { 157 jniThrowException(env, "java/lang/IllegalStateException", NULL); 158 } else if ( opStatus == (status_t) PERMISSION_DENIED ) { 159 jniThrowException(env, "java/lang/SecurityException", NULL); 160 } else if ( opStatus != (status_t) OK ) { 161 if (strlen(message) > 230) { 162 // if the message is too long, don't bother displaying the status code 163 jniThrowException( env, exception, message); 164 } else { 165 char msg[256]; 166 // append the status code to the message 167 sprintf(msg, "%s: status=0x%X", message, opStatus); 168 jniThrowException( env, exception, msg); 169 } 170 } 171 } 172} 173 174static void 175android_media_MediaPlayer_setDataSourceAndHeaders( 176 JNIEnv *env, jobject thiz, jstring path, 177 jobjectArray keys, jobjectArray values) { 178 179 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 180 if (mp == NULL ) { 181 jniThrowException(env, "java/lang/IllegalStateException", NULL); 182 return; 183 } 184 185 if (path == NULL) { 186 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 187 return; 188 } 189 190 const char *tmp = env->GetStringUTFChars(path, NULL); 191 if (tmp == NULL) { // Out of memory 192 return; 193 } 194 LOGV("setDataSource: path %s", tmp); 195 196 String8 pathStr(tmp); 197 env->ReleaseStringUTFChars(path, tmp); 198 tmp = NULL; 199 200 // We build a KeyedVector out of the key and val arrays 201 KeyedVector<String8, String8> headersVector; 202 if (!ConvertKeyValueArraysToKeyedVector( 203 env, keys, values, &headersVector)) { 204 return; 205 } 206 207 status_t opStatus = 208 mp->setDataSource( 209 pathStr, 210 headersVector.size() > 0? &headersVector : NULL); 211 212 process_media_player_call( 213 env, thiz, opStatus, "java/io/IOException", 214 "setDataSource failed." ); 215} 216 217static void 218android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path) 219{ 220 android_media_MediaPlayer_setDataSourceAndHeaders(env, thiz, path, NULL, NULL); 221} 222 223static void 224android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) 225{ 226 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 227 if (mp == NULL ) { 228 jniThrowException(env, "java/lang/IllegalStateException", NULL); 229 return; 230 } 231 232 if (fileDescriptor == NULL) { 233 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 234 return; 235 } 236 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 237 LOGV("setDataSourceFD: fd %d", fd); 238 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); 239} 240 241static sp<ISurfaceTexture> 242getVideoSurfaceTexture(JNIEnv* env, jobject thiz) { 243 ISurfaceTexture * const p = (ISurfaceTexture*)env->GetIntField(thiz, fields.surface_texture); 244 return sp<ISurfaceTexture>(p); 245} 246 247static void 248decVideoSurfaceRef(JNIEnv *env, jobject thiz) 249{ 250 sp<ISurfaceTexture> old_st = getVideoSurfaceTexture(env, thiz); 251 if (old_st != NULL) { 252 old_st->decStrong(thiz); 253 } 254} 255 256static void 257setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive) 258{ 259 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 260 if (mp == NULL) { 261 if (mediaPlayerMustBeAlive) { 262 jniThrowException(env, "java/lang/IllegalStateException", NULL); 263 } 264 return; 265 } 266 267 decVideoSurfaceRef(env, thiz); 268 269 sp<ISurfaceTexture> new_st; 270 if (jsurface) { 271 sp<Surface> surface(Surface_getSurface(env, jsurface)); 272 new_st = surface->getSurfaceTexture(); 273 new_st->incStrong(thiz); 274 } 275 276 env->SetIntField(thiz, fields.surface_texture, (int)new_st.get()); 277 278 // This will fail if the media player has not been initialized yet. This 279 // can be the case if setDisplay() on MediaPlayer.java has been called 280 // before setDataSource(). The redundant call to setVideoSurfaceTexture() 281 // in prepare/prepareAsync covers for this case. 282 mp->setVideoSurfaceTexture(new_st); 283} 284 285static void 286android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface) 287{ 288 setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */); 289} 290 291static void 292android_media_MediaPlayer_prepare(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; 298 } 299 300 // Handle the case where the display surface was set before the mp was 301 // initialized. We try again to make it stick. 302 sp<ISurfaceTexture> st = getVideoSurfaceTexture(env, thiz); 303 mp->setVideoSurfaceTexture(st); 304 305 process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." ); 306} 307 308static void 309android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz) 310{ 311 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 312 if (mp == NULL ) { 313 jniThrowException(env, "java/lang/IllegalStateException", NULL); 314 return; 315 } 316 317 // Handle the case where the display surface was set before the mp was 318 // initialized. We try again to make it stick. 319 sp<ISurfaceTexture> st = getVideoSurfaceTexture(env, thiz); 320 mp->setVideoSurfaceTexture(st); 321 322 process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." ); 323} 324 325static void 326android_media_MediaPlayer_start(JNIEnv *env, jobject thiz) 327{ 328 LOGV("start"); 329 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 330 if (mp == NULL ) { 331 jniThrowException(env, "java/lang/IllegalStateException", NULL); 332 return; 333 } 334 process_media_player_call( env, thiz, mp->start(), NULL, NULL ); 335} 336 337static void 338android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz) 339{ 340 LOGV("stop"); 341 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 342 if (mp == NULL ) { 343 jniThrowException(env, "java/lang/IllegalStateException", NULL); 344 return; 345 } 346 process_media_player_call( env, thiz, mp->stop(), NULL, NULL ); 347} 348 349static void 350android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz) 351{ 352 LOGV("pause"); 353 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 354 if (mp == NULL ) { 355 jniThrowException(env, "java/lang/IllegalStateException", NULL); 356 return; 357 } 358 process_media_player_call( env, thiz, mp->pause(), NULL, NULL ); 359} 360 361static jboolean 362android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz) 363{ 364 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 365 if (mp == NULL ) { 366 jniThrowException(env, "java/lang/IllegalStateException", NULL); 367 return false; 368 } 369 const jboolean is_playing = mp->isPlaying(); 370 371 LOGV("isPlaying: %d", is_playing); 372 return is_playing; 373} 374 375static void 376android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, int msec) 377{ 378 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 379 if (mp == NULL ) { 380 jniThrowException(env, "java/lang/IllegalStateException", NULL); 381 return; 382 } 383 LOGV("seekTo: %d(msec)", msec); 384 process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL ); 385} 386 387static int 388android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz) 389{ 390 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 391 if (mp == NULL ) { 392 jniThrowException(env, "java/lang/IllegalStateException", NULL); 393 return 0; 394 } 395 int w; 396 if (0 != mp->getVideoWidth(&w)) { 397 LOGE("getVideoWidth failed"); 398 w = 0; 399 } 400 LOGV("getVideoWidth: %d", w); 401 return w; 402} 403 404static int 405android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz) 406{ 407 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 408 if (mp == NULL ) { 409 jniThrowException(env, "java/lang/IllegalStateException", NULL); 410 return 0; 411 } 412 int h; 413 if (0 != mp->getVideoHeight(&h)) { 414 LOGE("getVideoHeight failed"); 415 h = 0; 416 } 417 LOGV("getVideoHeight: %d", h); 418 return h; 419} 420 421 422static int 423android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz) 424{ 425 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 426 if (mp == NULL ) { 427 jniThrowException(env, "java/lang/IllegalStateException", NULL); 428 return 0; 429 } 430 int msec; 431 process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL ); 432 LOGV("getCurrentPosition: %d (msec)", msec); 433 return msec; 434} 435 436static int 437android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz) 438{ 439 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 440 if (mp == NULL ) { 441 jniThrowException(env, "java/lang/IllegalStateException", NULL); 442 return 0; 443 } 444 int msec; 445 process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL ); 446 LOGV("getDuration: %d (msec)", msec); 447 return msec; 448} 449 450static void 451android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz) 452{ 453 LOGV("reset"); 454 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 455 if (mp == NULL ) { 456 jniThrowException(env, "java/lang/IllegalStateException", NULL); 457 return; 458 } 459 process_media_player_call( env, thiz, mp->reset(), NULL, NULL ); 460} 461 462static void 463android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, int streamtype) 464{ 465 LOGV("setAudioStreamType: %d", streamtype); 466 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 467 if (mp == NULL ) { 468 jniThrowException(env, "java/lang/IllegalStateException", NULL); 469 return; 470 } 471 process_media_player_call( env, thiz, mp->setAudioStreamType(streamtype) , NULL, NULL ); 472} 473 474static void 475android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping) 476{ 477 LOGV("setLooping: %d", looping); 478 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 479 if (mp == NULL ) { 480 jniThrowException(env, "java/lang/IllegalStateException", NULL); 481 return; 482 } 483 process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL ); 484} 485 486static jboolean 487android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz) 488{ 489 LOGV("isLooping"); 490 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 491 if (mp == NULL ) { 492 jniThrowException(env, "java/lang/IllegalStateException", NULL); 493 return false; 494 } 495 return mp->isLooping(); 496} 497 498static void 499android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, float leftVolume, float rightVolume) 500{ 501 LOGV("setVolume: left %f right %f", leftVolume, rightVolume); 502 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 503 if (mp == NULL ) { 504 jniThrowException(env, "java/lang/IllegalStateException", NULL); 505 return; 506 } 507 process_media_player_call( env, thiz, mp->setVolume(leftVolume, rightVolume), NULL, NULL ); 508} 509 510// FIXME: deprecated 511static jobject 512android_media_MediaPlayer_getFrameAt(JNIEnv *env, jobject thiz, jint msec) 513{ 514 return NULL; 515} 516 517 518// Sends the request and reply parcels to the media player via the 519// binder interface. 520static jint 521android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz, 522 jobject java_request, jobject java_reply) 523{ 524 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 525 if (media_player == NULL ) { 526 jniThrowException(env, "java/lang/IllegalStateException", NULL); 527 return UNKNOWN_ERROR; 528 } 529 530 531 Parcel *request = parcelForJavaObject(env, java_request); 532 Parcel *reply = parcelForJavaObject(env, java_reply); 533 534 // Don't use process_media_player_call which use the async loop to 535 // report errors, instead returns the status. 536 return media_player->invoke(*request, reply); 537} 538 539// Sends the new filter to the client. 540static jint 541android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request) 542{ 543 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 544 if (media_player == NULL ) { 545 jniThrowException(env, "java/lang/IllegalStateException", NULL); 546 return UNKNOWN_ERROR; 547 } 548 549 Parcel *filter = parcelForJavaObject(env, request); 550 551 if (filter == NULL ) { 552 jniThrowException(env, "java/lang/RuntimeException", "Filter is null"); 553 return UNKNOWN_ERROR; 554 } 555 556 return media_player->setMetadataFilter(*filter); 557} 558 559static jboolean 560android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only, 561 jboolean apply_filter, jobject reply) 562{ 563 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 564 if (media_player == NULL ) { 565 jniThrowException(env, "java/lang/IllegalStateException", NULL); 566 return false; 567 } 568 569 Parcel *metadata = parcelForJavaObject(env, reply); 570 571 if (metadata == NULL ) { 572 jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null"); 573 return false; 574 } 575 576 metadata->freeData(); 577 // On return metadata is positioned at the beginning of the 578 // metadata. Note however that the parcel actually starts with the 579 // return code so you should not rewind the parcel using 580 // setDataPosition(0). 581 return media_player->getMetadata(update_only, apply_filter, metadata) == OK; 582} 583 584// This function gets some field IDs, which in turn causes class initialization. 585// It is called from a static block in MediaPlayer, which won't run until the 586// first time an instance of this class is used. 587static void 588android_media_MediaPlayer_native_init(JNIEnv *env) 589{ 590 jclass clazz; 591 592 clazz = env->FindClass("android/media/MediaPlayer"); 593 if (clazz == NULL) { 594 return; 595 } 596 597 fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 598 if (fields.context == NULL) { 599 return; 600 } 601 602 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", 603 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 604 if (fields.post_event == NULL) { 605 return; 606 } 607 608 fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "I"); 609 if (fields.surface_texture == NULL) { 610 return; 611 } 612} 613 614static void 615android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) 616{ 617 LOGV("native_setup"); 618 sp<MediaPlayer> mp = new MediaPlayer(); 619 if (mp == NULL) { 620 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 621 return; 622 } 623 624 // create new listener and give it to MediaPlayer 625 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); 626 mp->setListener(listener); 627 628 // Stow our new C++ MediaPlayer in an opaque field in the Java object. 629 setMediaPlayer(env, thiz, mp); 630} 631 632static void 633android_media_MediaPlayer_release(JNIEnv *env, jobject thiz) 634{ 635 LOGV("release"); 636 decVideoSurfaceRef(env, thiz); 637 sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0); 638 if (mp != NULL) { 639 // this prevents native callbacks after the object is released 640 mp->setListener(0); 641 mp->disconnect(); 642 } 643} 644 645static void 646android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) 647{ 648 LOGV("native_finalize"); 649 android_media_MediaPlayer_release(env, thiz); 650} 651 652static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) { 653 LOGV("set_session_id(): %d", sessionId); 654 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 655 if (mp == NULL ) { 656 jniThrowException(env, "java/lang/IllegalStateException", NULL); 657 return; 658 } 659 process_media_player_call( env, thiz, mp->setAudioSessionId(sessionId), NULL, NULL ); 660} 661 662static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) { 663 LOGV("get_session_id()"); 664 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 665 if (mp == NULL ) { 666 jniThrowException(env, "java/lang/IllegalStateException", NULL); 667 return 0; 668 } 669 670 return mp->getAudioSessionId(); 671} 672 673static void 674android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level) 675{ 676 LOGV("setAuxEffectSendLevel: level %f", level); 677 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 678 if (mp == NULL ) { 679 jniThrowException(env, "java/lang/IllegalStateException", NULL); 680 return; 681 } 682 process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL ); 683} 684 685static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz, jint effectId) { 686 LOGV("attachAuxEffect(): %d", effectId); 687 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 688 if (mp == NULL ) { 689 jniThrowException(env, "java/lang/IllegalStateException", NULL); 690 return; 691 } 692 process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL ); 693} 694 695static jint 696android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject java_reply) 697{ 698 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player")); 699 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 700 if (service.get() == NULL) { 701 jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService"); 702 return UNKNOWN_ERROR; 703 } 704 705 Parcel *reply = parcelForJavaObject(env, java_reply); 706 707 return service->pullBatteryData(reply); 708} 709 710static jboolean 711android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request) 712{ 713 LOGV("setParameter: key %d", key); 714 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 715 if (mp == NULL ) { 716 jniThrowException(env, "java/lang/IllegalStateException", NULL); 717 return false; 718 } 719 720 Parcel *request = parcelForJavaObject(env, java_request); 721 status_t err = mp->setParameter(key, *request); 722 if (err == OK) { 723 return true; 724 } else { 725 return false; 726 } 727} 728 729static void 730android_media_MediaPlayer_getParameter(JNIEnv *env, jobject thiz, jint key, jobject java_reply) 731{ 732 LOGV("getParameter: key %d", key); 733 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 734 if (mp == NULL ) { 735 jniThrowException(env, "java/lang/IllegalStateException", NULL); 736 return; 737 } 738 739 Parcel *reply = parcelForJavaObject(env, java_reply); 740 process_media_player_call(env, thiz, mp->getParameter(key, reply), NULL, NULL ); 741} 742 743// ---------------------------------------------------------------------------- 744 745static JNINativeMethod gMethods[] = { 746 {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource}, 747 748 { 749 "_setDataSource", 750 "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", 751 (void *)android_media_MediaPlayer_setDataSourceAndHeaders 752 }, 753 754 {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, 755 {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface}, 756 {"prepare", "()V", (void *)android_media_MediaPlayer_prepare}, 757 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, 758 {"_start", "()V", (void *)android_media_MediaPlayer_start}, 759 {"_stop", "()V", (void *)android_media_MediaPlayer_stop}, 760 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth}, 761 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight}, 762 {"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo}, 763 {"_pause", "()V", (void *)android_media_MediaPlayer_pause}, 764 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying}, 765 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition}, 766 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration}, 767 {"_release", "()V", (void *)android_media_MediaPlayer_release}, 768 {"_reset", "()V", (void *)android_media_MediaPlayer_reset}, 769 {"setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType}, 770 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping}, 771 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping}, 772 {"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume}, 773 {"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt}, 774 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke}, 775 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter}, 776 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata}, 777 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init}, 778 {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup}, 779 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize}, 780 {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id}, 781 {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id}, 782 {"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel}, 783 {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect}, 784 {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData}, 785 {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter}, 786 {"getParameter", "(ILandroid/os/Parcel;)V", (void *)android_media_MediaPlayer_getParameter}, 787}; 788 789static const char* const kClassPathName = "android/media/MediaPlayer"; 790 791// This function only registers the native methods 792static int register_android_media_MediaPlayer(JNIEnv *env) 793{ 794 return AndroidRuntime::registerNativeMethods(env, 795 "android/media/MediaPlayer", gMethods, NELEM(gMethods)); 796} 797 798extern int register_android_media_MediaMetadataRetriever(JNIEnv *env); 799extern int register_android_media_MediaRecorder(JNIEnv *env); 800extern int register_android_media_MediaScanner(JNIEnv *env); 801extern int register_android_media_ResampleInputStream(JNIEnv *env); 802extern int register_android_media_MediaProfiles(JNIEnv *env); 803extern int register_android_media_AmrInputStream(JNIEnv *env); 804extern int register_android_mtp_MtpDatabase(JNIEnv *env); 805extern int register_android_mtp_MtpDevice(JNIEnv *env); 806extern int register_android_mtp_MtpServer(JNIEnv *env); 807 808jint JNI_OnLoad(JavaVM* vm, void* reserved) 809{ 810 JNIEnv* env = NULL; 811 jint result = -1; 812 813 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 814 LOGE("ERROR: GetEnv failed\n"); 815 goto bail; 816 } 817 assert(env != NULL); 818 819 if (register_android_media_MediaPlayer(env) < 0) { 820 LOGE("ERROR: MediaPlayer native registration failed\n"); 821 goto bail; 822 } 823 824 if (register_android_media_MediaRecorder(env) < 0) { 825 LOGE("ERROR: MediaRecorder native registration failed\n"); 826 goto bail; 827 } 828 829 if (register_android_media_MediaScanner(env) < 0) { 830 LOGE("ERROR: MediaScanner native registration failed\n"); 831 goto bail; 832 } 833 834 if (register_android_media_MediaMetadataRetriever(env) < 0) { 835 LOGE("ERROR: MediaMetadataRetriever native registration failed\n"); 836 goto bail; 837 } 838 839 if (register_android_media_AmrInputStream(env) < 0) { 840 LOGE("ERROR: AmrInputStream native registration failed\n"); 841 goto bail; 842 } 843 844 if (register_android_media_ResampleInputStream(env) < 0) { 845 LOGE("ERROR: ResampleInputStream native registration failed\n"); 846 goto bail; 847 } 848 849 if (register_android_media_MediaProfiles(env) < 0) { 850 LOGE("ERROR: MediaProfiles native registration failed"); 851 goto bail; 852 } 853 854 if (register_android_mtp_MtpDatabase(env) < 0) { 855 LOGE("ERROR: MtpDatabase native registration failed"); 856 goto bail; 857 } 858 859 if (register_android_mtp_MtpDevice(env) < 0) { 860 LOGE("ERROR: MtpDevice native registration failed"); 861 goto bail; 862 } 863 864 if (register_android_mtp_MtpServer(env) < 0) { 865 LOGE("ERROR: MtpServer native registration failed"); 866 goto bail; 867 } 868 869 /* success -- return valid version number */ 870 result = JNI_VERSION_1_4; 871 872bail: 873 return result; 874} 875 876// KTHXBYE 877