Home | History | Annotate | Download | only in jni
      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 <stdio.h>
     27 #include <assert.h>
     28 #include <limits.h>
     29 #include <unistd.h>
     30 #include <fcntl.h>
     31 #include <utils/threads.h>
     32 #include "jni.h"
     33 #include "JNIHelp.h"
     34 #include "android_runtime/AndroidRuntime.h"
     35 #include "android_runtime/android_view_Surface.h"
     36 #include "android_runtime/Log.h"
     37 #include "utils/Errors.h"  // for status_t
     38 #include "utils/KeyedVector.h"
     39 #include "utils/String8.h"
     40 #include "android_media_MediaDataSource.h"
     41 #include "android_media_PlaybackParams.h"
     42 #include "android_media_SyncParams.h"
     43 #include "android_media_Utils.h"
     44 
     45 #include "android_os_Parcel.h"
     46 #include "android_util_Binder.h"
     47 #include <binder/Parcel.h>
     48 #include <gui/IGraphicBufferProducer.h>
     49 #include <gui/Surface.h>
     50 #include <binder/IPCThreadState.h>
     51 #include <binder/IServiceManager.h>
     52 
     53 #include "android_util_Binder.h"
     54 // ----------------------------------------------------------------------------
     55 
     56 using namespace android;
     57 
     58 // ----------------------------------------------------------------------------
     59 
     60 struct fields_t {
     61     jfieldID    context;
     62     jfieldID    surface_texture;
     63 
     64     jmethodID   post_event;
     65 
     66     jmethodID   proxyConfigGetHost;
     67     jmethodID   proxyConfigGetPort;
     68     jmethodID   proxyConfigGetExclusionList;
     69 };
     70 static fields_t fields;
     71 
     72 static PlaybackParams::fields_t gPlaybackParamsFields;
     73 static SyncParams::fields_t gSyncParamsFields;
     74 
     75 static Mutex sLock;
     76 
     77 // ----------------------------------------------------------------------------
     78 // ref-counted object for callbacks
     79 class JNIMediaPlayerListener: public MediaPlayerListener
     80 {
     81 public:
     82     JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
     83     ~JNIMediaPlayerListener();
     84     virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
     85 private:
     86     JNIMediaPlayerListener();
     87     jclass      mClass;     // Reference to MediaPlayer class
     88     jobject     mObject;    // Weak ref to MediaPlayer Java object to call on
     89 };
     90 
     91 JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
     92 {
     93 
     94     // Hold onto the MediaPlayer class for use in calling the static method
     95     // that posts events to the application thread.
     96     jclass clazz = env->GetObjectClass(thiz);
     97     if (clazz == NULL) {
     98         ALOGE("Can't find android/media/MediaPlayer");
     99         jniThrowException(env, "java/lang/Exception", NULL);
    100         return;
    101     }
    102     mClass = (jclass)env->NewGlobalRef(clazz);
    103 
    104     // We use a weak reference so the MediaPlayer object can be garbage collected.
    105     // The reference is only used as a proxy for callbacks.
    106     mObject  = env->NewGlobalRef(weak_thiz);
    107 }
    108 
    109 JNIMediaPlayerListener::~JNIMediaPlayerListener()
    110 {
    111     // remove global references
    112     JNIEnv *env = AndroidRuntime::getJNIEnv();
    113     env->DeleteGlobalRef(mObject);
    114     env->DeleteGlobalRef(mClass);
    115 }
    116 
    117 void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
    118 {
    119     JNIEnv *env = AndroidRuntime::getJNIEnv();
    120     if (obj && obj->dataSize() > 0) {
    121         jobject jParcel = createJavaParcelObject(env);
    122         if (jParcel != NULL) {
    123             Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
    124             nativeParcel->setData(obj->data(), obj->dataSize());
    125             env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
    126                     msg, ext1, ext2, jParcel);
    127             env->DeleteLocalRef(jParcel);
    128         }
    129     } else {
    130         env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
    131                 msg, ext1, ext2, NULL);
    132     }
    133     if (env->ExceptionCheck()) {
    134         ALOGW("An exception occurred while notifying an event.");
    135         LOGW_EX(env);
    136         env->ExceptionClear();
    137     }
    138 }
    139 
    140 // ----------------------------------------------------------------------------
    141 
    142 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
    143 {
    144     Mutex::Autolock l(sLock);
    145     MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context);
    146     return sp<MediaPlayer>(p);
    147 }
    148 
    149 static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
    150 {
    151     Mutex::Autolock l(sLock);
    152     sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context);
    153     if (player.get()) {
    154         player->incStrong((void*)setMediaPlayer);
    155     }
    156     if (old != 0) {
    157         old->decStrong((void*)setMediaPlayer);
    158     }
    159     env->SetLongField(thiz, fields.context, (jlong)player.get());
    160     return old;
    161 }
    162 
    163 // If exception is NULL and opStatus is not OK, this method sends an error
    164 // event to the client application; otherwise, if exception is not NULL and
    165 // opStatus is not OK, this method throws the given exception to the client
    166 // application.
    167 static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message)
    168 {
    169     if (exception == NULL) {  // Don't throw exception. Instead, send an event.
    170         if (opStatus != (status_t) OK) {
    171             sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    172             if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0);
    173         }
    174     } else {  // Throw exception!
    175         if ( opStatus == (status_t) INVALID_OPERATION ) {
    176             jniThrowException(env, "java/lang/IllegalStateException", NULL);
    177         } else if ( opStatus == (status_t) BAD_VALUE ) {
    178             jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    179         } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
    180             jniThrowException(env, "java/lang/SecurityException", NULL);
    181         } else if ( opStatus != (status_t) OK ) {
    182             if (strlen(message) > 230) {
    183                // if the message is too long, don't bother displaying the status code
    184                jniThrowException( env, exception, message);
    185             } else {
    186                char msg[256];
    187                 // append the status code to the message
    188                sprintf(msg, "%s: status=0x%X", message, opStatus);
    189                jniThrowException( env, exception, msg);
    190             }
    191         }
    192     }
    193 }
    194 
    195 static void
    196 android_media_MediaPlayer_setDataSourceAndHeaders(
    197         JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
    198         jobjectArray keys, jobjectArray values) {
    199 
    200     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    201     if (mp == NULL ) {
    202         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    203         return;
    204     }
    205 
    206     if (path == NULL) {
    207         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    208         return;
    209     }
    210 
    211     const char *tmp = env->GetStringUTFChars(path, NULL);
    212     if (tmp == NULL) {  // Out of memory
    213         return;
    214     }
    215     ALOGV("setDataSource: path %s", tmp);
    216 
    217     String8 pathStr(tmp);
    218     env->ReleaseStringUTFChars(path, tmp);
    219     tmp = NULL;
    220 
    221     // We build a KeyedVector out of the key and val arrays
    222     KeyedVector<String8, String8> headersVector;
    223     if (!ConvertKeyValueArraysToKeyedVector(
    224             env, keys, values, &headersVector)) {
    225         return;
    226     }
    227 
    228     sp<IMediaHTTPService> httpService;
    229     if (httpServiceBinderObj != NULL) {
    230         sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
    231         httpService = interface_cast<IMediaHTTPService>(binder);
    232     }
    233 
    234     status_t opStatus =
    235         mp->setDataSource(
    236                 httpService,
    237                 pathStr,
    238                 headersVector.size() > 0? &headersVector : NULL);
    239 
    240     process_media_player_call(
    241             env, thiz, opStatus, "java/io/IOException",
    242             "setDataSource failed." );
    243 }
    244 
    245 static void
    246 android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
    247 {
    248     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    249     if (mp == NULL ) {
    250         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    251         return;
    252     }
    253 
    254     if (fileDescriptor == NULL) {
    255         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    256         return;
    257     }
    258     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    259     ALOGV("setDataSourceFD: fd %d", fd);
    260     process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
    261 }
    262 
    263 static void
    264 android_media_MediaPlayer_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource)
    265 {
    266     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    267     if (mp == NULL ) {
    268         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    269         return;
    270     }
    271 
    272     if (dataSource == NULL) {
    273         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    274         return;
    275     }
    276     sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource);
    277     process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." );
    278 }
    279 
    280 static sp<IGraphicBufferProducer>
    281 getVideoSurfaceTexture(JNIEnv* env, jobject thiz) {
    282     IGraphicBufferProducer * const p = (IGraphicBufferProducer*)env->GetLongField(thiz, fields.surface_texture);
    283     return sp<IGraphicBufferProducer>(p);
    284 }
    285 
    286 static void
    287 decVideoSurfaceRef(JNIEnv *env, jobject thiz)
    288 {
    289     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    290     if (mp == NULL) {
    291         return;
    292     }
    293 
    294     sp<IGraphicBufferProducer> old_st = getVideoSurfaceTexture(env, thiz);
    295     if (old_st != NULL) {
    296         old_st->decStrong((void*)decVideoSurfaceRef);
    297     }
    298 }
    299 
    300 static void
    301 setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive)
    302 {
    303     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    304     if (mp == NULL) {
    305         if (mediaPlayerMustBeAlive) {
    306             jniThrowException(env, "java/lang/IllegalStateException", NULL);
    307         }
    308         return;
    309     }
    310 
    311     decVideoSurfaceRef(env, thiz);
    312 
    313     sp<IGraphicBufferProducer> new_st;
    314     if (jsurface) {
    315         sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
    316         if (surface != NULL) {
    317             new_st = surface->getIGraphicBufferProducer();
    318             if (new_st == NULL) {
    319                 jniThrowException(env, "java/lang/IllegalArgumentException",
    320                     "The surface does not have a binding SurfaceTexture!");
    321                 return;
    322             }
    323             new_st->incStrong((void*)decVideoSurfaceRef);
    324         } else {
    325             jniThrowException(env, "java/lang/IllegalArgumentException",
    326                     "The surface has been released");
    327             return;
    328         }
    329     }
    330 
    331     env->SetLongField(thiz, fields.surface_texture, (jlong)new_st.get());
    332 
    333     // This will fail if the media player has not been initialized yet. This
    334     // can be the case if setDisplay() on MediaPlayer.java has been called
    335     // before setDataSource(). The redundant call to setVideoSurfaceTexture()
    336     // in prepare/prepareAsync covers for this case.
    337     mp->setVideoSurfaceTexture(new_st);
    338 }
    339 
    340 static void
    341 android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface)
    342 {
    343     setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
    344 }
    345 
    346 static void
    347 android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)
    348 {
    349     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    350     if (mp == NULL ) {
    351         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    352         return;
    353     }
    354 
    355     // Handle the case where the display surface was set before the mp was
    356     // initialized. We try again to make it stick.
    357     sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
    358     mp->setVideoSurfaceTexture(st);
    359 
    360     process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
    361 }
    362 
    363 static void
    364 android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
    365 {
    366     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    367     if (mp == NULL ) {
    368         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    369         return;
    370     }
    371 
    372     // Handle the case where the display surface was set before the mp was
    373     // initialized. We try again to make it stick.
    374     sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
    375     mp->setVideoSurfaceTexture(st);
    376 
    377     process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
    378 }
    379 
    380 static void
    381 android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
    382 {
    383     ALOGV("start");
    384     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    385     if (mp == NULL ) {
    386         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    387         return;
    388     }
    389     process_media_player_call( env, thiz, mp->start(), NULL, NULL );
    390 }
    391 
    392 static void
    393 android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz)
    394 {
    395     ALOGV("stop");
    396     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    397     if (mp == NULL ) {
    398         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    399         return;
    400     }
    401     process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
    402 }
    403 
    404 static void
    405 android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz)
    406 {
    407     ALOGV("pause");
    408     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    409     if (mp == NULL ) {
    410         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    411         return;
    412     }
    413     process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
    414 }
    415 
    416 static jboolean
    417 android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz)
    418 {
    419     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    420     if (mp == NULL ) {
    421         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    422         return JNI_FALSE;
    423     }
    424     const jboolean is_playing = mp->isPlaying();
    425 
    426     ALOGV("isPlaying: %d", is_playing);
    427     return is_playing;
    428 }
    429 
    430 static void
    431 android_media_MediaPlayer_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params)
    432 {
    433     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    434     if (mp == NULL) {
    435         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    436         return;
    437     }
    438 
    439     PlaybackParams pbp;
    440     pbp.fillFromJobject(env, gPlaybackParamsFields, params);
    441     ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u",
    442             pbp.speedSet, pbp.audioRate.mSpeed,
    443             pbp.pitchSet, pbp.audioRate.mPitch,
    444             pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode,
    445             pbp.audioStretchModeSet, pbp.audioRate.mStretchMode);
    446 
    447     AudioPlaybackRate rate;
    448     status_t err = mp->getPlaybackSettings(&rate);
    449     if (err == OK) {
    450         bool updatedRate = false;
    451         if (pbp.speedSet) {
    452             rate.mSpeed = pbp.audioRate.mSpeed;
    453             updatedRate = true;
    454         }
    455         if (pbp.pitchSet) {
    456             rate.mPitch = pbp.audioRate.mPitch;
    457             updatedRate = true;
    458         }
    459         if (pbp.audioFallbackModeSet) {
    460             rate.mFallbackMode = pbp.audioRate.mFallbackMode;
    461             updatedRate = true;
    462         }
    463         if (pbp.audioStretchModeSet) {
    464             rate.mStretchMode = pbp.audioRate.mStretchMode;
    465             updatedRate = true;
    466         }
    467         if (updatedRate) {
    468             err = mp->setPlaybackSettings(rate);
    469         }
    470     }
    471     process_media_player_call(
    472             env, thiz, err,
    473             "java/lang/IllegalStateException", "unexpected error");
    474 }
    475 
    476 static jobject
    477 android_media_MediaPlayer_getPlaybackParams(JNIEnv *env, jobject thiz)
    478 {
    479     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    480     if (mp == NULL) {
    481         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    482         return NULL;
    483     }
    484 
    485     PlaybackParams pbp;
    486     AudioPlaybackRate &audioRate = pbp.audioRate;
    487     process_media_player_call(
    488             env, thiz, mp->getPlaybackSettings(&audioRate),
    489             "java/lang/IllegalStateException", "unexpected error");
    490     ALOGV("getPlaybackSettings: %f %f %d %d",
    491             audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
    492 
    493     pbp.speedSet = true;
    494     pbp.pitchSet = true;
    495     pbp.audioFallbackModeSet = true;
    496     pbp.audioStretchModeSet = true;
    497 
    498     return pbp.asJobject(env, gPlaybackParamsFields);
    499 }
    500 
    501 static void
    502 android_media_MediaPlayer_setSyncParams(JNIEnv *env, jobject thiz, jobject params)
    503 {
    504     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    505     if (mp == NULL) {
    506         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    507         return;
    508     }
    509 
    510     SyncParams scp;
    511     scp.fillFromJobject(env, gSyncParamsFields, params);
    512     ALOGV("setSyncParams: %d:%d %d:%d %d:%f %d:%f",
    513           scp.syncSourceSet, scp.sync.mSource,
    514           scp.audioAdjustModeSet, scp.sync.mAudioAdjustMode,
    515           scp.toleranceSet, scp.sync.mTolerance,
    516           scp.frameRateSet, scp.frameRate);
    517 
    518     AVSyncSettings avsync;
    519     float videoFrameRate;
    520     status_t err = mp->getSyncSettings(&avsync, &videoFrameRate);
    521     if (err == OK) {
    522         bool updatedSync = scp.frameRateSet;
    523         if (scp.syncSourceSet) {
    524             avsync.mSource = scp.sync.mSource;
    525             updatedSync = true;
    526         }
    527         if (scp.audioAdjustModeSet) {
    528             avsync.mAudioAdjustMode = scp.sync.mAudioAdjustMode;
    529             updatedSync = true;
    530         }
    531         if (scp.toleranceSet) {
    532             avsync.mTolerance = scp.sync.mTolerance;
    533             updatedSync = true;
    534         }
    535         if (updatedSync) {
    536             err = mp->setSyncSettings(avsync, scp.frameRateSet ? scp.frameRate : -1.f);
    537         }
    538     }
    539     process_media_player_call(
    540             env, thiz, err,
    541             "java/lang/IllegalStateException", "unexpected error");
    542 }
    543 
    544 static jobject
    545 android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz)
    546 {
    547     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    548     if (mp == NULL) {
    549         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    550         return NULL;
    551     }
    552 
    553     SyncParams scp;
    554     scp.frameRate = -1.f;
    555     process_media_player_call(
    556             env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate),
    557             "java/lang/IllegalStateException", "unexpected error");
    558 
    559     ALOGV("getSyncSettings: %d %d %f %f",
    560             scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate);
    561 
    562     // sanity check params
    563     if (scp.sync.mSource >= AVSYNC_SOURCE_MAX
    564             || scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
    565             || scp.sync.mTolerance < 0.f
    566             || scp.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
    567         jniThrowException(env,  "java/lang/IllegalStateException", NULL);
    568         return NULL;
    569     }
    570 
    571     scp.syncSourceSet = true;
    572     scp.audioAdjustModeSet = true;
    573     scp.toleranceSet = true;
    574     scp.frameRateSet = scp.frameRate >= 0.f;
    575 
    576     return scp.asJobject(env, gSyncParamsFields);
    577 }
    578 
    579 static void
    580 android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jint msec)
    581 {
    582     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    583     if (mp == NULL ) {
    584         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    585         return;
    586     }
    587     ALOGV("seekTo: %d(msec)", msec);
    588     process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL );
    589 }
    590 
    591 static jint
    592 android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz)
    593 {
    594     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    595     if (mp == NULL ) {
    596         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    597         return 0;
    598     }
    599     int w;
    600     if (0 != mp->getVideoWidth(&w)) {
    601         ALOGE("getVideoWidth failed");
    602         w = 0;
    603     }
    604     ALOGV("getVideoWidth: %d", w);
    605     return (jint) w;
    606 }
    607 
    608 static jint
    609 android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz)
    610 {
    611     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    612     if (mp == NULL ) {
    613         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    614         return 0;
    615     }
    616     int h;
    617     if (0 != mp->getVideoHeight(&h)) {
    618         ALOGE("getVideoHeight failed");
    619         h = 0;
    620     }
    621     ALOGV("getVideoHeight: %d", h);
    622     return (jint) h;
    623 }
    624 
    625 
    626 static jint
    627 android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz)
    628 {
    629     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    630     if (mp == NULL ) {
    631         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    632         return 0;
    633     }
    634     int msec;
    635     process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
    636     ALOGV("getCurrentPosition: %d (msec)", msec);
    637     return (jint) msec;
    638 }
    639 
    640 static jint
    641 android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz)
    642 {
    643     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    644     if (mp == NULL ) {
    645         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    646         return 0;
    647     }
    648     int msec;
    649     process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
    650     ALOGV("getDuration: %d (msec)", msec);
    651     return (jint) msec;
    652 }
    653 
    654 static void
    655 android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
    656 {
    657     ALOGV("reset");
    658     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    659     if (mp == NULL ) {
    660         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    661         return;
    662     }
    663     process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
    664 }
    665 
    666 static void
    667 android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, jint streamtype)
    668 {
    669     ALOGV("setAudioStreamType: %d", streamtype);
    670     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    671     if (mp == NULL ) {
    672         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    673         return;
    674     }
    675     process_media_player_call( env, thiz, mp->setAudioStreamType((audio_stream_type_t) streamtype) , NULL, NULL );
    676 }
    677 
    678 static jint
    679 android_media_MediaPlayer_getAudioStreamType(JNIEnv *env, jobject thiz)
    680 {
    681     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    682     if (mp == NULL ) {
    683         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    684         return 0;
    685     }
    686     audio_stream_type_t streamtype;
    687     process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL );
    688     ALOGV("getAudioStreamType: %d (streamtype)", streamtype);
    689     return (jint) streamtype;
    690 }
    691 
    692 static jboolean
    693 android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
    694 {
    695     ALOGV("setParameter: key %d", key);
    696     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    697     if (mp == NULL ) {
    698         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    699         return false;
    700     }
    701 
    702     Parcel *request = parcelForJavaObject(env, java_request);
    703     status_t err = mp->setParameter(key, *request);
    704     if (err == OK) {
    705         return true;
    706     } else {
    707         return false;
    708     }
    709 }
    710 
    711 static void
    712 android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
    713 {
    714     ALOGV("setLooping: %d", looping);
    715     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    716     if (mp == NULL ) {
    717         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    718         return;
    719     }
    720     process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL );
    721 }
    722 
    723 static jboolean
    724 android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz)
    725 {
    726     ALOGV("isLooping");
    727     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    728     if (mp == NULL ) {
    729         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    730         return JNI_FALSE;
    731     }
    732     return mp->isLooping() ? JNI_TRUE : JNI_FALSE;
    733 }
    734 
    735 static void
    736 android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, jfloat leftVolume, jfloat rightVolume)
    737 {
    738     ALOGV("setVolume: left %f  right %f", (float) leftVolume, (float) rightVolume);
    739     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    740     if (mp == NULL ) {
    741         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    742         return;
    743     }
    744     process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL );
    745 }
    746 
    747 // Sends the request and reply parcels to the media player via the
    748 // binder interface.
    749 static jint
    750 android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz,
    751                                  jobject java_request, jobject java_reply)
    752 {
    753     sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
    754     if (media_player == NULL ) {
    755         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    756         return UNKNOWN_ERROR;
    757     }
    758 
    759     Parcel *request = parcelForJavaObject(env, java_request);
    760     Parcel *reply = parcelForJavaObject(env, java_reply);
    761 
    762     // Don't use process_media_player_call which use the async loop to
    763     // report errors, instead returns the status.
    764     return (jint) media_player->invoke(*request, reply);
    765 }
    766 
    767 // Sends the new filter to the client.
    768 static jint
    769 android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
    770 {
    771     sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
    772     if (media_player == NULL ) {
    773         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    774         return UNKNOWN_ERROR;
    775     }
    776 
    777     Parcel *filter = parcelForJavaObject(env, request);
    778 
    779     if (filter == NULL ) {
    780         jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
    781         return UNKNOWN_ERROR;
    782     }
    783 
    784     return (jint) media_player->setMetadataFilter(*filter);
    785 }
    786 
    787 static jboolean
    788 android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
    789                                       jboolean apply_filter, jobject reply)
    790 {
    791     sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
    792     if (media_player == NULL ) {
    793         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    794         return JNI_FALSE;
    795     }
    796 
    797     Parcel *metadata = parcelForJavaObject(env, reply);
    798 
    799     if (metadata == NULL ) {
    800         jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
    801         return JNI_FALSE;
    802     }
    803 
    804     metadata->freeData();
    805     // On return metadata is positioned at the beginning of the
    806     // metadata. Note however that the parcel actually starts with the
    807     // return code so you should not rewind the parcel using
    808     // setDataPosition(0).
    809     if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) {
    810         return JNI_TRUE;
    811     } else {
    812         return JNI_FALSE;
    813     }
    814 }
    815 
    816 // This function gets some field IDs, which in turn causes class initialization.
    817 // It is called from a static block in MediaPlayer, which won't run until the
    818 // first time an instance of this class is used.
    819 static void
    820 android_media_MediaPlayer_native_init(JNIEnv *env)
    821 {
    822     jclass clazz;
    823 
    824     clazz = env->FindClass("android/media/MediaPlayer");
    825     if (clazz == NULL) {
    826         return;
    827     }
    828 
    829     fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
    830     if (fields.context == NULL) {
    831         return;
    832     }
    833 
    834     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
    835                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
    836     if (fields.post_event == NULL) {
    837         return;
    838     }
    839 
    840     fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "J");
    841     if (fields.surface_texture == NULL) {
    842         return;
    843     }
    844 
    845     env->DeleteLocalRef(clazz);
    846 
    847     clazz = env->FindClass("android/net/ProxyInfo");
    848     if (clazz == NULL) {
    849         return;
    850     }
    851 
    852     fields.proxyConfigGetHost =
    853         env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;");
    854 
    855     fields.proxyConfigGetPort =
    856         env->GetMethodID(clazz, "getPort", "()I");
    857 
    858     fields.proxyConfigGetExclusionList =
    859         env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;");
    860 
    861     env->DeleteLocalRef(clazz);
    862 
    863     gPlaybackParamsFields.init(env);
    864     gSyncParamsFields.init(env);
    865 }
    866 
    867 static void
    868 android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
    869 {
    870     ALOGV("native_setup");
    871     sp<MediaPlayer> mp = new MediaPlayer();
    872     if (mp == NULL) {
    873         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
    874         return;
    875     }
    876 
    877     // create new listener and give it to MediaPlayer
    878     sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
    879     mp->setListener(listener);
    880 
    881     // Stow our new C++ MediaPlayer in an opaque field in the Java object.
    882     setMediaPlayer(env, thiz, mp);
    883 }
    884 
    885 static void
    886 android_media_MediaPlayer_release(JNIEnv *env, jobject thiz)
    887 {
    888     ALOGV("release");
    889     decVideoSurfaceRef(env, thiz);
    890     sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0);
    891     if (mp != NULL) {
    892         // this prevents native callbacks after the object is released
    893         mp->setListener(0);
    894         mp->disconnect();
    895     }
    896 }
    897 
    898 static void
    899 android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
    900 {
    901     ALOGV("native_finalize");
    902     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    903     if (mp != NULL) {
    904         ALOGW("MediaPlayer finalized without being released");
    905     }
    906     android_media_MediaPlayer_release(env, thiz);
    907 }
    908 
    909 static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz,
    910         jint sessionId) {
    911     ALOGV("set_session_id(): %d", sessionId);
    912     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    913     if (mp == NULL ) {
    914         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    915         return;
    916     }
    917     process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL,
    918             NULL);
    919 }
    920 
    921 static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env,  jobject thiz) {
    922     ALOGV("get_session_id()");
    923     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    924     if (mp == NULL ) {
    925         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    926         return 0;
    927     }
    928 
    929     return (jint) mp->getAudioSessionId();
    930 }
    931 
    932 static void
    933 android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level)
    934 {
    935     ALOGV("setAuxEffectSendLevel: level %f", level);
    936     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    937     if (mp == NULL ) {
    938         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    939         return;
    940     }
    941     process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL );
    942 }
    943 
    944 static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env,  jobject thiz, jint effectId) {
    945     ALOGV("attachAuxEffect(): %d", effectId);
    946     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    947     if (mp == NULL ) {
    948         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    949         return;
    950     }
    951     process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
    952 }
    953 
    954 static jint
    955 android_media_MediaPlayer_pullBatteryData(
    956         JNIEnv *env, jobject /* thiz */, jobject java_reply)
    957 {
    958     sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
    959     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
    960     if (service.get() == NULL) {
    961         jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService");
    962         return UNKNOWN_ERROR;
    963     }
    964 
    965     Parcel *reply = parcelForJavaObject(env, java_reply);
    966 
    967     return (jint) service->pullBatteryData(reply);
    968 }
    969 
    970 static jint
    971 android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz,
    972                                                 jstring addrString, jint port) {
    973     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    974     if (mp == NULL ) {
    975         jniThrowException(env, "java/lang/IllegalStateException", NULL);
    976         return INVALID_OPERATION;
    977     }
    978 
    979     const char *cAddrString = NULL;
    980 
    981     if (NULL != addrString) {
    982         cAddrString = env->GetStringUTFChars(addrString, NULL);
    983         if (cAddrString == NULL) {  // Out of memory
    984             return NO_MEMORY;
    985         }
    986     }
    987     ALOGV("setRetransmitEndpoint: %s:%d",
    988             cAddrString ? cAddrString : "(null)", port);
    989 
    990     status_t ret;
    991     if (cAddrString && (port > 0xFFFF)) {
    992         ret = BAD_VALUE;
    993     } else {
    994         ret = mp->setRetransmitEndpoint(cAddrString,
    995                 static_cast<uint16_t>(port));
    996     }
    997 
    998     if (NULL != addrString) {
    999         env->ReleaseStringUTFChars(addrString, cAddrString);
   1000     }
   1001 
   1002     if (ret == INVALID_OPERATION ) {
   1003         jniThrowException(env, "java/lang/IllegalStateException", NULL);
   1004     }
   1005 
   1006     return (jint) ret;
   1007 }
   1008 
   1009 static void
   1010 android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
   1011 {
   1012     ALOGV("setNextMediaPlayer");
   1013     sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz);
   1014     if (thisplayer == NULL) {
   1015         jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized");
   1016         return;
   1017     }
   1018     sp<MediaPlayer> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player);
   1019     if (nextplayer == NULL && java_player != NULL) {
   1020         jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized");
   1021         return;
   1022     }
   1023 
   1024     if (nextplayer == thisplayer) {
   1025         jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self");
   1026         return;
   1027     }
   1028     // tie the two players together
   1029     process_media_player_call(
   1030             env, thiz, thisplayer->setNextMediaPlayer(nextplayer),
   1031             "java/lang/IllegalArgumentException",
   1032             "setNextMediaPlayer failed." );
   1033     ;
   1034 }
   1035 
   1036 // ----------------------------------------------------------------------------
   1037 
   1038 static const JNINativeMethod gMethods[] = {
   1039     {
   1040         "nativeSetDataSource",
   1041         "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
   1042         "[Ljava/lang/String;)V",
   1043         (void *)android_media_MediaPlayer_setDataSourceAndHeaders
   1044     },
   1045 
   1046     {"_setDataSource",      "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
   1047     {"_setDataSource",      "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
   1048     {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer_setVideoSurface},
   1049     {"_prepare",            "()V",                              (void *)android_media_MediaPlayer_prepare},
   1050     {"prepareAsync",        "()V",                              (void *)android_media_MediaPlayer_prepareAsync},
   1051     {"_start",              "()V",                              (void *)android_media_MediaPlayer_start},
   1052     {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
   1053     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
   1054     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
   1055     {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
   1056     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
   1057     {"setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer_setSyncParams},
   1058     {"getSyncParams",     "()Landroid/media/SyncParams;",   (void *)android_media_MediaPlayer_getSyncParams},
   1059     {"seekTo",              "(I)V",                             (void *)android_media_MediaPlayer_seekTo},
   1060     {"_pause",              "()V",                              (void *)android_media_MediaPlayer_pause},
   1061     {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer_isPlaying},
   1062     {"getCurrentPosition",  "()I",                              (void *)android_media_MediaPlayer_getCurrentPosition},
   1063     {"getDuration",         "()I",                              (void *)android_media_MediaPlayer_getDuration},
   1064     {"_release",            "()V",                              (void *)android_media_MediaPlayer_release},
   1065     {"_reset",              "()V",                              (void *)android_media_MediaPlayer_reset},
   1066     {"_setAudioStreamType", "(I)V",                             (void *)android_media_MediaPlayer_setAudioStreamType},
   1067     {"_getAudioStreamType", "()I",                              (void *)android_media_MediaPlayer_getAudioStreamType},
   1068     {"setParameter",        "(ILandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer_setParameter},
   1069     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer_setLooping},
   1070     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer_isLooping},
   1071     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer_setVolume},
   1072     {"native_invoke",       "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
   1073     {"native_setMetadataFilter", "(Landroid/os/Parcel;)I",      (void *)android_media_MediaPlayer_setMetadataFilter},
   1074     {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer_getMetadata},
   1075     {"native_init",         "()V",                              (void *)android_media_MediaPlayer_native_init},
   1076     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer_native_setup},
   1077     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer_native_finalize},
   1078     {"getAudioSessionId",   "()I",                              (void *)android_media_MediaPlayer_get_audio_session_id},
   1079     {"setAudioSessionId",   "(I)V",                             (void *)android_media_MediaPlayer_set_audio_session_id},
   1080     {"_setAuxEffectSendLevel", "(F)V",                          (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
   1081     {"attachAuxEffect",     "(I)V",                             (void *)android_media_MediaPlayer_attachAuxEffect},
   1082     {"native_pullBatteryData", "(Landroid/os/Parcel;)I",        (void *)android_media_MediaPlayer_pullBatteryData},
   1083     {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I",  (void *)android_media_MediaPlayer_setRetransmitEndpoint},
   1084     {"setNextMediaPlayer",  "(Landroid/media/MediaPlayer;)V",   (void *)android_media_MediaPlayer_setNextMediaPlayer},
   1085 };
   1086 
   1087 // This function only registers the native methods
   1088 static int register_android_media_MediaPlayer(JNIEnv *env)
   1089 {
   1090     return AndroidRuntime::registerNativeMethods(env,
   1091                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
   1092 }
   1093 extern int register_android_media_ExifInterface(JNIEnv *env);
   1094 extern int register_android_media_ImageReader(JNIEnv *env);
   1095 extern int register_android_media_ImageWriter(JNIEnv *env);
   1096 extern int register_android_media_Crypto(JNIEnv *env);
   1097 extern int register_android_media_Drm(JNIEnv *env);
   1098 extern int register_android_media_MediaCodec(JNIEnv *env);
   1099 extern int register_android_media_MediaExtractor(JNIEnv *env);
   1100 extern int register_android_media_MediaCodecList(JNIEnv *env);
   1101 extern int register_android_media_MediaHTTPConnection(JNIEnv *env);
   1102 extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
   1103 extern int register_android_media_MediaMuxer(JNIEnv *env);
   1104 extern int register_android_media_MediaRecorder(JNIEnv *env);
   1105 extern int register_android_media_MediaScanner(JNIEnv *env);
   1106 extern int register_android_media_MediaSync(JNIEnv *env);
   1107 extern int register_android_media_ResampleInputStream(JNIEnv *env);
   1108 extern int register_android_media_MediaProfiles(JNIEnv *env);
   1109 extern int register_android_media_AmrInputStream(JNIEnv *env);
   1110 extern int register_android_mtp_MtpDatabase(JNIEnv *env);
   1111 extern int register_android_mtp_MtpDevice(JNIEnv *env);
   1112 extern int register_android_mtp_MtpServer(JNIEnv *env);
   1113 
   1114 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
   1115 {
   1116     JNIEnv* env = NULL;
   1117     jint result = -1;
   1118 
   1119     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
   1120         ALOGE("ERROR: GetEnv failed\n");
   1121         goto bail;
   1122     }
   1123     assert(env != NULL);
   1124 
   1125     if (register_android_media_ImageWriter(env) != JNI_OK) {
   1126         ALOGE("ERROR: ImageWriter native registration failed");
   1127         goto bail;
   1128     }
   1129 
   1130     if (register_android_media_ImageReader(env) < 0) {
   1131         ALOGE("ERROR: ImageReader native registration failed");
   1132         goto bail;
   1133     }
   1134 
   1135     if (register_android_media_MediaPlayer(env) < 0) {
   1136         ALOGE("ERROR: MediaPlayer native registration failed\n");
   1137         goto bail;
   1138     }
   1139 
   1140     if (register_android_media_MediaRecorder(env) < 0) {
   1141         ALOGE("ERROR: MediaRecorder native registration failed\n");
   1142         goto bail;
   1143     }
   1144 
   1145     if (register_android_media_MediaScanner(env) < 0) {
   1146         ALOGE("ERROR: MediaScanner native registration failed\n");
   1147         goto bail;
   1148     }
   1149 
   1150     if (register_android_media_MediaMetadataRetriever(env) < 0) {
   1151         ALOGE("ERROR: MediaMetadataRetriever native registration failed\n");
   1152         goto bail;
   1153     }
   1154 
   1155     if (register_android_media_AmrInputStream(env) < 0) {
   1156         ALOGE("ERROR: AmrInputStream native registration failed\n");
   1157         goto bail;
   1158     }
   1159 
   1160     if (register_android_media_ResampleInputStream(env) < 0) {
   1161         ALOGE("ERROR: ResampleInputStream native registration failed\n");
   1162         goto bail;
   1163     }
   1164 
   1165     if (register_android_media_MediaProfiles(env) < 0) {
   1166         ALOGE("ERROR: MediaProfiles native registration failed");
   1167         goto bail;
   1168     }
   1169 
   1170     if (register_android_mtp_MtpDatabase(env) < 0) {
   1171         ALOGE("ERROR: MtpDatabase native registration failed");
   1172         goto bail;
   1173     }
   1174 
   1175     if (register_android_mtp_MtpDevice(env) < 0) {
   1176         ALOGE("ERROR: MtpDevice native registration failed");
   1177         goto bail;
   1178     }
   1179 
   1180     if (register_android_mtp_MtpServer(env) < 0) {
   1181         ALOGE("ERROR: MtpServer native registration failed");
   1182         goto bail;
   1183     }
   1184 
   1185     if (register_android_media_MediaCodec(env) < 0) {
   1186         ALOGE("ERROR: MediaCodec native registration failed");
   1187         goto bail;
   1188     }
   1189 
   1190     if (register_android_media_MediaSync(env) < 0) {
   1191         ALOGE("ERROR: MediaSync native registration failed");
   1192         goto bail;
   1193     }
   1194 
   1195     if (register_android_media_MediaExtractor(env) < 0) {
   1196         ALOGE("ERROR: MediaCodec native registration failed");
   1197         goto bail;
   1198     }
   1199 
   1200     if (register_android_media_MediaMuxer(env) < 0) {
   1201         ALOGE("ERROR: MediaMuxer native registration failed");
   1202         goto bail;
   1203     }
   1204 
   1205     if (register_android_media_MediaCodecList(env) < 0) {
   1206         ALOGE("ERROR: MediaCodec native registration failed");
   1207         goto bail;
   1208     }
   1209 
   1210     if (register_android_media_Crypto(env) < 0) {
   1211         ALOGE("ERROR: MediaCodec native registration failed");
   1212         goto bail;
   1213     }
   1214 
   1215     if (register_android_media_Drm(env) < 0) {
   1216         ALOGE("ERROR: MediaDrm native registration failed");
   1217         goto bail;
   1218     }
   1219 
   1220     if (register_android_media_MediaHTTPConnection(env) < 0) {
   1221         ALOGE("ERROR: MediaHTTPConnection native registration failed");
   1222         goto bail;
   1223     }
   1224 
   1225     if (register_android_media_ExifInterface(env) < 0) {
   1226         ALOGE("ERROR: ExifInterface native registration failed");
   1227         goto bail;
   1228     }
   1229 
   1230     /* success -- return valid version number */
   1231     result = JNI_VERSION_1_4;
   1232 
   1233 bail:
   1234     return result;
   1235 }
   1236 
   1237 // KTHXBYE
   1238