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