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