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 
JNIMediaPlayerListener(JNIEnv * env,jobject thiz,jobject weak_thiz)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 
~JNIMediaPlayerListener()109 JNIMediaPlayerListener::~JNIMediaPlayerListener()
110 {
111     // remove global references
112     JNIEnv *env = AndroidRuntime::getJNIEnv();
113     env->DeleteGlobalRef(mObject);
114     env->DeleteGlobalRef(mClass);
115 }
116 
notify(int msg,int ext1,int ext2,const Parcel * obj)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 
getMediaPlayer(JNIEnv * env,jobject thiz)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 
setMediaPlayer(JNIEnv * env,jobject thiz,const sp<MediaPlayer> & player)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.
process_media_player_call(JNIEnv * env,jobject thiz,status_t opStatus,const char * exception,const char * message)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
android_media_MediaPlayer_setDataSourceAndHeaders(JNIEnv * env,jobject thiz,jobject httpServiceBinderObj,jstring path,jobjectArray keys,jobjectArray values)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
android_media_MediaPlayer_setDataSourceFD(JNIEnv * env,jobject thiz,jobject fileDescriptor,jlong offset,jlong length)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
android_media_MediaPlayer_setDataSourceCallback(JNIEnv * env,jobject thiz,jobject dataSource)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>
getVideoSurfaceTexture(JNIEnv * env,jobject thiz)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
decVideoSurfaceRef(JNIEnv * env,jobject thiz)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
setVideoSurface(JNIEnv * env,jobject thiz,jobject jsurface,jboolean mediaPlayerMustBeAlive)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
android_media_MediaPlayer_setVideoSurface(JNIEnv * env,jobject thiz,jobject jsurface)341 android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface)
342 {
343     setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
344 }
345 
346 static void
android_media_MediaPlayer_prepare(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_prepareAsync(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_start(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_stop(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_pause(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_isPlaying(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_setPlaybackParams(JNIEnv * env,jobject thiz,jobject params)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
android_media_MediaPlayer_getPlaybackParams(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_setSyncParams(JNIEnv * env,jobject thiz,jobject params)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
android_media_MediaPlayer_getSyncParams(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_seekTo(JNIEnv * env,jobject thiz,jint msec)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
android_media_MediaPlayer_getVideoWidth(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_getVideoHeight(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_getCurrentPosition(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_getDuration(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_reset(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_setAudioStreamType(JNIEnv * env,jobject thiz,jint streamtype)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
android_media_MediaPlayer_getAudioStreamType(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_setParameter(JNIEnv * env,jobject thiz,jint key,jobject java_request)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
android_media_MediaPlayer_setLooping(JNIEnv * env,jobject thiz,jboolean looping)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
android_media_MediaPlayer_isLooping(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_setVolume(JNIEnv * env,jobject thiz,jfloat leftVolume,jfloat rightVolume)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
android_media_MediaPlayer_invoke(JNIEnv * env,jobject thiz,jobject java_request,jobject java_reply)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
android_media_MediaPlayer_setMetadataFilter(JNIEnv * env,jobject thiz,jobject request)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
android_media_MediaPlayer_getMetadata(JNIEnv * env,jobject thiz,jboolean update_only,jboolean apply_filter,jobject reply)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
android_media_MediaPlayer_native_init(JNIEnv * env)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
android_media_MediaPlayer_native_setup(JNIEnv * env,jobject thiz,jobject weak_this)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
android_media_MediaPlayer_release(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_native_finalize(JNIEnv * env,jobject thiz)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 
android_media_MediaPlayer_set_audio_session_id(JNIEnv * env,jobject thiz,jint sessionId)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 
android_media_MediaPlayer_get_audio_session_id(JNIEnv * env,jobject thiz)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
android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv * env,jobject thiz,jfloat level)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 
android_media_MediaPlayer_attachAuxEffect(JNIEnv * env,jobject thiz,jint effectId)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
android_media_MediaPlayer_pullBatteryData(JNIEnv * env,jobject,jobject java_reply)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
android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv * env,jobject thiz,jstring addrString,jint port)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
android_media_MediaPlayer_setNextMediaPlayer(JNIEnv * env,jobject thiz,jobject java_player)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
register_android_media_MediaPlayer(JNIEnv * env)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 
JNI_OnLoad(JavaVM * vm,void *)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