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