blob: 3074bb17be24ed7a5da5833695f838a11a81038e [file] [log] [blame]
James Dongc371a022011-04-06 12:16:07 -07001/*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002**
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>
Nicolas Catania20cb94e2009-05-12 23:25:55 -070023#include <media/MediaPlayerInterface.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <stdio.h>
25#include <assert.h>
26#include <limits.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <utils/threads.h>
30#include "jni.h"
31#include "JNIHelp.h"
32#include "android_runtime/AndroidRuntime.h"
Ted Bonkenburg1ee60112011-07-26 09:51:18 -070033#include "android_runtime/android_view_Surface.h"
The Android Open Source Project4df24232009-03-05 14:34:35 -080034#include "utils/Errors.h" // for status_t
Andreas Huber25643002010-01-28 11:19:57 -080035#include "utils/KeyedVector.h"
36#include "utils/String8.h"
James Dong79f407c2011-05-05 12:50:04 -070037#include "android_media_Utils.h"
38
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080039#include "android_os_Parcel.h"
Nicolas Catania20cb94e2009-05-12 23:25:55 -070040#include "android_util_Binder.h"
41#include <binder/Parcel.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080042#include <gui/ISurfaceTexture.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080043#include <gui/Surface.h>
Gloria Wangd211f412011-02-19 18:37:57 -080044#include <binder/IPCThreadState.h>
45#include <binder/IServiceManager.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
47// ----------------------------------------------------------------------------
48
49using namespace android;
50
51// ----------------------------------------------------------------------------
52
53struct fields_t {
54 jfieldID context;
Ted Bonkenburg1ee60112011-07-26 09:51:18 -070055 jfieldID surface_texture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056
57 jmethodID post_event;
58};
59static fields_t fields;
60
61static Mutex sLock;
62
63// ----------------------------------------------------------------------------
64// ref-counted object for callbacks
65class JNIMediaPlayerListener: public MediaPlayerListener
66{
67public:
68 JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
69 ~JNIMediaPlayerListener();
Gloria Wang162ee492011-04-11 17:23:27 -070070 virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071private:
72 JNIMediaPlayerListener();
73 jclass mClass; // Reference to MediaPlayer class
74 jobject mObject; // Weak ref to MediaPlayer Java object to call on
75};
76
77JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
78{
79
80 // Hold onto the MediaPlayer class for use in calling the static method
81 // that posts events to the application thread.
82 jclass clazz = env->GetObjectClass(thiz);
83 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +000084 ALOGE("Can't find android/media/MediaPlayer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 jniThrowException(env, "java/lang/Exception", NULL);
86 return;
87 }
88 mClass = (jclass)env->NewGlobalRef(clazz);
89
90 // We use a weak reference so the MediaPlayer object can be garbage collected.
91 // The reference is only used as a proxy for callbacks.
92 mObject = env->NewGlobalRef(weak_thiz);
93}
94
95JNIMediaPlayerListener::~JNIMediaPlayerListener()
96{
97 // remove global references
98 JNIEnv *env = AndroidRuntime::getJNIEnv();
99 env->DeleteGlobalRef(mObject);
100 env->DeleteGlobalRef(mClass);
101}
102
Gloria Wang162ee492011-04-11 17:23:27 -0700103void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104{
105 JNIEnv *env = AndroidRuntime::getJNIEnv();
Gloria Wang162ee492011-04-11 17:23:27 -0700106 if (obj && obj->dataSize() > 0) {
107 jbyteArray jArray = env->NewByteArray(obj->dataSize());
108 if (jArray != NULL) {
109 jbyte *nArray = env->GetByteArrayElements(jArray, NULL);
110 memcpy(nArray, obj->data(), obj->dataSize());
111 env->ReleaseByteArrayElements(jArray, nArray, 0);
112 env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
113 msg, ext1, ext2, jArray);
114 env->DeleteLocalRef(jArray);
115 }
116 } else {
117 env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
118 msg, ext1, ext2, NULL);
119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120}
121
122// ----------------------------------------------------------------------------
123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
125{
126 Mutex::Autolock l(sLock);
127 MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context);
128 return sp<MediaPlayer>(p);
129}
130
131static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
132{
133 Mutex::Autolock l(sLock);
134 sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context);
135 if (player.get()) {
136 player->incStrong(thiz);
137 }
138 if (old != 0) {
139 old->decStrong(thiz);
140 }
141 env->SetIntField(thiz, fields.context, (int)player.get());
142 return old;
143}
144
Nicolas Catania32f82772009-06-11 16:33:49 -0700145// If exception is NULL and opStatus is not OK, this method sends an error
146// event to the client application; otherwise, if exception is not NULL and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147// opStatus is not OK, this method throws the given exception to the client
148// application.
149static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message)
150{
151 if (exception == NULL) { // Don't throw exception. Instead, send an event.
152 if (opStatus != (status_t) OK) {
153 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
154 if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0);
155 }
156 } else { // Throw exception!
157 if ( opStatus == (status_t) INVALID_OPERATION ) {
158 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Dave Burkefc301b02011-08-30 14:39:17 +0100159 } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
160 jniThrowException(env, "java/lang/SecurityException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 } else if ( opStatus != (status_t) OK ) {
162 if (strlen(message) > 230) {
163 // if the message is too long, don't bother displaying the status code
164 jniThrowException( env, exception, message);
165 } else {
166 char msg[256];
167 // append the status code to the message
168 sprintf(msg, "%s: status=0x%X", message, opStatus);
169 jniThrowException( env, exception, msg);
170 }
171 }
172 }
173}
174
175static void
Andreas Huber25643002010-01-28 11:19:57 -0800176android_media_MediaPlayer_setDataSourceAndHeaders(
James Dong17524dc2011-05-04 13:41:58 -0700177 JNIEnv *env, jobject thiz, jstring path,
178 jobjectArray keys, jobjectArray values) {
179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
181 if (mp == NULL ) {
182 jniThrowException(env, "java/lang/IllegalStateException", NULL);
183 return;
184 }
185
186 if (path == NULL) {
187 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
188 return;
189 }
190
James Dongc371a022011-04-06 12:16:07 -0700191 const char *tmp = env->GetStringUTFChars(path, NULL);
192 if (tmp == NULL) { // Out of memory
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 return;
194 }
Steve Block71f2cf12011-10-20 11:56:00 +0100195 ALOGV("setDataSource: path %s", tmp);
Andreas Huber25643002010-01-28 11:19:57 -0800196
James Dongc371a022011-04-06 12:16:07 -0700197 String8 pathStr(tmp);
198 env->ReleaseStringUTFChars(path, tmp);
199 tmp = NULL;
200
James Dong17524dc2011-05-04 13:41:58 -0700201 // We build a KeyedVector out of the key and val arrays
Andreas Huber25643002010-01-28 11:19:57 -0800202 KeyedVector<String8, String8> headersVector;
James Dong79f407c2011-05-05 12:50:04 -0700203 if (!ConvertKeyValueArraysToKeyedVector(
204 env, keys, values, &headersVector)) {
205 return;
Andreas Huber25643002010-01-28 11:19:57 -0800206 }
207
Andreas Huber25643002010-01-28 11:19:57 -0800208 status_t opStatus =
209 mp->setDataSource(
James Dongc371a022011-04-06 12:16:07 -0700210 pathStr,
James Dong79f407c2011-05-05 12:50:04 -0700211 headersVector.size() > 0? &headersVector : NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212
Andreas Huber25643002010-01-28 11:19:57 -0800213 process_media_player_call(
214 env, thiz, opStatus, "java/io/IOException",
215 "setDataSource failed." );
216}
217
218static void
219android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path)
220{
James Dong17524dc2011-05-04 13:41:58 -0700221 android_media_MediaPlayer_setDataSourceAndHeaders(env, thiz, path, NULL, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222}
223
224static void
225android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
226{
227 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
228 if (mp == NULL ) {
229 jniThrowException(env, "java/lang/IllegalStateException", NULL);
230 return;
231 }
232
233 if (fileDescriptor == NULL) {
234 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
235 return;
236 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700237 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
Steve Block71f2cf12011-10-20 11:56:00 +0100238 ALOGV("setDataSourceFD: fd %d", fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
240}
241
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700242static sp<ISurfaceTexture>
243getVideoSurfaceTexture(JNIEnv* env, jobject thiz) {
244 ISurfaceTexture * const p = (ISurfaceTexture*)env->GetIntField(thiz, fields.surface_texture);
245 return sp<ISurfaceTexture>(p);
Dave Sparks8b0b1742009-05-29 09:01:20 -0700246}
247
248static void
Gloria Wangd59310d2011-09-14 13:59:45 -0700249decVideoSurfaceRef(JNIEnv *env, jobject thiz)
250{
Gloria Wange828beb2011-09-15 15:28:43 -0700251 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
252 if (mp == NULL) {
253 return;
254 }
255
Gloria Wangd59310d2011-09-14 13:59:45 -0700256 sp<ISurfaceTexture> old_st = getVideoSurfaceTexture(env, thiz);
257 if (old_st != NULL) {
258 old_st->decStrong(thiz);
259 }
260}
261
262static void
James Dong43ef9132011-08-12 11:33:27 -0700263setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive)
Dave Sparks8b0b1742009-05-29 09:01:20 -0700264{
265 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
James Dong43ef9132011-08-12 11:33:27 -0700266 if (mp == NULL) {
267 if (mediaPlayerMustBeAlive) {
268 jniThrowException(env, "java/lang/IllegalStateException", NULL);
269 }
Dave Sparks8b0b1742009-05-29 09:01:20 -0700270 return;
271 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700272
Gloria Wangd59310d2011-09-14 13:59:45 -0700273 decVideoSurfaceRef(env, thiz);
274
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700275 sp<ISurfaceTexture> new_st;
276 if (jsurface) {
277 sp<Surface> surface(Surface_getSurface(env, jsurface));
Jamie Gennisf76afc82011-10-14 19:06:55 -0700278 if (surface != NULL) {
279 new_st = surface->getSurfaceTexture();
280 new_st->incStrong(thiz);
281 } else {
282 jniThrowException(env, "java/lang/IllegalArgumentException",
283 "The surface has been released");
284 return;
285 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700286 }
Gloria Wangd59310d2011-09-14 13:59:45 -0700287
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700288 env->SetIntField(thiz, fields.surface_texture, (int)new_st.get());
289
290 // This will fail if the media player has not been initialized yet. This
291 // can be the case if setDisplay() on MediaPlayer.java has been called
292 // before setDataSource(). The redundant call to setVideoSurfaceTexture()
293 // in prepare/prepareAsync covers for this case.
294 mp->setVideoSurfaceTexture(new_st);
Dave Sparks8b0b1742009-05-29 09:01:20 -0700295}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296
297static void
James Dong43ef9132011-08-12 11:33:27 -0700298android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface)
299{
300 setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
301}
302
303static void
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)
305{
306 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
307 if (mp == NULL ) {
308 jniThrowException(env, "java/lang/IllegalStateException", NULL);
309 return;
310 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700311
312 // Handle the case where the display surface was set before the mp was
313 // initialized. We try again to make it stick.
314 sp<ISurfaceTexture> st = getVideoSurfaceTexture(env, thiz);
315 mp->setVideoSurfaceTexture(st);
316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
318}
319
320static void
321android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
322{
323 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
324 if (mp == NULL ) {
325 jniThrowException(env, "java/lang/IllegalStateException", NULL);
326 return;
327 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700328
329 // Handle the case where the display surface was set before the mp was
330 // initialized. We try again to make it stick.
331 sp<ISurfaceTexture> st = getVideoSurfaceTexture(env, thiz);
332 mp->setVideoSurfaceTexture(st);
333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
335}
336
337static void
338android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
339{
Steve Block71f2cf12011-10-20 11:56:00 +0100340 ALOGV("start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
342 if (mp == NULL ) {
343 jniThrowException(env, "java/lang/IllegalStateException", NULL);
344 return;
345 }
346 process_media_player_call( env, thiz, mp->start(), NULL, NULL );
347}
348
349static void
350android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz)
351{
Steve Block71f2cf12011-10-20 11:56:00 +0100352 ALOGV("stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
354 if (mp == NULL ) {
355 jniThrowException(env, "java/lang/IllegalStateException", NULL);
356 return;
357 }
Nicolas Catania32f82772009-06-11 16:33:49 -0700358 process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359}
360
361static void
362android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz)
363{
Steve Block71f2cf12011-10-20 11:56:00 +0100364 ALOGV("pause");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
366 if (mp == NULL ) {
367 jniThrowException(env, "java/lang/IllegalStateException", NULL);
368 return;
369 }
370 process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
371}
372
373static jboolean
374android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz)
375{
376 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
377 if (mp == NULL ) {
378 jniThrowException(env, "java/lang/IllegalStateException", NULL);
379 return false;
380 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800381 const jboolean is_playing = mp->isPlaying();
382
Steve Block71f2cf12011-10-20 11:56:00 +0100383 ALOGV("isPlaying: %d", is_playing);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800384 return is_playing;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385}
386
387static void
388android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, int msec)
389{
390 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
391 if (mp == NULL ) {
392 jniThrowException(env, "java/lang/IllegalStateException", NULL);
393 return;
394 }
Steve Block71f2cf12011-10-20 11:56:00 +0100395 ALOGV("seekTo: %d(msec)", msec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 process_media_player_call( env, thiz, mp->seekTo(msec), NULL, NULL );
397}
398
399static int
400android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz)
401{
402 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
403 if (mp == NULL ) {
404 jniThrowException(env, "java/lang/IllegalStateException", NULL);
405 return 0;
406 }
407 int w;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800408 if (0 != mp->getVideoWidth(&w)) {
Steve Block3762c312012-01-06 19:20:56 +0000409 ALOGE("getVideoWidth failed");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800410 w = 0;
411 }
Steve Block71f2cf12011-10-20 11:56:00 +0100412 ALOGV("getVideoWidth: %d", w);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800413 return w;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414}
415
416static int
417android_media_MediaPlayer_getVideoHeight(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 0;
423 }
424 int h;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800425 if (0 != mp->getVideoHeight(&h)) {
Steve Block3762c312012-01-06 19:20:56 +0000426 ALOGE("getVideoHeight failed");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800427 h = 0;
428 }
Steve Block71f2cf12011-10-20 11:56:00 +0100429 ALOGV("getVideoHeight: %d", h);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800430 return h;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431}
432
433
434static int
435android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz)
436{
437 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
438 if (mp == NULL ) {
439 jniThrowException(env, "java/lang/IllegalStateException", NULL);
440 return 0;
441 }
442 int msec;
443 process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
Steve Block71f2cf12011-10-20 11:56:00 +0100444 ALOGV("getCurrentPosition: %d (msec)", msec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 return msec;
446}
447
448static int
449android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz)
450{
451 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
452 if (mp == NULL ) {
453 jniThrowException(env, "java/lang/IllegalStateException", NULL);
454 return 0;
455 }
456 int msec;
457 process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
Steve Block71f2cf12011-10-20 11:56:00 +0100458 ALOGV("getDuration: %d (msec)", msec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 return msec;
460}
461
462static void
463android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
464{
Steve Block71f2cf12011-10-20 11:56:00 +0100465 ALOGV("reset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
467 if (mp == NULL ) {
468 jniThrowException(env, "java/lang/IllegalStateException", NULL);
469 return;
470 }
471 process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
472}
473
474static void
475android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, int streamtype)
476{
Steve Block71f2cf12011-10-20 11:56:00 +0100477 ALOGV("setAudioStreamType: %d", streamtype);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
479 if (mp == NULL ) {
480 jniThrowException(env, "java/lang/IllegalStateException", NULL);
481 return;
482 }
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800483 process_media_player_call( env, thiz, mp->setAudioStreamType((audio_stream_type_t) streamtype) , NULL, NULL );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484}
485
486static void
487android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
488{
Steve Block71f2cf12011-10-20 11:56:00 +0100489 ALOGV("setLooping: %d", looping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
491 if (mp == NULL ) {
492 jniThrowException(env, "java/lang/IllegalStateException", NULL);
493 return;
494 }
495 process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL );
496}
497
498static jboolean
499android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz)
500{
Steve Block71f2cf12011-10-20 11:56:00 +0100501 ALOGV("isLooping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
503 if (mp == NULL ) {
504 jniThrowException(env, "java/lang/IllegalStateException", NULL);
505 return false;
506 }
507 return mp->isLooping();
508}
509
510static void
511android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, float leftVolume, float rightVolume)
512{
Steve Block71f2cf12011-10-20 11:56:00 +0100513 ALOGV("setVolume: left %f right %f", leftVolume, rightVolume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
515 if (mp == NULL ) {
516 jniThrowException(env, "java/lang/IllegalStateException", NULL);
517 return;
518 }
519 process_media_player_call( env, thiz, mp->setVolume(leftVolume, rightVolume), NULL, NULL );
520}
521
522// FIXME: deprecated
523static jobject
524android_media_MediaPlayer_getFrameAt(JNIEnv *env, jobject thiz, jint msec)
525{
526 return NULL;
527}
528
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700529
530// Sends the request and reply parcels to the media player via the
531// binder interface.
532static jint
533android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz,
534 jobject java_request, jobject java_reply)
535{
536 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
537 if (media_player == NULL ) {
538 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700539 return UNKNOWN_ERROR;
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700540 }
541
542
543 Parcel *request = parcelForJavaObject(env, java_request);
544 Parcel *reply = parcelForJavaObject(env, java_reply);
545
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700546 // Don't use process_media_player_call which use the async loop to
547 // report errors, instead returns the status.
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700548 return media_player->invoke(*request, reply);
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700549}
550
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700551// Sends the new filter to the client.
552static jint
553android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
554{
555 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
556 if (media_player == NULL ) {
557 jniThrowException(env, "java/lang/IllegalStateException", NULL);
558 return UNKNOWN_ERROR;
559 }
560
561 Parcel *filter = parcelForJavaObject(env, request);
562
Nicolas Catania5d55c712009-07-09 09:21:33 -0700563 if (filter == NULL ) {
564 jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
565 return UNKNOWN_ERROR;
566 }
567
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700568 return media_player->setMetadataFilter(*filter);
569}
570
Nicolas Catania5d55c712009-07-09 09:21:33 -0700571static jboolean
572android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
573 jboolean apply_filter, jobject reply)
574{
575 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
576 if (media_player == NULL ) {
577 jniThrowException(env, "java/lang/IllegalStateException", NULL);
578 return false;
579 }
580
581 Parcel *metadata = parcelForJavaObject(env, reply);
582
583 if (metadata == NULL ) {
584 jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
585 return false;
586 }
587
588 metadata->freeData();
589 // On return metadata is positioned at the beginning of the
590 // metadata. Note however that the parcel actually starts with the
591 // return code so you should not rewind the parcel using
592 // setDataPosition(0).
593 return media_player->getMetadata(update_only, apply_filter, metadata) == OK;
594}
595
Marco Nelissen4935d052009-08-03 11:12:58 -0700596// This function gets some field IDs, which in turn causes class initialization.
597// It is called from a static block in MediaPlayer, which won't run until the
598// first time an instance of this class is used.
599static void
600android_media_MediaPlayer_native_init(JNIEnv *env)
601{
602 jclass clazz;
603
604 clazz = env->FindClass("android/media/MediaPlayer");
605 if (clazz == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700606 return;
607 }
608
609 fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
610 if (fields.context == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700611 return;
612 }
613
614 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
615 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
616 if (fields.post_event == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700617 return;
618 }
619
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700620 fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "I");
621 if (fields.surface_texture == NULL) {
Glenn Kastencc562a32011-02-08 17:26:17 -0800622 return;
623 }
Marco Nelissen4935d052009-08-03 11:12:58 -0700624}
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626static void
627android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
628{
Steve Block71f2cf12011-10-20 11:56:00 +0100629 ALOGV("native_setup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 sp<MediaPlayer> mp = new MediaPlayer();
631 if (mp == NULL) {
632 jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
633 return;
634 }
635
636 // create new listener and give it to MediaPlayer
637 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
638 mp->setListener(listener);
639
640 // Stow our new C++ MediaPlayer in an opaque field in the Java object.
641 setMediaPlayer(env, thiz, mp);
642}
643
644static void
645android_media_MediaPlayer_release(JNIEnv *env, jobject thiz)
646{
Steve Block71f2cf12011-10-20 11:56:00 +0100647 ALOGV("release");
Gloria Wangd59310d2011-09-14 13:59:45 -0700648 decVideoSurfaceRef(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0);
650 if (mp != NULL) {
651 // this prevents native callbacks after the object is released
652 mp->setListener(0);
653 mp->disconnect();
654 }
655}
656
657static void
658android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
659{
Steve Block71f2cf12011-10-20 11:56:00 +0100660 ALOGV("native_finalize");
Marco Nelissen8dc20842011-09-28 09:21:11 -0700661 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
662 if (mp != NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000663 ALOGW("MediaPlayer finalized without being released");
Marco Nelissen8dc20842011-09-28 09:21:11 -0700664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 android_media_MediaPlayer_release(env, thiz);
666}
667
Eric Laurent619346f2010-06-21 09:27:30 -0700668static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) {
Steve Block71f2cf12011-10-20 11:56:00 +0100669 ALOGV("set_session_id(): %d", sessionId);
Eric Laurent619346f2010-06-21 09:27:30 -0700670 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->setAudioSessionId(sessionId), NULL, NULL );
676}
677
678static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) {
Steve Block71f2cf12011-10-20 11:56:00 +0100679 ALOGV("get_session_id()");
Eric Laurent619346f2010-06-21 09:27:30 -0700680 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
681 if (mp == NULL ) {
682 jniThrowException(env, "java/lang/IllegalStateException", NULL);
683 return 0;
684 }
685
686 return mp->getAudioSessionId();
687}
688
Eric Laurent7070b362010-07-16 07:43:46 -0700689static void
690android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level)
691{
Steve Block71f2cf12011-10-20 11:56:00 +0100692 ALOGV("setAuxEffectSendLevel: level %f", level);
Eric Laurent7070b362010-07-16 07:43:46 -0700693 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
694 if (mp == NULL ) {
695 jniThrowException(env, "java/lang/IllegalStateException", NULL);
696 return;
697 }
698 process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL );
699}
700
701static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz, jint effectId) {
Steve Block71f2cf12011-10-20 11:56:00 +0100702 ALOGV("attachAuxEffect(): %d", effectId);
Eric Laurent7070b362010-07-16 07:43:46 -0700703 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
704 if (mp == NULL ) {
705 jniThrowException(env, "java/lang/IllegalStateException", NULL);
706 return;
707 }
708 process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
709}
710
Gloria Wangd211f412011-02-19 18:37:57 -0800711static jint
712android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject java_reply)
713{
714 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
715 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
716 if (service.get() == NULL) {
717 jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService");
718 return UNKNOWN_ERROR;
719 }
720
721 Parcel *reply = parcelForJavaObject(env, java_reply);
722
723 return service->pullBatteryData(reply);
724}
725
John Grossman720aa282012-02-22 15:38:35 -0800726static jint
727android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz,
728 jstring addrString, jint port) {
729 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
730 if (mp == NULL ) {
731 jniThrowException(env, "java/lang/IllegalStateException", NULL);
732 return INVALID_OPERATION;
733 }
734
735 const char *cAddrString = NULL;
736
737 if (NULL != addrString) {
738 cAddrString = env->GetStringUTFChars(addrString, NULL);
739 if (cAddrString == NULL) { // Out of memory
740 return NO_MEMORY;
741 }
742 }
743 ALOGV("setRetransmitEndpoint: %s:%d",
744 cAddrString ? cAddrString : "(null)", port);
745
746 status_t ret;
747 if (cAddrString && (port > 0xFFFF)) {
748 ret = BAD_VALUE;
749 } else {
750 ret = mp->setRetransmitEndpoint(cAddrString,
751 static_cast<uint16_t>(port));
752 }
753
754 if (NULL != addrString) {
755 env->ReleaseStringUTFChars(addrString, cAddrString);
756 }
757
758 if (ret == INVALID_OPERATION ) {
759 jniThrowException(env, "java/lang/IllegalStateException", NULL);
760 }
761
762 return ret;
763}
764
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700765static jboolean
766android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
767{
Steve Block71f2cf12011-10-20 11:56:00 +0100768 ALOGV("setParameter: key %d", key);
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700769 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
770 if (mp == NULL ) {
771 jniThrowException(env, "java/lang/IllegalStateException", NULL);
772 return false;
773 }
774
775 Parcel *request = parcelForJavaObject(env, java_request);
776 status_t err = mp->setParameter(key, *request);
777 if (err == OK) {
778 return true;
779 } else {
780 return false;
781 }
782}
783
784static void
785android_media_MediaPlayer_getParameter(JNIEnv *env, jobject thiz, jint key, jobject java_reply)
786{
Steve Block71f2cf12011-10-20 11:56:00 +0100787 ALOGV("getParameter: key %d", key);
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700788 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
789 if (mp == NULL ) {
790 jniThrowException(env, "java/lang/IllegalStateException", NULL);
791 return;
792 }
793
794 Parcel *reply = parcelForJavaObject(env, java_reply);
795 process_media_player_call(env, thiz, mp->getParameter(key, reply), NULL, NULL );
796}
797
Marco Nelissen84b83202012-02-28 16:07:44 -0800798static void
799android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
800{
801 ALOGV("setNextMediaPlayer");
802 sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz);
803 if (thisplayer == NULL) {
804 jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized");
805 return;
806 }
807 sp<MediaPlayer> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player);
808 if (nextplayer == NULL && java_player != NULL) {
809 jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized");
810 return;
811 }
812
813 if (nextplayer == thisplayer) {
814 jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self");
815 return;
816 }
817 // tie the two players together
818 process_media_player_call(
819 env, thiz, thisplayer->setNextMediaPlayer(nextplayer),
820 "java/lang/IllegalArgumentException",
821 "setNextMediaPlayer failed." );
822 ;
823}
824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825// ----------------------------------------------------------------------------
826
827static JNINativeMethod gMethods[] = {
828 {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource},
James Dong17524dc2011-05-04 13:41:58 -0700829
830 {
831 "_setDataSource",
832 "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
833 (void *)android_media_MediaPlayer_setDataSourceAndHeaders
834 },
835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700837 {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 {"prepare", "()V", (void *)android_media_MediaPlayer_prepare},
839 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
840 {"_start", "()V", (void *)android_media_MediaPlayer_start},
841 {"_stop", "()V", (void *)android_media_MediaPlayer_stop},
842 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
843 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
844 {"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo},
845 {"_pause", "()V", (void *)android_media_MediaPlayer_pause},
846 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying},
847 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition},
848 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration},
849 {"_release", "()V", (void *)android_media_MediaPlayer_release},
850 {"_reset", "()V", (void *)android_media_MediaPlayer_reset},
851 {"setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType},
852 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping},
853 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping},
854 {"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume},
855 {"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt},
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700856 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700857 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
Nicolas Catania5d55c712009-07-09 09:21:33 -0700858 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
Marco Nelissen4935d052009-08-03 11:12:58 -0700859 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
861 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
Eric Laurent619346f2010-06-21 09:27:30 -0700862 {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
863 {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
Eric Laurent7070b362010-07-16 07:43:46 -0700864 {"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
865 {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
Gloria Wangd211f412011-02-19 18:37:57 -0800866 {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
Gloria Wangd01ec6e2011-04-25 17:28:22 -0700867 {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter},
868 {"getParameter", "(ILandroid/os/Parcel;)V", (void *)android_media_MediaPlayer_getParameter},
John Grossman720aa282012-02-22 15:38:35 -0800869 {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint},
Marco Nelissen84b83202012-02-28 16:07:44 -0800870 {"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871};
872
873static const char* const kClassPathName = "android/media/MediaPlayer";
874
Marco Nelissen4935d052009-08-03 11:12:58 -0700875// This function only registers the native methods
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876static int register_android_media_MediaPlayer(JNIEnv *env)
877{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 return AndroidRuntime::registerNativeMethods(env,
879 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
880}
881
Andreas Huber88572f72012-02-21 11:47:18 -0800882extern int register_android_media_MediaCodec(JNIEnv *env);
883extern int register_android_media_MediaExtractor(JNIEnv *env);
Andreas Huber5a04bf32012-03-29 16:41:38 -0700884extern int register_android_media_MediaCodecList(JNIEnv *env);
Andreas Huberbfb9fb12009-12-03 11:31:19 -0800885extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886extern int register_android_media_MediaRecorder(JNIEnv *env);
887extern int register_android_media_MediaScanner(JNIEnv *env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888extern int register_android_media_ResampleInputStream(JNIEnv *env);
James Dongc3711942010-01-19 17:45:38 -0800889extern int register_android_media_MediaProfiles(JNIEnv *env);
Andreas Huberbfb9fb12009-12-03 11:31:19 -0800890extern int register_android_media_AmrInputStream(JNIEnv *env);
Mike Lockwood0cd01362010-12-30 11:54:33 -0500891extern int register_android_mtp_MtpDatabase(JNIEnv *env);
Mike Lockwood8182e722010-12-30 15:38:45 -0500892extern int register_android_mtp_MtpDevice(JNIEnv *env);
Mike Lockwood0cd01362010-12-30 11:54:33 -0500893extern int register_android_mtp_MtpServer(JNIEnv *env);
Andreas Huberbfb9fb12009-12-03 11:31:19 -0800894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895jint JNI_OnLoad(JavaVM* vm, void* reserved)
896{
897 JNIEnv* env = NULL;
898 jint result = -1;
899
900 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
Steve Block3762c312012-01-06 19:20:56 +0000901 ALOGE("ERROR: GetEnv failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 goto bail;
903 }
904 assert(env != NULL);
905
906 if (register_android_media_MediaPlayer(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000907 ALOGE("ERROR: MediaPlayer native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 goto bail;
909 }
910
911 if (register_android_media_MediaRecorder(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000912 ALOGE("ERROR: MediaRecorder native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 goto bail;
914 }
915
916 if (register_android_media_MediaScanner(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000917 ALOGE("ERROR: MediaScanner native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 goto bail;
919 }
920
921 if (register_android_media_MediaMetadataRetriever(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000922 ALOGE("ERROR: MediaMetadataRetriever native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 goto bail;
924 }
925
926 if (register_android_media_AmrInputStream(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000927 ALOGE("ERROR: AmrInputStream native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 goto bail;
929 }
930
931 if (register_android_media_ResampleInputStream(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000932 ALOGE("ERROR: ResampleInputStream native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 goto bail;
934 }
935
James Dongc3711942010-01-19 17:45:38 -0800936 if (register_android_media_MediaProfiles(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000937 ALOGE("ERROR: MediaProfiles native registration failed");
James Dongc3711942010-01-19 17:45:38 -0800938 goto bail;
939 }
940
Mike Lockwood0cd01362010-12-30 11:54:33 -0500941 if (register_android_mtp_MtpDatabase(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000942 ALOGE("ERROR: MtpDatabase native registration failed");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400943 goto bail;
944 }
945
Mike Lockwood8182e722010-12-30 15:38:45 -0500946 if (register_android_mtp_MtpDevice(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000947 ALOGE("ERROR: MtpDevice native registration failed");
Mike Lockwood8182e722010-12-30 15:38:45 -0500948 goto bail;
949 }
950
Mike Lockwood0cd01362010-12-30 11:54:33 -0500951 if (register_android_mtp_MtpServer(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +0000952 ALOGE("ERROR: MtpServer native registration failed");
Mike Lockwood81ea83d2010-06-30 17:49:41 -0400953 goto bail;
954 }
955
Andreas Huber88572f72012-02-21 11:47:18 -0800956 if (register_android_media_MediaCodec(env) < 0) {
957 ALOGE("ERROR: MediaCodec native registration failed");
958 goto bail;
959 }
960
961 if (register_android_media_MediaExtractor(env) < 0) {
962 ALOGE("ERROR: MediaCodec native registration failed");
963 goto bail;
964 }
965
Andreas Huber5a04bf32012-03-29 16:41:38 -0700966 if (register_android_media_MediaCodecList(env) < 0) {
967 ALOGE("ERROR: MediaCodec native registration failed");
968 goto bail;
969 }
970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 /* success -- return valid version number */
972 result = JNI_VERSION_1_4;
973
974bail:
975 return result;
976}
977
978// KTHXBYE