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