android_media_MediaPlayer.cpp revision 035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117
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/AudioResamplerPublic.h> 24#include <media/IMediaHTTPService.h> 25#include <media/MediaPlayerInterface.h> 26#include <media/MediaAnalyticsItem.h> 27#include <media/stagefright/Utils.h> // for FOURCC definition 28#include <stdio.h> 29#include <assert.h> 30#include <limits.h> 31#include <unistd.h> 32#include <fcntl.h> 33#include <utils/threads.h> 34#include "jni.h" 35#include "JNIHelp.h" 36#include "android_runtime/AndroidRuntime.h" 37#include "android_runtime/android_view_Surface.h" 38#include "android_runtime/Log.h" 39#include "utils/Errors.h" // for status_t 40#include "utils/KeyedVector.h" 41#include "utils/String8.h" 42#include "android_media_BufferingParams.h" 43#include "android_media_MediaDataSource.h" 44#include "android_media_MediaMetricsJNI.h" 45#include "android_media_PlaybackParams.h" 46#include "android_media_SyncParams.h" 47#include "android_media_VolumeShaper.h" 48#include "android_media_Utils.h" 49 50#include "android_os_Parcel.h" 51#include "android_util_Binder.h" 52#include <binder/Parcel.h> 53#include <gui/IGraphicBufferProducer.h> 54#include <gui/Surface.h> 55#include <binder/IPCThreadState.h> 56#include <binder/IServiceManager.h> 57 58#include "android_util_Binder.h" 59 60// Modular DRM begin 61#include <media/drm/DrmAPI.h> 62 63#define FIND_CLASS(var, className) \ 64var = env->FindClass(className); \ 65LOG_FATAL_IF(! (var), "Unable to find class " className); 66 67#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 68var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 69LOG_FATAL_IF(! (var), "Unable to find field " fieldName); 70 71#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ 72var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \ 73LOG_FATAL_IF(! (var), "Unable to find method " fieldName); 74 75#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 76var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \ 77LOG_FATAL_IF(! (var), "Unable to find field " fieldName); 78 79 80// TODO: investigate if these can be shared with their MediaDrm counterparts 81struct RequestFields { 82 jfieldID data; 83 jfieldID defaultUrl; 84 jfieldID requestType; 85}; 86 87struct HashmapFields { 88 jmethodID init; 89 jmethodID get; 90 jmethodID put; 91 jmethodID entrySet; 92}; 93 94struct SetFields { 95 jmethodID iterator; 96}; 97 98struct IteratorFields { 99 jmethodID next; 100 jmethodID hasNext; 101}; 102 103struct EntryFields { 104 jmethodID getKey; 105 jmethodID getValue; 106}; 107 108struct KeyTypes { 109 jint kKeyTypeStreaming; 110 jint kKeyTypeOffline; 111 jint kKeyTypeRelease; 112}; 113 114static KeyTypes gKeyTypes; 115 116struct KeyRequestTypes { 117 jint kKeyRequestTypeInitial; 118 jint kKeyRequestTypeRenewal; 119 jint kKeyRequestTypeRelease; 120}; 121 122static KeyRequestTypes gKeyRequestTypes; 123 124struct StateExceptionFields { 125 jmethodID init; 126 jclass classId; 127}; 128 129struct drm_fields_t { 130 RequestFields keyRequest; 131 HashmapFields hashmap; 132 SetFields set; 133 IteratorFields iterator; 134 EntryFields entry; 135 StateExceptionFields stateException; 136 jclass stringClassId; 137}; 138 139static drm_fields_t gFields; 140 141// Modular DRM end 142 143// ---------------------------------------------------------------------------- 144 145using namespace android; 146 147// ---------------------------------------------------------------------------- 148 149struct fields_t { 150 jfieldID context; 151 jfieldID surface_texture; 152 153 jmethodID post_event; 154 155 jmethodID proxyConfigGetHost; 156 jmethodID proxyConfigGetPort; 157 jmethodID proxyConfigGetExclusionList; 158}; 159static fields_t fields; 160 161static BufferingParams::fields_t gBufferingParamsFields; 162static PlaybackParams::fields_t gPlaybackParamsFields; 163static SyncParams::fields_t gSyncParamsFields; 164static VolumeShaperHelper::fields_t gVolumeShaperFields; 165 166static Mutex sLock; 167 168// ---------------------------------------------------------------------------- 169// ref-counted object for callbacks 170class JNIMediaPlayerListener: public MediaPlayerListener 171{ 172public: 173 JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz); 174 ~JNIMediaPlayerListener(); 175 virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL); 176private: 177 JNIMediaPlayerListener(); 178 jclass mClass; // Reference to MediaPlayer class 179 jobject mObject; // Weak ref to MediaPlayer Java object to call on 180}; 181 182JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz) 183{ 184 185 // Hold onto the MediaPlayer class for use in calling the static method 186 // that posts events to the application thread. 187 jclass clazz = env->GetObjectClass(thiz); 188 if (clazz == NULL) { 189 ALOGE("Can't find android/media/MediaPlayer"); 190 jniThrowException(env, "java/lang/Exception", NULL); 191 return; 192 } 193 mClass = (jclass)env->NewGlobalRef(clazz); 194 195 // We use a weak reference so the MediaPlayer object can be garbage collected. 196 // The reference is only used as a proxy for callbacks. 197 mObject = env->NewGlobalRef(weak_thiz); 198} 199 200JNIMediaPlayerListener::~JNIMediaPlayerListener() 201{ 202 // remove global references 203 JNIEnv *env = AndroidRuntime::getJNIEnv(); 204 env->DeleteGlobalRef(mObject); 205 env->DeleteGlobalRef(mClass); 206} 207 208void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj) 209{ 210 JNIEnv *env = AndroidRuntime::getJNIEnv(); 211 if (obj && obj->dataSize() > 0) { 212 jobject jParcel = createJavaParcelObject(env); 213 if (jParcel != NULL) { 214 Parcel* nativeParcel = parcelForJavaObject(env, jParcel); 215 nativeParcel->setData(obj->data(), obj->dataSize()); 216 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, 217 msg, ext1, ext2, jParcel); 218 env->DeleteLocalRef(jParcel); 219 } 220 } else { 221 env->CallStaticVoidMethod(mClass, fields.post_event, mObject, 222 msg, ext1, ext2, NULL); 223 } 224 if (env->ExceptionCheck()) { 225 ALOGW("An exception occurred while notifying an event."); 226 LOGW_EX(env); 227 env->ExceptionClear(); 228 } 229} 230 231// ---------------------------------------------------------------------------- 232 233static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) 234{ 235 Mutex::Autolock l(sLock); 236 MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context); 237 return sp<MediaPlayer>(p); 238} 239 240static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player) 241{ 242 Mutex::Autolock l(sLock); 243 sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context); 244 if (player.get()) { 245 player->incStrong((void*)setMediaPlayer); 246 } 247 if (old != 0) { 248 old->decStrong((void*)setMediaPlayer); 249 } 250 env->SetLongField(thiz, fields.context, (jlong)player.get()); 251 return old; 252} 253 254// If exception is NULL and opStatus is not OK, this method sends an error 255// event to the client application; otherwise, if exception is not NULL and 256// opStatus is not OK, this method throws the given exception to the client 257// application. 258static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message) 259{ 260 if (exception == NULL) { // Don't throw exception. Instead, send an event. 261 if (opStatus != (status_t) OK) { 262 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 263 if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0); 264 } 265 } else { // Throw exception! 266 if ( opStatus == (status_t) INVALID_OPERATION ) { 267 jniThrowException(env, "java/lang/IllegalStateException", NULL); 268 } else if ( opStatus == (status_t) BAD_VALUE ) { 269 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 270 } else if ( opStatus == (status_t) PERMISSION_DENIED ) { 271 jniThrowException(env, "java/lang/SecurityException", NULL); 272 } else if ( opStatus != (status_t) OK ) { 273 if (strlen(message) > 230) { 274 // if the message is too long, don't bother displaying the status code 275 jniThrowException( env, exception, message); 276 } else { 277 char msg[256]; 278 // append the status code to the message 279 sprintf(msg, "%s: status=0x%X", message, opStatus); 280 jniThrowException( env, exception, msg); 281 } 282 } 283 } 284} 285 286static void 287android_media_MediaPlayer_setDataSourceAndHeaders( 288 JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path, 289 jobjectArray keys, jobjectArray values) { 290 291 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 292 if (mp == NULL ) { 293 jniThrowException(env, "java/lang/IllegalStateException", NULL); 294 return; 295 } 296 297 if (path == NULL) { 298 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 299 return; 300 } 301 302 const char *tmp = env->GetStringUTFChars(path, NULL); 303 if (tmp == NULL) { // Out of memory 304 return; 305 } 306 ALOGV("setDataSource: path %s", tmp); 307 308 String8 pathStr(tmp); 309 env->ReleaseStringUTFChars(path, tmp); 310 tmp = NULL; 311 312 // We build a KeyedVector out of the key and val arrays 313 KeyedVector<String8, String8> headersVector; 314 if (!ConvertKeyValueArraysToKeyedVector( 315 env, keys, values, &headersVector)) { 316 return; 317 } 318 319 sp<IMediaHTTPService> httpService; 320 if (httpServiceBinderObj != NULL) { 321 sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj); 322 httpService = interface_cast<IMediaHTTPService>(binder); 323 } 324 325 status_t opStatus = 326 mp->setDataSource( 327 httpService, 328 pathStr, 329 headersVector.size() > 0? &headersVector : NULL); 330 331 process_media_player_call( 332 env, thiz, opStatus, "java/io/IOException", 333 "setDataSource failed." ); 334} 335 336static void 337android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) 338{ 339 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 340 if (mp == NULL ) { 341 jniThrowException(env, "java/lang/IllegalStateException", NULL); 342 return; 343 } 344 345 if (fileDescriptor == NULL) { 346 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 347 return; 348 } 349 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 350 ALOGV("setDataSourceFD: fd %d", fd); 351 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); 352} 353 354static void 355android_media_MediaPlayer_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource) 356{ 357 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 358 if (mp == NULL ) { 359 jniThrowException(env, "java/lang/IllegalStateException", NULL); 360 return; 361 } 362 363 if (dataSource == NULL) { 364 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 365 return; 366 } 367 sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource); 368 process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." ); 369} 370 371static sp<IGraphicBufferProducer> 372getVideoSurfaceTexture(JNIEnv* env, jobject thiz) { 373 IGraphicBufferProducer * const p = (IGraphicBufferProducer*)env->GetLongField(thiz, fields.surface_texture); 374 return sp<IGraphicBufferProducer>(p); 375} 376 377static void 378decVideoSurfaceRef(JNIEnv *env, jobject thiz) 379{ 380 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 381 if (mp == NULL) { 382 return; 383 } 384 385 sp<IGraphicBufferProducer> old_st = getVideoSurfaceTexture(env, thiz); 386 if (old_st != NULL) { 387 old_st->decStrong((void*)decVideoSurfaceRef); 388 } 389} 390 391static void 392setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive) 393{ 394 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 395 if (mp == NULL) { 396 if (mediaPlayerMustBeAlive) { 397 jniThrowException(env, "java/lang/IllegalStateException", NULL); 398 } 399 return; 400 } 401 402 decVideoSurfaceRef(env, thiz); 403 404 sp<IGraphicBufferProducer> new_st; 405 if (jsurface) { 406 sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 407 if (surface != NULL) { 408 new_st = surface->getIGraphicBufferProducer(); 409 if (new_st == NULL) { 410 jniThrowException(env, "java/lang/IllegalArgumentException", 411 "The surface does not have a binding SurfaceTexture!"); 412 return; 413 } 414 new_st->incStrong((void*)decVideoSurfaceRef); 415 } else { 416 jniThrowException(env, "java/lang/IllegalArgumentException", 417 "The surface has been released"); 418 return; 419 } 420 } 421 422 env->SetLongField(thiz, fields.surface_texture, (jlong)new_st.get()); 423 424 // This will fail if the media player has not been initialized yet. This 425 // can be the case if setDisplay() on MediaPlayer.java has been called 426 // before setDataSource(). The redundant call to setVideoSurfaceTexture() 427 // in prepare/prepareAsync covers for this case. 428 mp->setVideoSurfaceTexture(new_st); 429} 430 431static void 432android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface) 433{ 434 setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */); 435} 436 437static jobject 438android_media_MediaPlayer_getDefaultBufferingParams(JNIEnv *env, jobject thiz) 439{ 440 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 441 if (mp == NULL) { 442 jniThrowException(env, "java/lang/IllegalStateException", NULL); 443 return NULL; 444 } 445 446 BufferingParams bp; 447 BufferingSettings &settings = bp.settings; 448 process_media_player_call( 449 env, thiz, mp->getDefaultBufferingSettings(&settings), 450 "java/lang/IllegalStateException", "unexpected error"); 451 ALOGV("getDefaultBufferingSettings:{%s}", settings.toString().string()); 452 453 return bp.asJobject(env, gBufferingParamsFields); 454} 455 456static jobject 457android_media_MediaPlayer_getBufferingParams(JNIEnv *env, jobject thiz) 458{ 459 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 460 if (mp == NULL) { 461 jniThrowException(env, "java/lang/IllegalStateException", NULL); 462 return NULL; 463 } 464 465 BufferingParams bp; 466 BufferingSettings &settings = bp.settings; 467 process_media_player_call( 468 env, thiz, mp->getBufferingSettings(&settings), 469 "java/lang/IllegalStateException", "unexpected error"); 470 ALOGV("getBufferingSettings:{%s}", settings.toString().string()); 471 472 return bp.asJobject(env, gBufferingParamsFields); 473} 474 475static void 476android_media_MediaPlayer_setBufferingParams(JNIEnv *env, jobject thiz, jobject params) 477{ 478 if (params == NULL) { 479 return; 480 } 481 482 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 483 if (mp == NULL) { 484 jniThrowException(env, "java/lang/IllegalStateException", NULL); 485 return; 486 } 487 488 BufferingParams bp; 489 bp.fillFromJobject(env, gBufferingParamsFields, params); 490 ALOGV("setBufferingParams:{%s}", bp.settings.toString().string()); 491 492 process_media_player_call( 493 env, thiz, mp->setBufferingSettings(bp.settings), 494 "java/lang/IllegalStateException", "unexpected error"); 495} 496 497static void 498android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) 499{ 500 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 501 if (mp == NULL ) { 502 jniThrowException(env, "java/lang/IllegalStateException", NULL); 503 return; 504 } 505 506 // Handle the case where the display surface was set before the mp was 507 // initialized. We try again to make it stick. 508 sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz); 509 mp->setVideoSurfaceTexture(st); 510 511 process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." ); 512} 513 514static void 515android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz) 516{ 517 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 518 if (mp == NULL ) { 519 jniThrowException(env, "java/lang/IllegalStateException", NULL); 520 return; 521 } 522 523 // Handle the case where the display surface was set before the mp was 524 // initialized. We try again to make it stick. 525 sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz); 526 mp->setVideoSurfaceTexture(st); 527 528 process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." ); 529} 530 531static void 532android_media_MediaPlayer_start(JNIEnv *env, jobject thiz) 533{ 534 ALOGV("start"); 535 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 536 if (mp == NULL ) { 537 jniThrowException(env, "java/lang/IllegalStateException", NULL); 538 return; 539 } 540 process_media_player_call( env, thiz, mp->start(), NULL, NULL ); 541} 542 543static void 544android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz) 545{ 546 ALOGV("stop"); 547 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 548 if (mp == NULL ) { 549 jniThrowException(env, "java/lang/IllegalStateException", NULL); 550 return; 551 } 552 process_media_player_call( env, thiz, mp->stop(), NULL, NULL ); 553} 554 555static void 556android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz) 557{ 558 ALOGV("pause"); 559 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 560 if (mp == NULL ) { 561 jniThrowException(env, "java/lang/IllegalStateException", NULL); 562 return; 563 } 564 process_media_player_call( env, thiz, mp->pause(), NULL, NULL ); 565} 566 567static jboolean 568android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz) 569{ 570 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 571 if (mp == NULL ) { 572 jniThrowException(env, "java/lang/IllegalStateException", NULL); 573 return JNI_FALSE; 574 } 575 const jboolean is_playing = mp->isPlaying(); 576 577 ALOGV("isPlaying: %d", is_playing); 578 return is_playing; 579} 580 581static void 582android_media_MediaPlayer_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params) 583{ 584 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 585 if (mp == NULL) { 586 jniThrowException(env, "java/lang/IllegalStateException", NULL); 587 return; 588 } 589 590 PlaybackParams pbp; 591 pbp.fillFromJobject(env, gPlaybackParamsFields, params); 592 ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u", 593 pbp.speedSet, pbp.audioRate.mSpeed, 594 pbp.pitchSet, pbp.audioRate.mPitch, 595 pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode, 596 pbp.audioStretchModeSet, pbp.audioRate.mStretchMode); 597 598 AudioPlaybackRate rate; 599 status_t err = mp->getPlaybackSettings(&rate); 600 if (err == OK) { 601 bool updatedRate = false; 602 if (pbp.speedSet) { 603 rate.mSpeed = pbp.audioRate.mSpeed; 604 updatedRate = true; 605 } 606 if (pbp.pitchSet) { 607 rate.mPitch = pbp.audioRate.mPitch; 608 updatedRate = true; 609 } 610 if (pbp.audioFallbackModeSet) { 611 rate.mFallbackMode = pbp.audioRate.mFallbackMode; 612 updatedRate = true; 613 } 614 if (pbp.audioStretchModeSet) { 615 rate.mStretchMode = pbp.audioRate.mStretchMode; 616 updatedRate = true; 617 } 618 if (updatedRate) { 619 err = mp->setPlaybackSettings(rate); 620 } 621 } 622 process_media_player_call( 623 env, thiz, err, 624 "java/lang/IllegalStateException", "unexpected error"); 625} 626 627static jobject 628android_media_MediaPlayer_getPlaybackParams(JNIEnv *env, jobject thiz) 629{ 630 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 631 if (mp == NULL) { 632 jniThrowException(env, "java/lang/IllegalStateException", NULL); 633 return NULL; 634 } 635 636 PlaybackParams pbp; 637 AudioPlaybackRate &audioRate = pbp.audioRate; 638 process_media_player_call( 639 env, thiz, mp->getPlaybackSettings(&audioRate), 640 "java/lang/IllegalStateException", "unexpected error"); 641 ALOGV("getPlaybackSettings: %f %f %d %d", 642 audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode); 643 644 pbp.speedSet = true; 645 pbp.pitchSet = true; 646 pbp.audioFallbackModeSet = true; 647 pbp.audioStretchModeSet = true; 648 649 return pbp.asJobject(env, gPlaybackParamsFields); 650} 651 652static void 653android_media_MediaPlayer_setSyncParams(JNIEnv *env, jobject thiz, jobject params) 654{ 655 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 656 if (mp == NULL) { 657 jniThrowException(env, "java/lang/IllegalStateException", NULL); 658 return; 659 } 660 661 SyncParams scp; 662 scp.fillFromJobject(env, gSyncParamsFields, params); 663 ALOGV("setSyncParams: %d:%d %d:%d %d:%f %d:%f", 664 scp.syncSourceSet, scp.sync.mSource, 665 scp.audioAdjustModeSet, scp.sync.mAudioAdjustMode, 666 scp.toleranceSet, scp.sync.mTolerance, 667 scp.frameRateSet, scp.frameRate); 668 669 AVSyncSettings avsync; 670 float videoFrameRate; 671 status_t err = mp->getSyncSettings(&avsync, &videoFrameRate); 672 if (err == OK) { 673 bool updatedSync = scp.frameRateSet; 674 if (scp.syncSourceSet) { 675 avsync.mSource = scp.sync.mSource; 676 updatedSync = true; 677 } 678 if (scp.audioAdjustModeSet) { 679 avsync.mAudioAdjustMode = scp.sync.mAudioAdjustMode; 680 updatedSync = true; 681 } 682 if (scp.toleranceSet) { 683 avsync.mTolerance = scp.sync.mTolerance; 684 updatedSync = true; 685 } 686 if (updatedSync) { 687 err = mp->setSyncSettings(avsync, scp.frameRateSet ? scp.frameRate : -1.f); 688 } 689 } 690 process_media_player_call( 691 env, thiz, err, 692 "java/lang/IllegalStateException", "unexpected error"); 693} 694 695static jobject 696android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz) 697{ 698 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 699 if (mp == NULL) { 700 jniThrowException(env, "java/lang/IllegalStateException", NULL); 701 return NULL; 702 } 703 704 SyncParams scp; 705 scp.frameRate = -1.f; 706 process_media_player_call( 707 env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate), 708 "java/lang/IllegalStateException", "unexpected error"); 709 710 ALOGV("getSyncSettings: %d %d %f %f", 711 scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate); 712 713 // sanity check params 714 if (scp.sync.mSource >= AVSYNC_SOURCE_MAX 715 || scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX 716 || scp.sync.mTolerance < 0.f 717 || scp.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) { 718 jniThrowException(env, "java/lang/IllegalStateException", NULL); 719 return NULL; 720 } 721 722 scp.syncSourceSet = true; 723 scp.audioAdjustModeSet = true; 724 scp.toleranceSet = true; 725 scp.frameRateSet = scp.frameRate >= 0.f; 726 727 return scp.asJobject(env, gSyncParamsFields); 728} 729 730static void 731android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jint msec, jint mode) 732{ 733 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 734 if (mp == NULL ) { 735 jniThrowException(env, "java/lang/IllegalStateException", NULL); 736 return; 737 } 738 ALOGV("seekTo: %d(msec), mode=%d", msec, mode); 739 process_media_player_call( env, thiz, mp->seekTo(msec, (MediaPlayerSeekMode)mode), NULL, NULL ); 740} 741 742static jint 743android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz) 744{ 745 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 746 if (mp == NULL ) { 747 jniThrowException(env, "java/lang/IllegalStateException", NULL); 748 return 0; 749 } 750 int w; 751 if (0 != mp->getVideoWidth(&w)) { 752 ALOGE("getVideoWidth failed"); 753 w = 0; 754 } 755 ALOGV("getVideoWidth: %d", w); 756 return (jint) w; 757} 758 759static jint 760android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz) 761{ 762 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 763 if (mp == NULL ) { 764 jniThrowException(env, "java/lang/IllegalStateException", NULL); 765 return 0; 766 } 767 int h; 768 if (0 != mp->getVideoHeight(&h)) { 769 ALOGE("getVideoHeight failed"); 770 h = 0; 771 } 772 ALOGV("getVideoHeight: %d", h); 773 return (jint) h; 774} 775 776static jobject 777android_media_MediaPlayer_getMetrics(JNIEnv *env, jobject thiz) 778{ 779 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 780 if (mp == NULL ) { 781 jniThrowException(env, "java/lang/IllegalStateException", NULL); 782 return 0; 783 } 784 785 Parcel p; 786 int key = FOURCC('m','t','r','X'); 787 status_t status = mp->getParameter(key, &p); 788 if (status != OK) { 789 ALOGD("getMetrics() failed: %d", status); 790 return (jobject) NULL; 791 } 792 793 MediaAnalyticsItem *item = new MediaAnalyticsItem; 794 item->readFromParcel(p); 795 jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL); 796 797 // housekeeping 798 delete item; 799 item = NULL; 800 801 return mybundle; 802} 803 804static jint 805android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz) 806{ 807 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 808 if (mp == NULL ) { 809 jniThrowException(env, "java/lang/IllegalStateException", NULL); 810 return 0; 811 } 812 int msec; 813 process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL ); 814 ALOGV("getCurrentPosition: %d (msec)", msec); 815 return (jint) msec; 816} 817 818static jint 819android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz) 820{ 821 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 822 if (mp == NULL ) { 823 jniThrowException(env, "java/lang/IllegalStateException", NULL); 824 return 0; 825 } 826 int msec; 827 process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL ); 828 ALOGV("getDuration: %d (msec)", msec); 829 return (jint) msec; 830} 831 832static void 833android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz) 834{ 835 ALOGV("reset"); 836 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 837 if (mp == NULL ) { 838 jniThrowException(env, "java/lang/IllegalStateException", NULL); 839 return; 840 } 841 process_media_player_call( env, thiz, mp->reset(), NULL, NULL ); 842} 843 844static void 845android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, jint streamtype) 846{ 847 ALOGV("setAudioStreamType: %d", streamtype); 848 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 849 if (mp == NULL ) { 850 jniThrowException(env, "java/lang/IllegalStateException", NULL); 851 return; 852 } 853 process_media_player_call( env, thiz, mp->setAudioStreamType((audio_stream_type_t) streamtype) , NULL, NULL ); 854} 855 856static jint 857android_media_MediaPlayer_getAudioStreamType(JNIEnv *env, jobject thiz) 858{ 859 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 860 if (mp == NULL ) { 861 jniThrowException(env, "java/lang/IllegalStateException", NULL); 862 return 0; 863 } 864 audio_stream_type_t streamtype; 865 process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL ); 866 ALOGV("getAudioStreamType: %d (streamtype)", streamtype); 867 return (jint) streamtype; 868} 869 870static jboolean 871android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request) 872{ 873 ALOGV("setParameter: key %d", key); 874 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 875 if (mp == NULL ) { 876 jniThrowException(env, "java/lang/IllegalStateException", NULL); 877 return false; 878 } 879 880 Parcel *request = parcelForJavaObject(env, java_request); 881 status_t err = mp->setParameter(key, *request); 882 if (err == OK) { 883 return true; 884 } else { 885 return false; 886 } 887} 888 889static void 890android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping) 891{ 892 ALOGV("setLooping: %d", looping); 893 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 894 if (mp == NULL ) { 895 jniThrowException(env, "java/lang/IllegalStateException", NULL); 896 return; 897 } 898 process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL ); 899} 900 901static jboolean 902android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz) 903{ 904 ALOGV("isLooping"); 905 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 906 if (mp == NULL ) { 907 jniThrowException(env, "java/lang/IllegalStateException", NULL); 908 return JNI_FALSE; 909 } 910 return mp->isLooping() ? JNI_TRUE : JNI_FALSE; 911} 912 913static void 914android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, jfloat leftVolume, jfloat rightVolume) 915{ 916 ALOGV("setVolume: left %f right %f", (float) leftVolume, (float) rightVolume); 917 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 918 if (mp == NULL ) { 919 jniThrowException(env, "java/lang/IllegalStateException", NULL); 920 return; 921 } 922 process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL ); 923} 924 925// Sends the request and reply parcels to the media player via the 926// binder interface. 927static jint 928android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz, 929 jobject java_request, jobject java_reply) 930{ 931 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 932 if (media_player == NULL ) { 933 jniThrowException(env, "java/lang/IllegalStateException", NULL); 934 return UNKNOWN_ERROR; 935 } 936 937 Parcel *request = parcelForJavaObject(env, java_request); 938 Parcel *reply = parcelForJavaObject(env, java_reply); 939 940 // Don't use process_media_player_call which use the async loop to 941 // report errors, instead returns the status. 942 return (jint) media_player->invoke(*request, reply); 943} 944 945// Sends the new filter to the client. 946static jint 947android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request) 948{ 949 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 950 if (media_player == NULL ) { 951 jniThrowException(env, "java/lang/IllegalStateException", NULL); 952 return UNKNOWN_ERROR; 953 } 954 955 Parcel *filter = parcelForJavaObject(env, request); 956 957 if (filter == NULL ) { 958 jniThrowException(env, "java/lang/RuntimeException", "Filter is null"); 959 return UNKNOWN_ERROR; 960 } 961 962 return (jint) media_player->setMetadataFilter(*filter); 963} 964 965static jboolean 966android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only, 967 jboolean apply_filter, jobject reply) 968{ 969 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz); 970 if (media_player == NULL ) { 971 jniThrowException(env, "java/lang/IllegalStateException", NULL); 972 return JNI_FALSE; 973 } 974 975 Parcel *metadata = parcelForJavaObject(env, reply); 976 977 if (metadata == NULL ) { 978 jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null"); 979 return JNI_FALSE; 980 } 981 982 metadata->freeData(); 983 // On return metadata is positioned at the beginning of the 984 // metadata. Note however that the parcel actually starts with the 985 // return code so you should not rewind the parcel using 986 // setDataPosition(0). 987 if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) { 988 return JNI_TRUE; 989 } else { 990 return JNI_FALSE; 991 } 992} 993 994// This function gets some field IDs, which in turn causes class initialization. 995// It is called from a static block in MediaPlayer, which won't run until the 996// first time an instance of this class is used. 997static void 998android_media_MediaPlayer_native_init(JNIEnv *env) 999{ 1000 jclass clazz; 1001 1002 clazz = env->FindClass("android/media/MediaPlayer"); 1003 if (clazz == NULL) { 1004 return; 1005 } 1006 1007 fields.context = env->GetFieldID(clazz, "mNativeContext", "J"); 1008 if (fields.context == NULL) { 1009 return; 1010 } 1011 1012 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", 1013 "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 1014 if (fields.post_event == NULL) { 1015 return; 1016 } 1017 1018 fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "J"); 1019 if (fields.surface_texture == NULL) { 1020 return; 1021 } 1022 1023 env->DeleteLocalRef(clazz); 1024 1025 clazz = env->FindClass("android/net/ProxyInfo"); 1026 if (clazz == NULL) { 1027 return; 1028 } 1029 1030 fields.proxyConfigGetHost = 1031 env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;"); 1032 1033 fields.proxyConfigGetPort = 1034 env->GetMethodID(clazz, "getPort", "()I"); 1035 1036 fields.proxyConfigGetExclusionList = 1037 env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;"); 1038 1039 env->DeleteLocalRef(clazz); 1040 1041 gBufferingParamsFields.init(env); 1042 1043 // Modular DRM 1044 FIND_CLASS(clazz, "android/media/MediaDrm"); 1045 if (clazz) { 1046 jfieldID field; 1047 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I"); 1048 gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field); 1049 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I"); 1050 gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field); 1051 GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I"); 1052 gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field); 1053 1054 env->DeleteLocalRef(clazz); 1055 } else { 1056 ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't " 1057 "get clazz android/media/MediaDrm"); 1058 } 1059 1060 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); 1061 if (clazz) { 1062 GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B"); 1063 GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;"); 1064 GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I"); 1065 1066 jfieldID field; 1067 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I"); 1068 gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field); 1069 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I"); 1070 gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field); 1071 GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I"); 1072 gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field); 1073 1074 env->DeleteLocalRef(clazz); 1075 } else { 1076 ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't " 1077 "get clazz android/media/MediaDrm$KeyRequest"); 1078 } 1079 1080 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException"); 1081 if (clazz) { 1082 GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V"); 1083 gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz)); 1084 1085 env->DeleteLocalRef(clazz); 1086 } else { 1087 ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't " 1088 "get clazz android/media/MediaDrm$MediaDrmStateException"); 1089 } 1090 1091 gPlaybackParamsFields.init(env); 1092 gSyncParamsFields.init(env); 1093 gVolumeShaperFields.init(env); 1094} 1095 1096static void 1097android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) 1098{ 1099 ALOGV("native_setup"); 1100 sp<MediaPlayer> mp = new MediaPlayer(); 1101 if (mp == NULL) { 1102 jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); 1103 return; 1104 } 1105 1106 // create new listener and give it to MediaPlayer 1107 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); 1108 mp->setListener(listener); 1109 1110 // Stow our new C++ MediaPlayer in an opaque field in the Java object. 1111 setMediaPlayer(env, thiz, mp); 1112} 1113 1114static void 1115android_media_MediaPlayer_release(JNIEnv *env, jobject thiz) 1116{ 1117 ALOGV("release"); 1118 decVideoSurfaceRef(env, thiz); 1119 sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0); 1120 if (mp != NULL) { 1121 // this prevents native callbacks after the object is released 1122 mp->setListener(0); 1123 mp->disconnect(); 1124 } 1125} 1126 1127static void 1128android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) 1129{ 1130 ALOGV("native_finalize"); 1131 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1132 if (mp != NULL) { 1133 ALOGW("MediaPlayer finalized without being released"); 1134 } 1135 android_media_MediaPlayer_release(env, thiz); 1136} 1137 1138static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, 1139 jint sessionId) { 1140 ALOGV("set_session_id(): %d", sessionId); 1141 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1142 if (mp == NULL ) { 1143 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1144 return; 1145 } 1146 process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL, 1147 NULL); 1148} 1149 1150static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) { 1151 ALOGV("get_session_id()"); 1152 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1153 if (mp == NULL ) { 1154 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1155 return 0; 1156 } 1157 1158 return (jint) mp->getAudioSessionId(); 1159} 1160 1161static void 1162android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level) 1163{ 1164 ALOGV("setAuxEffectSendLevel: level %f", level); 1165 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1166 if (mp == NULL ) { 1167 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1168 return; 1169 } 1170 process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL ); 1171} 1172 1173static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz, jint effectId) { 1174 ALOGV("attachAuxEffect(): %d", effectId); 1175 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1176 if (mp == NULL ) { 1177 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1178 return; 1179 } 1180 process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL ); 1181} 1182 1183static jint 1184android_media_MediaPlayer_pullBatteryData( 1185 JNIEnv *env, jobject /* thiz */, jobject java_reply) 1186{ 1187 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player")); 1188 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 1189 if (service.get() == NULL) { 1190 jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService"); 1191 return UNKNOWN_ERROR; 1192 } 1193 1194 Parcel *reply = parcelForJavaObject(env, java_reply); 1195 1196 return (jint) service->pullBatteryData(reply); 1197} 1198 1199static jint 1200android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz, 1201 jstring addrString, jint port) { 1202 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1203 if (mp == NULL ) { 1204 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1205 return INVALID_OPERATION; 1206 } 1207 1208 const char *cAddrString = NULL; 1209 1210 if (NULL != addrString) { 1211 cAddrString = env->GetStringUTFChars(addrString, NULL); 1212 if (cAddrString == NULL) { // Out of memory 1213 return NO_MEMORY; 1214 } 1215 } 1216 ALOGV("setRetransmitEndpoint: %s:%d", 1217 cAddrString ? cAddrString : "(null)", port); 1218 1219 status_t ret; 1220 if (cAddrString && (port > 0xFFFF)) { 1221 ret = BAD_VALUE; 1222 } else { 1223 ret = mp->setRetransmitEndpoint(cAddrString, 1224 static_cast<uint16_t>(port)); 1225 } 1226 1227 if (NULL != addrString) { 1228 env->ReleaseStringUTFChars(addrString, cAddrString); 1229 } 1230 1231 if (ret == INVALID_OPERATION ) { 1232 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1233 } 1234 1235 return (jint) ret; 1236} 1237 1238static void 1239android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player) 1240{ 1241 ALOGV("setNextMediaPlayer"); 1242 sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz); 1243 if (thisplayer == NULL) { 1244 jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized"); 1245 return; 1246 } 1247 sp<MediaPlayer> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player); 1248 if (nextplayer == NULL && java_player != NULL) { 1249 jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized"); 1250 return; 1251 } 1252 1253 if (nextplayer == thisplayer) { 1254 jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self"); 1255 return; 1256 } 1257 // tie the two players together 1258 process_media_player_call( 1259 env, thiz, thisplayer->setNextMediaPlayer(nextplayer), 1260 "java/lang/IllegalArgumentException", 1261 "setNextMediaPlayer failed." ); 1262 ; 1263} 1264 1265// Pass through the arguments to the MediaServer player implementation. 1266static jint android_media_MediaPlayer_applyVolumeShaper(JNIEnv *env, jobject thiz, 1267 jobject jconfig, jobject joperation) { 1268 // NOTE: hard code here to prevent platform issues. Must match VolumeShaper.java 1269 const int VOLUME_SHAPER_INVALID_OPERATION = -38; 1270 1271 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1272 if (mp == nullptr) { 1273 return (jint)VOLUME_SHAPER_INVALID_OPERATION; 1274 } 1275 1276 sp<VolumeShaper::Configuration> configuration; 1277 sp<VolumeShaper::Operation> operation; 1278 if (jconfig != nullptr) { 1279 configuration = VolumeShaperHelper::convertJobjectToConfiguration( 1280 env, gVolumeShaperFields, jconfig); 1281 ALOGV("applyVolumeShaper configuration: %s", configuration->toString().c_str()); 1282 } 1283 if (joperation != nullptr) { 1284 operation = VolumeShaperHelper::convertJobjectToOperation( 1285 env, gVolumeShaperFields, joperation); 1286 ALOGV("applyVolumeShaper operation: %s", operation->toString().c_str()); 1287 } 1288 VolumeShaper::Status status = mp->applyVolumeShaper(configuration, operation); 1289 if (status == INVALID_OPERATION) { 1290 status = VOLUME_SHAPER_INVALID_OPERATION; 1291 } 1292 return (jint)status; // if status < 0 an error, else a VolumeShaper id 1293} 1294 1295// Pass through the arguments to the MediaServer player implementation. 1296static jobject android_media_MediaPlayer_getVolumeShaperState(JNIEnv *env, jobject thiz, 1297 jint id) { 1298 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1299 if (mp == nullptr) { 1300 return (jobject)nullptr; 1301 } 1302 1303 sp<VolumeShaper::State> state = mp->getVolumeShaperState((int)id); 1304 if (state.get() == nullptr) { 1305 return (jobject)nullptr; 1306 } 1307 return VolumeShaperHelper::convertStateToJobject(env, gVolumeShaperFields, state); 1308} 1309 1310///////////////////////////////////////////////////////////////////////////////////// 1311// Modular DRM begin 1312 1313// TODO: investigate if these can be shared with their MediaDrm counterparts 1314static void throwDrmStateException(JNIEnv *env, const char *msg, status_t err) 1315{ 1316 ALOGE("Illegal DRM state exception: %s (%d)", msg, err); 1317 1318 jobject exception = env->NewObject(gFields.stateException.classId, 1319 gFields.stateException.init, static_cast<int>(err), 1320 env->NewStringUTF(msg)); 1321 env->Throw(static_cast<jthrowable>(exception)); 1322} 1323 1324// TODO: investigate if these can be shared with their MediaDrm counterparts 1325static bool throwDrmExceptionAsNecessary(JNIEnv *env, status_t err, const char *msg = NULL) 1326{ 1327 const char *drmMessage = "Unknown DRM Msg"; 1328 1329 switch (err) { 1330 case ERROR_DRM_UNKNOWN: 1331 drmMessage = "General DRM error"; 1332 break; 1333 case ERROR_DRM_NO_LICENSE: 1334 drmMessage = "No license"; 1335 break; 1336 case ERROR_DRM_LICENSE_EXPIRED: 1337 drmMessage = "License expired"; 1338 break; 1339 case ERROR_DRM_SESSION_NOT_OPENED: 1340 drmMessage = "Session not opened"; 1341 break; 1342 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED: 1343 drmMessage = "Not initialized"; 1344 break; 1345 case ERROR_DRM_DECRYPT: 1346 drmMessage = "Decrypt error"; 1347 break; 1348 case ERROR_DRM_CANNOT_HANDLE: 1349 drmMessage = "Unsupported scheme or data format"; 1350 break; 1351 case ERROR_DRM_TAMPER_DETECTED: 1352 drmMessage = "Invalid state"; 1353 break; 1354 default: 1355 break; 1356 } 1357 1358 String8 vendorMessage; 1359 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) { 1360 vendorMessage = String8::format("DRM vendor-defined error: %d", err); 1361 drmMessage = vendorMessage.string(); 1362 } 1363 1364 if (err == BAD_VALUE) { 1365 jniThrowException(env, "java/lang/IllegalArgumentException", msg); 1366 return true; 1367 } else if (err == ERROR_DRM_NOT_PROVISIONED) { 1368 jniThrowException(env, "android/media/NotProvisionedException", msg); 1369 return true; 1370 } else if (err == ERROR_DRM_RESOURCE_BUSY) { 1371 jniThrowException(env, "android/media/ResourceBusyException", msg); 1372 return true; 1373 } else if (err == ERROR_DRM_DEVICE_REVOKED) { 1374 jniThrowException(env, "android/media/DeniedByServerException", msg); 1375 return true; 1376 } else if (err == DEAD_OBJECT) { 1377 jniThrowException(env, "android/media/MediaDrmResetException", 1378 "mediaserver died"); 1379 return true; 1380 } else if (err != OK) { 1381 String8 errbuf; 1382 if (drmMessage != NULL) { 1383 if (msg == NULL) { 1384 msg = drmMessage; 1385 } else { 1386 errbuf = String8::format("%s: %s", msg, drmMessage); 1387 msg = errbuf.string(); 1388 } 1389 } 1390 throwDrmStateException(env, msg, err); 1391 return true; 1392 } 1393 return false; 1394} 1395 1396// TODO: investigate if these can be shared with their MediaDrm counterparts 1397static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector) 1398{ 1399 size_t length = vector.size(); 1400 jbyteArray result = env->NewByteArray(length); 1401 if (result != NULL) { 1402 env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array()); 1403 } 1404 return result; 1405} 1406 1407// TODO: investigate if these can be shared with their MediaDrm counterparts 1408static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray) 1409{ 1410 Vector<uint8_t> vector; 1411 size_t length = env->GetArrayLength(byteArray); 1412 vector.insertAt((size_t)0, length); 1413 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray()); 1414 return vector; 1415} 1416 1417// TODO: investigate if these can be shared with their MediaDrm counterparts 1418static String8 JStringToString8(JNIEnv *env, jstring const &jstr) 1419{ 1420 String8 result; 1421 1422 const char *s = env->GetStringUTFChars(jstr, NULL); 1423 if (s) { 1424 result = s; 1425 env->ReleaseStringUTFChars(jstr, s); 1426 } 1427 return result; 1428} 1429 1430// TODO: investigate if these can be shared with their MediaDrm counterparts 1431static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, 1432 jobject &hashMap, bool* pIsOK) 1433{ 1434 jclass clazz = gFields.stringClassId; 1435 KeyedVector<String8, String8> keyedVector; 1436 *pIsOK = true; 1437 1438 jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet); 1439 if (entrySet) { 1440 jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator); 1441 if (iterator) { 1442 jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 1443 while (hasNext) { 1444 jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next); 1445 if (entry) { 1446 jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey); 1447 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) { 1448 jniThrowException(env, "java/lang/IllegalArgumentException", 1449 "HashMap key is not a String"); 1450 env->DeleteLocalRef(entry); 1451 *pIsOK = false; 1452 break; 1453 } 1454 jstring jkey = static_cast<jstring>(obj); 1455 1456 obj = env->CallObjectMethod(entry, gFields.entry.getValue); 1457 if (obj == NULL || !env->IsInstanceOf(obj, clazz)) { 1458 jniThrowException(env, "java/lang/IllegalArgumentException", 1459 "HashMap value is not a String"); 1460 env->DeleteLocalRef(entry); 1461 *pIsOK = false; 1462 break; 1463 } 1464 jstring jvalue = static_cast<jstring>(obj); 1465 1466 String8 key = JStringToString8(env, jkey); 1467 String8 value = JStringToString8(env, jvalue); 1468 keyedVector.add(key, value); 1469 1470 env->DeleteLocalRef(jkey); 1471 env->DeleteLocalRef(jvalue); 1472 hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext); 1473 } 1474 env->DeleteLocalRef(entry); 1475 } 1476 env->DeleteLocalRef(iterator); 1477 } 1478 env->DeleteLocalRef(entrySet); 1479 } 1480 return keyedVector; 1481} 1482 1483static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz, 1484 jbyteArray uuidObj, jint mode) 1485{ 1486 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1487 if (mp == NULL) { 1488 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1489 return; 1490 } 1491 1492 if (uuidObj == NULL) { 1493 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1494 return; 1495 } 1496 1497 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj); 1498 1499 if (uuid.size() != 16) { 1500 jniThrowException( 1501 env, 1502 "java/lang/IllegalArgumentException", 1503 "invalid UUID size, expected 16 bytes"); 1504 return; 1505 } 1506 1507 status_t err = mp->prepareDrm(uuid.array(), mode); 1508 if (err != OK) { 1509 if (err == INVALID_OPERATION) { 1510 jniThrowException( 1511 env, 1512 "java/lang/IllegalStateException", 1513 "The player is not prepared yet."); 1514 } else if (err == ERROR_DRM_CANNOT_HANDLE) { 1515 jniThrowException( 1516 env, 1517 "android/media/UnsupportedSchemeException", 1518 "Failed to instantiate drm object."); 1519 } else { 1520 throwDrmExceptionAsNecessary(env, err, "Failed to prepare DRM scheme"); 1521 } 1522 } 1523} 1524 1525static void android_media_MediaPlayer_releaseDrm(JNIEnv *env, jobject thiz) 1526{ 1527 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1528 if (mp == NULL ) { 1529 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1530 return; 1531 } 1532 1533 status_t err = mp->releaseDrm(); 1534 if (err != OK) { 1535 if (err == INVALID_OPERATION) { 1536 jniThrowException( 1537 env, 1538 "java/lang/IllegalStateException", 1539 "The player is not prepared yet."); 1540 } 1541 } 1542} 1543 1544static jobject android_media_MediaPlayer_getKeyRequest(JNIEnv *env, jobject thiz, jbyteArray jscope, 1545 jstring jmimeType, jint jkeyType, jobject joptParams) 1546{ 1547 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1548 if (mp == NULL) { 1549 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1550 return NULL; 1551 } 1552 1553 Vector<uint8_t> scope; 1554 if (jscope != NULL) { 1555 scope = JByteArrayToVector(env, jscope); 1556 } 1557 1558 String8 mimeType; 1559 if (jmimeType != NULL) { 1560 mimeType = JStringToString8(env, jmimeType); 1561 } 1562 1563 DrmPlugin::KeyType keyType; 1564 if (jkeyType == gKeyTypes.kKeyTypeStreaming) { 1565 keyType = DrmPlugin::kKeyType_Streaming; 1566 } else if (jkeyType == gKeyTypes.kKeyTypeOffline) { 1567 keyType = DrmPlugin::kKeyType_Offline; 1568 } else if (jkeyType == gKeyTypes.kKeyTypeRelease) { 1569 keyType = DrmPlugin::kKeyType_Release; 1570 } else { 1571 jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType"); 1572 return NULL; 1573 } 1574 1575 KeyedVector<String8, String8> optParams; 1576 if (joptParams != NULL) { 1577 bool isOK; 1578 optParams = HashMapToKeyedVector(env, joptParams, &isOK); 1579 if (!isOK) { 1580 return NULL; 1581 } 1582 } 1583 1584 Vector<uint8_t> request; 1585 String8 defaultUrl; 1586 DrmPlugin::KeyRequestType keyRequestType; 1587 status_t err = mp->getKeyRequest(scope, mimeType, keyType, optParams, request, defaultUrl, 1588 keyRequestType); 1589 1590 if (throwDrmExceptionAsNecessary(env, err, "Failed to get key request")) { 1591 return NULL; 1592 } 1593 1594 ALOGV("JNI getKeyRequest err %d request %d url %s keyReqType %d", 1595 err, (int)request.size(), defaultUrl.string(), (int)keyRequestType); 1596 1597 // Fill out return obj 1598 jclass clazz; 1599 FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest"); 1600 1601 jobject keyObj = NULL; 1602 1603 if (clazz) { 1604 keyObj = env->AllocObject(clazz); 1605 jbyteArray jrequest = VectorToJByteArray(env, request); 1606 env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest); 1607 1608 jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string()); 1609 env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl); 1610 1611 switch (keyRequestType) { 1612 case DrmPlugin::kKeyRequestType_Initial: 1613 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1614 gKeyRequestTypes.kKeyRequestTypeInitial); 1615 break; 1616 case DrmPlugin::kKeyRequestType_Renewal: 1617 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1618 gKeyRequestTypes.kKeyRequestTypeRenewal); 1619 break; 1620 case DrmPlugin::kKeyRequestType_Release: 1621 env->SetIntField(keyObj, gFields.keyRequest.requestType, 1622 gKeyRequestTypes.kKeyRequestTypeRelease); 1623 break; 1624 default: 1625 throwDrmStateException(env, "MediaPlayer/DRM plugin failure: unknown " 1626 "key request type", ERROR_DRM_UNKNOWN); 1627 break; 1628 } 1629 } 1630 1631 return keyObj; 1632} 1633 1634static jbyteArray android_media_MediaPlayer_provideKeyResponse(JNIEnv *env, jobject thiz, 1635 jbyteArray jreleaseKeySetId, jbyteArray jresponse) 1636{ 1637 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1638 if (mp == NULL ) { 1639 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1640 return NULL; 1641 } 1642 1643 if (jresponse == NULL) { 1644 jniThrowException(env, "java/lang/IllegalArgumentException", "key response is null"); 1645 return NULL; 1646 } 1647 1648 Vector<uint8_t> releaseKeySetId; 1649 if (jreleaseKeySetId != NULL) { 1650 releaseKeySetId = JByteArrayToVector(env, jreleaseKeySetId); 1651 } 1652 1653 Vector<uint8_t> response(JByteArrayToVector(env, jresponse)); 1654 Vector<uint8_t> keySetId; 1655 1656 status_t err = mp->provideKeyResponse(releaseKeySetId, response, keySetId); 1657 1658 if (throwDrmExceptionAsNecessary(env, err, "Failed to handle key response")) { 1659 return NULL; 1660 } 1661 return VectorToJByteArray(env, keySetId); 1662} 1663 1664static void android_media_MediaPlayer_restoreKeys(JNIEnv *env, jobject thiz, jbyteArray jkeySetId) 1665{ 1666 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1667 if (mp == NULL) { 1668 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1669 return; 1670 } 1671 1672 if (jkeySetId == NULL) { 1673 jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType"); 1674 return; 1675 } 1676 1677 Vector<uint8_t> keySetId; 1678 keySetId = JByteArrayToVector(env, jkeySetId); 1679 1680 status_t err = mp->restoreKeys(keySetId); 1681 1682 ALOGV("JNI restoreKeys err %d ", err); 1683 throwDrmExceptionAsNecessary(env, err, "Failed to restore keys"); 1684} 1685 1686static jstring android_media_MediaPlayer_getDrmPropertyString(JNIEnv *env, jobject thiz, 1687 jstring jname) 1688{ 1689 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1690 if (mp == NULL) { 1691 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1692 return NULL; 1693 } 1694 1695 if (jname == NULL) { 1696 jniThrowException(env, "java/lang/IllegalArgumentException", 1697 "property name String is null"); 1698 return NULL; 1699 } 1700 1701 String8 name = JStringToString8(env, jname); 1702 String8 value; 1703 1704 status_t err = mp->getDrmPropertyString(name, value); 1705 1706 ALOGV("JNI getPropertyString err %d", err); 1707 1708 if (throwDrmExceptionAsNecessary(env, err, "Failed to get property")) { 1709 return NULL; 1710 } 1711 1712 return env->NewStringUTF(value.string()); 1713} 1714 1715static void android_media_MediaPlayer_setDrmPropertyString(JNIEnv *env, jobject thiz, 1716 jstring jname, jstring jvalue) 1717{ 1718 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); 1719 if (mp == NULL) { 1720 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1721 return; 1722 } 1723 1724 if (jname == NULL) { 1725 jniThrowException(env, "java/lang/IllegalArgumentException", 1726 "property name String is null"); 1727 return; 1728 } 1729 1730 if (jvalue == NULL) { 1731 jniThrowException(env, "java/lang/IllegalArgumentException", 1732 "property value String is null"); 1733 return; 1734 } 1735 1736 String8 name = JStringToString8(env, jname); 1737 String8 value = JStringToString8(env, jvalue); 1738 1739 status_t err = mp->setDrmPropertyString(name, value); 1740 1741 ALOGV("JNI setPropertyString err %d", err); 1742 throwDrmExceptionAsNecessary(env, err, "Failed to set property"); 1743} 1744// Modular DRM end 1745// ---------------------------------------------------------------------------- 1746 1747static const JNINativeMethod gMethods[] = { 1748 { 1749 "nativeSetDataSource", 1750 "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;" 1751 "[Ljava/lang/String;)V", 1752 (void *)android_media_MediaPlayer_setDataSourceAndHeaders 1753 }, 1754 1755 {"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, 1756 {"_setDataSource", "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback }, 1757 {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface}, 1758 {"getDefaultBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer_getDefaultBufferingParams}, 1759 {"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer_getBufferingParams}, 1760 {"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer_setBufferingParams}, 1761 {"_prepare", "()V", (void *)android_media_MediaPlayer_prepare}, 1762 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, 1763 {"_start", "()V", (void *)android_media_MediaPlayer_start}, 1764 {"_stop", "()V", (void *)android_media_MediaPlayer_stop}, 1765 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth}, 1766 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight}, 1767 {"getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaPlayer_getMetrics}, 1768 {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams}, 1769 {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams}, 1770 {"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer_setSyncParams}, 1771 {"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer_getSyncParams}, 1772 {"_seekTo", "(II)V", (void *)android_media_MediaPlayer_seekTo}, 1773 {"_pause", "()V", (void *)android_media_MediaPlayer_pause}, 1774 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying}, 1775 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition}, 1776 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration}, 1777 {"_release", "()V", (void *)android_media_MediaPlayer_release}, 1778 {"_reset", "()V", (void *)android_media_MediaPlayer_reset}, 1779 {"_setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType}, 1780 {"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer_getAudioStreamType}, 1781 {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter}, 1782 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping}, 1783 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping}, 1784 {"_setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume}, 1785 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke}, 1786 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter}, 1787 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata}, 1788 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init}, 1789 {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup}, 1790 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize}, 1791 {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id}, 1792 {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id}, 1793 {"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel}, 1794 {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect}, 1795 {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData}, 1796 {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint}, 1797 {"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer}, 1798 {"native_applyVolumeShaper", 1799 "(Landroid/media/VolumeShaper$Configuration;Landroid/media/VolumeShaper$Operation;)I", 1800 (void *)android_media_MediaPlayer_applyVolumeShaper}, 1801 {"native_getVolumeShaperState", 1802 "(I)Landroid/media/VolumeShaper$State;", 1803 (void *)android_media_MediaPlayer_getVolumeShaperState}, 1804 // Modular DRM 1805 { "_prepareDrm", "([BI)V", (void *)android_media_MediaPlayer_prepareDrm }, 1806 { "_releaseDrm", "()V", (void *)android_media_MediaPlayer_releaseDrm }, 1807 { "_getKeyRequest", "([BLjava/lang/String;ILjava/util/Map;)" "Landroid/media/MediaDrm$KeyRequest;", 1808 (void *)android_media_MediaPlayer_getKeyRequest }, 1809 { "_provideKeyResponse", "([B[B)[B", (void *)android_media_MediaPlayer_provideKeyResponse }, 1810 { "_getDrmPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_MediaPlayer_getDrmPropertyString }, 1811 { "_setDrmPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDrmPropertyString }, 1812 { "_restoreKeys", "([B)V", (void *)android_media_MediaPlayer_restoreKeys }, 1813}; 1814 1815// This function only registers the native methods 1816static int register_android_media_MediaPlayer(JNIEnv *env) 1817{ 1818 return AndroidRuntime::registerNativeMethods(env, 1819 "android/media/MediaPlayer", gMethods, NELEM(gMethods)); 1820} 1821extern int register_android_media_ImageReader(JNIEnv *env); 1822extern int register_android_media_ImageWriter(JNIEnv *env); 1823extern int register_android_media_Crypto(JNIEnv *env); 1824extern int register_android_media_Drm(JNIEnv *env); 1825extern int register_android_media_MediaCodec(JNIEnv *env); 1826extern int register_android_media_MediaExtractor(JNIEnv *env); 1827extern int register_android_media_MediaCodecList(JNIEnv *env); 1828extern int register_android_media_MediaHTTPConnection(JNIEnv *env); 1829extern int register_android_media_MediaMetadataRetriever(JNIEnv *env); 1830extern int register_android_media_MediaMuxer(JNIEnv *env); 1831extern int register_android_media_MediaRecorder(JNIEnv *env); 1832extern int register_android_media_MediaScanner(JNIEnv *env); 1833extern int register_android_media_MediaSync(JNIEnv *env); 1834extern int register_android_media_ResampleInputStream(JNIEnv *env); 1835extern int register_android_media_MediaProfiles(JNIEnv *env); 1836extern int register_android_mtp_MtpDatabase(JNIEnv *env); 1837extern int register_android_mtp_MtpDevice(JNIEnv *env); 1838extern int register_android_mtp_MtpServer(JNIEnv *env); 1839 1840jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) 1841{ 1842 JNIEnv* env = NULL; 1843 jint result = -1; 1844 1845 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 1846 ALOGE("ERROR: GetEnv failed\n"); 1847 goto bail; 1848 } 1849 assert(env != NULL); 1850 1851 if (register_android_media_ImageWriter(env) != JNI_OK) { 1852 ALOGE("ERROR: ImageWriter native registration failed"); 1853 goto bail; 1854 } 1855 1856 if (register_android_media_ImageReader(env) < 0) { 1857 ALOGE("ERROR: ImageReader native registration failed"); 1858 goto bail; 1859 } 1860 1861 if (register_android_media_MediaPlayer(env) < 0) { 1862 ALOGE("ERROR: MediaPlayer native registration failed\n"); 1863 goto bail; 1864 } 1865 1866 if (register_android_media_MediaRecorder(env) < 0) { 1867 ALOGE("ERROR: MediaRecorder native registration failed\n"); 1868 goto bail; 1869 } 1870 1871 if (register_android_media_MediaScanner(env) < 0) { 1872 ALOGE("ERROR: MediaScanner native registration failed\n"); 1873 goto bail; 1874 } 1875 1876 if (register_android_media_MediaMetadataRetriever(env) < 0) { 1877 ALOGE("ERROR: MediaMetadataRetriever native registration failed\n"); 1878 goto bail; 1879 } 1880 1881 if (register_android_media_ResampleInputStream(env) < 0) { 1882 ALOGE("ERROR: ResampleInputStream native registration failed\n"); 1883 goto bail; 1884 } 1885 1886 if (register_android_media_MediaProfiles(env) < 0) { 1887 ALOGE("ERROR: MediaProfiles native registration failed"); 1888 goto bail; 1889 } 1890 1891 if (register_android_mtp_MtpDatabase(env) < 0) { 1892 ALOGE("ERROR: MtpDatabase native registration failed"); 1893 goto bail; 1894 } 1895 1896 if (register_android_mtp_MtpDevice(env) < 0) { 1897 ALOGE("ERROR: MtpDevice native registration failed"); 1898 goto bail; 1899 } 1900 1901 if (register_android_mtp_MtpServer(env) < 0) { 1902 ALOGE("ERROR: MtpServer native registration failed"); 1903 goto bail; 1904 } 1905 1906 if (register_android_media_MediaCodec(env) < 0) { 1907 ALOGE("ERROR: MediaCodec native registration failed"); 1908 goto bail; 1909 } 1910 1911 if (register_android_media_MediaSync(env) < 0) { 1912 ALOGE("ERROR: MediaSync native registration failed"); 1913 goto bail; 1914 } 1915 1916 if (register_android_media_MediaExtractor(env) < 0) { 1917 ALOGE("ERROR: MediaCodec native registration failed"); 1918 goto bail; 1919 } 1920 1921 if (register_android_media_MediaMuxer(env) < 0) { 1922 ALOGE("ERROR: MediaMuxer native registration failed"); 1923 goto bail; 1924 } 1925 1926 if (register_android_media_MediaCodecList(env) < 0) { 1927 ALOGE("ERROR: MediaCodec native registration failed"); 1928 goto bail; 1929 } 1930 1931 if (register_android_media_Crypto(env) < 0) { 1932 ALOGE("ERROR: MediaCodec native registration failed"); 1933 goto bail; 1934 } 1935 1936 if (register_android_media_Drm(env) < 0) { 1937 ALOGE("ERROR: MediaDrm native registration failed"); 1938 goto bail; 1939 } 1940 1941 if (register_android_media_MediaHTTPConnection(env) < 0) { 1942 ALOGE("ERROR: MediaHTTPConnection native registration failed"); 1943 goto bail; 1944 } 1945 1946 /* success -- return valid version number */ 1947 result = JNI_VERSION_1_4; 1948 1949bail: 1950 return result; 1951} 1952 1953// KTHXBYE 1954