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