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