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