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