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