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