blob: febaba9303afa64dabf60e484da9fbe4d3fe080b [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>
Lajos Molnarb3d5fd22015-04-22 13:14:34 -070023#include <media/AudioResamplerPublic.h>
Andreas Huberd2506a52014-01-29 10:32:46 -080024#include <media/IMediaHTTPService.h>
Nicolas Catania20cb94e2009-05-12 23:25:55 -070025#include <media/MediaPlayerInterface.h>
Ray Essick81fbc5b2019-12-07 06:24:59 -080026#include <media/MediaMetricsItem.h>
Dongwon Kangefada5692017-10-09 11:46:39 -070027#include <media/stagefright/foundation/ByteUtils.h> // for FOURCC definition
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028#include <stdio.h>
29#include <assert.h>
30#include <limits.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <utils/threads.h>
34#include "jni.h"
Orion Hodson329c6122020-06-02 13:22:06 +010035#include <nativehelper/JNIPlatformHelp.h>
Colin Cross082aec62020-08-27 04:12:26 +000036#include <nativehelper/ScopedUtfChars.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037#include "android_runtime/AndroidRuntime.h"
Ted Bonkenburg1ee60112011-07-26 09:51:18 -070038#include "android_runtime/android_view_Surface.h"
Ruben Brunk87eac992013-09-09 17:44:59 -070039#include "android_runtime/Log.h"
The Android Open Source Project4df24232009-03-05 14:34:35 -080040#include "utils/Errors.h" // for status_t
Andreas Huber25643002010-01-28 11:19:57 -080041#include "utils/KeyedVector.h"
42#include "utils/String8.h"
Chris Watkins4eaa2932015-03-20 10:31:42 -070043#include "android_media_MediaDataSource.h"
Ray Essick0e0fee12017-01-25 18:01:56 -080044#include "android_media_MediaMetricsJNI.h"
Wei Jia2d61e2b2015-05-08 15:23:28 -070045#include "android_media_PlaybackParams.h"
46#include "android_media_SyncParams.h"
Andy Hung035d4ec2017-01-24 13:45:02 -080047#include "android_media_VolumeShaper.h"
Jooyung Hancb1e8962019-02-21 14:18:11 +090048#include "android_media_Streams.h"
James Dong79f407c2011-05-05 12:50:04 -070049
Jeff Sharkeyd84e1ce2012-03-06 18:26:19 -080050#include "android_os_Parcel.h"
Nicolas Catania20cb94e2009-05-12 23:25:55 -070051#include "android_util_Binder.h"
52#include <binder/Parcel.h>
Andy McFaddend47f7d82012-12-18 09:48:38 -080053#include <gui/IGraphicBufferProducer.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080054#include <gui/Surface.h>
Gloria Wangd211f412011-02-19 18:37:57 -080055#include <binder/IPCThreadState.h>
56#include <binder/IServiceManager.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057
Andreas Huberd2506a52014-01-29 10:32:46 -080058#include "android_util_Binder.h"
Hassan Shojania0b52e952017-01-23 09:06:31 -080059
60// Modular DRM begin
Hassan Shojania0b52e952017-01-23 09:06:31 -080061#define FIND_CLASS(var, className) \
62var = env->FindClass(className); \
63LOG_FATAL_IF(! (var), "Unable to find class " className);
64
Hassan Shojania0b52e952017-01-23 09:06:31 -080065#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
66var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
67LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
68
Hassan Shojania0b52e952017-01-23 09:06:31 -080069struct StateExceptionFields {
70 jmethodID init;
71 jclass classId;
72};
73
Hassan Shojania06b25fb2017-02-06 21:09:42 -080074static StateExceptionFields gStateExceptionFields;
Hassan Shojania0b52e952017-01-23 09:06:31 -080075// Modular DRM end
76
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077// ----------------------------------------------------------------------------
78
79using namespace android;
80
Ivan Lozano330d8762017-08-08 12:51:06 -070081using media::VolumeShaper;
82
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083// ----------------------------------------------------------------------------
84
85struct fields_t {
86 jfieldID context;
Ted Bonkenburg1ee60112011-07-26 09:51:18 -070087 jfieldID surface_texture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088
89 jmethodID post_event;
Andreas Huberd5f9fa52013-05-28 14:39:39 -070090
91 jmethodID proxyConfigGetHost;
92 jmethodID proxyConfigGetPort;
93 jmethodID proxyConfigGetExclusionList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094};
95static fields_t fields;
96
Wei Jia2d61e2b2015-05-08 15:23:28 -070097static PlaybackParams::fields_t gPlaybackParamsFields;
98static SyncParams::fields_t gSyncParamsFields;
Andy Hung035d4ec2017-01-24 13:45:02 -080099static VolumeShaperHelper::fields_t gVolumeShaperFields;
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101static Mutex sLock;
102
103// ----------------------------------------------------------------------------
104// ref-counted object for callbacks
105class JNIMediaPlayerListener: public MediaPlayerListener
106{
107public:
108 JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
109 ~JNIMediaPlayerListener();
Gloria Wang162ee492011-04-11 17:23:27 -0700110 virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111private:
112 JNIMediaPlayerListener();
113 jclass mClass; // Reference to MediaPlayer class
114 jobject mObject; // Weak ref to MediaPlayer Java object to call on
115};
116
117JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
118{
119
120 // Hold onto the MediaPlayer class for use in calling the static method
121 // that posts events to the application thread.
122 jclass clazz = env->GetObjectClass(thiz);
123 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000124 ALOGE("Can't find android/media/MediaPlayer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 jniThrowException(env, "java/lang/Exception", NULL);
126 return;
127 }
128 mClass = (jclass)env->NewGlobalRef(clazz);
129
130 // We use a weak reference so the MediaPlayer object can be garbage collected.
131 // The reference is only used as a proxy for callbacks.
132 mObject = env->NewGlobalRef(weak_thiz);
133}
134
135JNIMediaPlayerListener::~JNIMediaPlayerListener()
136{
137 // remove global references
138 JNIEnv *env = AndroidRuntime::getJNIEnv();
139 env->DeleteGlobalRef(mObject);
140 env->DeleteGlobalRef(mClass);
141}
142
Gloria Wang162ee492011-04-11 17:23:27 -0700143void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144{
145 JNIEnv *env = AndroidRuntime::getJNIEnv();
Gloria Wang162ee492011-04-11 17:23:27 -0700146 if (obj && obj->dataSize() > 0) {
Insun Kang333c0992012-07-10 12:47:03 +0900147 jobject jParcel = createJavaParcelObject(env);
148 if (jParcel != NULL) {
149 Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
Insun Kang89020972012-05-01 14:13:19 +0900150 nativeParcel->setData(obj->data(), obj->dataSize());
Gloria Wang162ee492011-04-11 17:23:27 -0700151 env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
Insun Kang333c0992012-07-10 12:47:03 +0900152 msg, ext1, ext2, jParcel);
Elliott Hughes99f75212013-11-13 15:10:40 -0800153 env->DeleteLocalRef(jParcel);
Gloria Wang162ee492011-04-11 17:23:27 -0700154 }
155 } else {
156 env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
157 msg, ext1, ext2, NULL);
158 }
Insun Kang89020972012-05-01 14:13:19 +0900159 if (env->ExceptionCheck()) {
160 ALOGW("An exception occurred while notifying an event.");
161 LOGW_EX(env);
162 env->ExceptionClear();
163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164}
165
166// ----------------------------------------------------------------------------
167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
169{
170 Mutex::Autolock l(sLock);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000171 MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 return sp<MediaPlayer>(p);
173}
174
175static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
176{
177 Mutex::Autolock l(sLock);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000178 sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 if (player.get()) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800180 player->incStrong((void*)setMediaPlayer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 }
182 if (old != 0) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800183 old->decStrong((void*)setMediaPlayer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000185 env->SetLongField(thiz, fields.context, (jlong)player.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 return old;
187}
188
Nicolas Catania32f82772009-06-11 16:33:49 -0700189// If exception is NULL and opStatus is not OK, this method sends an error
190// event to the client application; otherwise, if exception is not NULL and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191// opStatus is not OK, this method throws the given exception to the client
192// application.
193static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStatus, const char* exception, const char *message)
194{
195 if (exception == NULL) { // Don't throw exception. Instead, send an event.
196 if (opStatus != (status_t) OK) {
197 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
198 if (mp != 0) mp->notify(MEDIA_ERROR, opStatus, 0);
199 }
200 } else { // Throw exception!
201 if ( opStatus == (status_t) INVALID_OPERATION ) {
202 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700203 } else if ( opStatus == (status_t) BAD_VALUE ) {
204 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
Dave Burkefc301b02011-08-30 14:39:17 +0100205 } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
206 jniThrowException(env, "java/lang/SecurityException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 } else if ( opStatus != (status_t) OK ) {
208 if (strlen(message) > 230) {
209 // if the message is too long, don't bother displaying the status code
210 jniThrowException( env, exception, message);
211 } else {
212 char msg[256];
213 // append the status code to the message
214 sprintf(msg, "%s: status=0x%X", message, opStatus);
215 jniThrowException( env, exception, msg);
216 }
217 }
218 }
219}
220
221static void
Andreas Huber25643002010-01-28 11:19:57 -0800222android_media_MediaPlayer_setDataSourceAndHeaders(
Andreas Huberd2506a52014-01-29 10:32:46 -0800223 JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
James Dong17524dc2011-05-04 13:41:58 -0700224 jobjectArray keys, jobjectArray values) {
225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
227 if (mp == NULL ) {
228 jniThrowException(env, "java/lang/IllegalStateException", NULL);
229 return;
230 }
231
232 if (path == NULL) {
233 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
234 return;
235 }
236
James Dongc371a022011-04-06 12:16:07 -0700237 const char *tmp = env->GetStringUTFChars(path, NULL);
238 if (tmp == NULL) { // Out of memory
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 return;
240 }
Steve Block71f2cf12011-10-20 11:56:00 +0100241 ALOGV("setDataSource: path %s", tmp);
Andreas Huber25643002010-01-28 11:19:57 -0800242
James Dongc371a022011-04-06 12:16:07 -0700243 String8 pathStr(tmp);
244 env->ReleaseStringUTFChars(path, tmp);
245 tmp = NULL;
246
James Dong17524dc2011-05-04 13:41:58 -0700247 // We build a KeyedVector out of the key and val arrays
Andreas Huber25643002010-01-28 11:19:57 -0800248 KeyedVector<String8, String8> headersVector;
James Dong79f407c2011-05-05 12:50:04 -0700249 if (!ConvertKeyValueArraysToKeyedVector(
250 env, keys, values, &headersVector)) {
251 return;
Andreas Huber25643002010-01-28 11:19:57 -0800252 }
253
Andreas Huberd2506a52014-01-29 10:32:46 -0800254 sp<IMediaHTTPService> httpService;
255 if (httpServiceBinderObj != NULL) {
256 sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
257 httpService = interface_cast<IMediaHTTPService>(binder);
258 }
259
Andreas Huber25643002010-01-28 11:19:57 -0800260 status_t opStatus =
261 mp->setDataSource(
Andreas Huberd2506a52014-01-29 10:32:46 -0800262 httpService,
Tomasz Wasilczyk835dfe52023-08-17 16:27:22 +0000263 pathStr.c_str(),
James Dong79f407c2011-05-05 12:50:04 -0700264 headersVector.size() > 0? &headersVector : NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
Andreas Huber25643002010-01-28 11:19:57 -0800266 process_media_player_call(
267 env, thiz, opStatus, "java/io/IOException",
268 "setDataSource failed." );
269}
270
271static void
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
273{
274 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
275 if (mp == NULL ) {
276 jniThrowException(env, "java/lang/IllegalStateException", NULL);
277 return;
278 }
279
280 if (fileDescriptor == NULL) {
281 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
282 return;
283 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700284 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
Steve Block71f2cf12011-10-20 11:56:00 +0100285 ALOGV("setDataSourceFD: fd %d", fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
287}
288
Chris Watkins4eaa2932015-03-20 10:31:42 -0700289static void
290android_media_MediaPlayer_setDataSourceCallback(JNIEnv *env, jobject thiz, jobject dataSource)
291{
292 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
293 if (mp == NULL ) {
294 jniThrowException(env, "java/lang/IllegalStateException", NULL);
295 return;
296 }
297
298 if (dataSource == NULL) {
299 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
300 return;
301 }
302 sp<IDataSource> callbackDataSource = new JMediaDataSource(env, dataSource);
303 process_media_player_call(env, thiz, mp->setDataSource(callbackDataSource), "java/lang/RuntimeException", "setDataSourceCallback failed." );
304}
305
Andy McFaddend47f7d82012-12-18 09:48:38 -0800306static sp<IGraphicBufferProducer>
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700307getVideoSurfaceTexture(JNIEnv* env, jobject thiz) {
Ashok Bhat075e9a12014-01-06 13:45:09 +0000308 IGraphicBufferProducer * const p = (IGraphicBufferProducer*)env->GetLongField(thiz, fields.surface_texture);
Andy McFaddend47f7d82012-12-18 09:48:38 -0800309 return sp<IGraphicBufferProducer>(p);
Dave Sparks8b0b1742009-05-29 09:01:20 -0700310}
311
312static void
Gloria Wangd59310d2011-09-14 13:59:45 -0700313decVideoSurfaceRef(JNIEnv *env, jobject thiz)
314{
Gloria Wange828beb2011-09-15 15:28:43 -0700315 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
316 if (mp == NULL) {
317 return;
318 }
319
Andy McFaddend47f7d82012-12-18 09:48:38 -0800320 sp<IGraphicBufferProducer> old_st = getVideoSurfaceTexture(env, thiz);
Gloria Wangd59310d2011-09-14 13:59:45 -0700321 if (old_st != NULL) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800322 old_st->decStrong((void*)decVideoSurfaceRef);
Gloria Wangd59310d2011-09-14 13:59:45 -0700323 }
324}
325
326static void
James Dong43ef9132011-08-12 11:33:27 -0700327setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive)
Dave Sparks8b0b1742009-05-29 09:01:20 -0700328{
329 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
James Dong43ef9132011-08-12 11:33:27 -0700330 if (mp == NULL) {
331 if (mediaPlayerMustBeAlive) {
332 jniThrowException(env, "java/lang/IllegalStateException", NULL);
333 }
Dave Sparks8b0b1742009-05-29 09:01:20 -0700334 return;
335 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700336
Gloria Wangd59310d2011-09-14 13:59:45 -0700337 decVideoSurfaceRef(env, thiz);
338
Andy McFaddend47f7d82012-12-18 09:48:38 -0800339 sp<IGraphicBufferProducer> new_st;
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700340 if (jsurface) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700341 sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
Jamie Gennisf76afc82011-10-14 19:06:55 -0700342 if (surface != NULL) {
Mathias Agopian52800612013-02-14 17:11:20 -0800343 new_st = surface->getIGraphicBufferProducer();
James Dong097922b9c2012-10-04 09:16:40 -0700344 if (new_st == NULL) {
345 jniThrowException(env, "java/lang/IllegalArgumentException",
346 "The surface does not have a binding SurfaceTexture!");
347 return;
348 }
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800349 new_st->incStrong((void*)decVideoSurfaceRef);
Jamie Gennisf76afc82011-10-14 19:06:55 -0700350 } else {
351 jniThrowException(env, "java/lang/IllegalArgumentException",
352 "The surface has been released");
353 return;
354 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700355 }
Gloria Wangd59310d2011-09-14 13:59:45 -0700356
Ashok Bhat075e9a12014-01-06 13:45:09 +0000357 env->SetLongField(thiz, fields.surface_texture, (jlong)new_st.get());
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700358
359 // This will fail if the media player has not been initialized yet. This
360 // can be the case if setDisplay() on MediaPlayer.java has been called
361 // before setDataSource(). The redundant call to setVideoSurfaceTexture()
362 // in prepare/prepareAsync covers for this case.
363 mp->setVideoSurfaceTexture(new_st);
Dave Sparks8b0b1742009-05-29 09:01:20 -0700364}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
366static void
James Dong43ef9132011-08-12 11:33:27 -0700367android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface)
368{
369 setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
370}
371
372static void
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)
374{
375 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
376 if (mp == NULL ) {
377 jniThrowException(env, "java/lang/IllegalStateException", NULL);
378 return;
379 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700380
381 // Handle the case where the display surface was set before the mp was
382 // initialized. We try again to make it stick.
Andy McFaddend47f7d82012-12-18 09:48:38 -0800383 sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700384 mp->setVideoSurfaceTexture(st);
385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
387}
388
389static void
390android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz)
391{
392 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
393 if (mp == NULL ) {
394 jniThrowException(env, "java/lang/IllegalStateException", NULL);
395 return;
396 }
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700397
398 // Handle the case where the display surface was set before the mp was
399 // initialized. We try again to make it stick.
Andy McFaddend47f7d82012-12-18 09:48:38 -0800400 sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700401 mp->setVideoSurfaceTexture(st);
402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
404}
405
406static void
407android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
408{
Steve Block71f2cf12011-10-20 11:56:00 +0100409 ALOGV("start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
411 if (mp == NULL ) {
412 jniThrowException(env, "java/lang/IllegalStateException", NULL);
413 return;
414 }
415 process_media_player_call( env, thiz, mp->start(), NULL, NULL );
416}
417
418static void
419android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz)
420{
Steve Block71f2cf12011-10-20 11:56:00 +0100421 ALOGV("stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
423 if (mp == NULL ) {
424 jniThrowException(env, "java/lang/IllegalStateException", NULL);
425 return;
426 }
Nicolas Catania32f82772009-06-11 16:33:49 -0700427 process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428}
429
430static void
431android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz)
432{
Steve Block71f2cf12011-10-20 11:56:00 +0100433 ALOGV("pause");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
435 if (mp == NULL ) {
436 jniThrowException(env, "java/lang/IllegalStateException", NULL);
437 return;
438 }
439 process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
440}
441
442static jboolean
443android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz)
444{
445 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
446 if (mp == NULL ) {
447 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000448 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800450 const jboolean is_playing = mp->isPlaying();
451
Steve Block71f2cf12011-10-20 11:56:00 +0100452 ALOGV("isPlaying: %d", is_playing);
The Android Open Source Project4df24232009-03-05 14:34:35 -0800453 return is_playing;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454}
455
456static void
Wei Jia2d61e2b2015-05-08 15:23:28 -0700457android_media_MediaPlayer_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params)
Wei Jiad93fcf42015-02-09 16:05:53 -0800458{
459 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
460 if (mp == NULL) {
461 jniThrowException(env, "java/lang/IllegalStateException", NULL);
462 return;
463 }
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700464
Wei Jia2d61e2b2015-05-08 15:23:28 -0700465 PlaybackParams pbp;
466 pbp.fillFromJobject(env, gPlaybackParamsFields, params);
467 ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u",
468 pbp.speedSet, pbp.audioRate.mSpeed,
469 pbp.pitchSet, pbp.audioRate.mPitch,
470 pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode,
471 pbp.audioStretchModeSet, pbp.audioRate.mStretchMode);
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700472
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700473 AudioPlaybackRate rate;
474 status_t err = mp->getPlaybackSettings(&rate);
475 if (err == OK) {
476 bool updatedRate = false;
Wei Jia2d61e2b2015-05-08 15:23:28 -0700477 if (pbp.speedSet) {
478 rate.mSpeed = pbp.audioRate.mSpeed;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700479 updatedRate = true;
480 }
Wei Jia2d61e2b2015-05-08 15:23:28 -0700481 if (pbp.pitchSet) {
482 rate.mPitch = pbp.audioRate.mPitch;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700483 updatedRate = true;
484 }
Wei Jia2d61e2b2015-05-08 15:23:28 -0700485 if (pbp.audioFallbackModeSet) {
486 rate.mFallbackMode = pbp.audioRate.mFallbackMode;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700487 updatedRate = true;
488 }
Wei Jia2d61e2b2015-05-08 15:23:28 -0700489 if (pbp.audioStretchModeSet) {
490 rate.mStretchMode = pbp.audioRate.mStretchMode;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700491 updatedRate = true;
492 }
493 if (updatedRate) {
494 err = mp->setPlaybackSettings(rate);
495 }
496 }
497 process_media_player_call(
498 env, thiz, err,
499 "java/lang/IllegalStateException", "unexpected error");
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700500}
501
502static jobject
Wei Jia2d61e2b2015-05-08 15:23:28 -0700503android_media_MediaPlayer_getPlaybackParams(JNIEnv *env, jobject thiz)
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700504{
505 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
506 if (mp == NULL) {
507 jniThrowException(env, "java/lang/IllegalStateException", NULL);
508 return NULL;
509 }
510
Wei Jia2d61e2b2015-05-08 15:23:28 -0700511 PlaybackParams pbp;
512 AudioPlaybackRate &audioRate = pbp.audioRate;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700513 process_media_player_call(
514 env, thiz, mp->getPlaybackSettings(&audioRate),
515 "java/lang/IllegalStateException", "unexpected error");
Dongwon Kang44801272018-05-23 17:38:35 -0700516 if (env->ExceptionCheck()) {
517 return nullptr;
518 }
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700519 ALOGV("getPlaybackSettings: %f %f %d %d",
520 audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
521
Wei Jia2d61e2b2015-05-08 15:23:28 -0700522 pbp.speedSet = true;
523 pbp.pitchSet = true;
524 pbp.audioFallbackModeSet = true;
525 pbp.audioStretchModeSet = true;
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700526
Wei Jia2d61e2b2015-05-08 15:23:28 -0700527 return pbp.asJobject(env, gPlaybackParamsFields);
Wei Jiad93fcf42015-02-09 16:05:53 -0800528}
529
530static void
Wei Jia2d61e2b2015-05-08 15:23:28 -0700531android_media_MediaPlayer_setSyncParams(JNIEnv *env, jobject thiz, jobject params)
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700532{
533 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
534 if (mp == NULL) {
535 jniThrowException(env, "java/lang/IllegalStateException", NULL);
536 return;
537 }
538
Wei Jia2d61e2b2015-05-08 15:23:28 -0700539 SyncParams scp;
540 scp.fillFromJobject(env, gSyncParamsFields, params);
541 ALOGV("setSyncParams: %d:%d %d:%d %d:%f %d:%f",
542 scp.syncSourceSet, scp.sync.mSource,
543 scp.audioAdjustModeSet, scp.sync.mAudioAdjustMode,
544 scp.toleranceSet, scp.sync.mTolerance,
545 scp.frameRateSet, scp.frameRate);
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700546
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700547 AVSyncSettings avsync;
548 float videoFrameRate;
549 status_t err = mp->getSyncSettings(&avsync, &videoFrameRate);
550 if (err == OK) {
Wei Jia2d61e2b2015-05-08 15:23:28 -0700551 bool updatedSync = scp.frameRateSet;
552 if (scp.syncSourceSet) {
553 avsync.mSource = scp.sync.mSource;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700554 updatedSync = true;
555 }
Wei Jia2d61e2b2015-05-08 15:23:28 -0700556 if (scp.audioAdjustModeSet) {
557 avsync.mAudioAdjustMode = scp.sync.mAudioAdjustMode;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700558 updatedSync = true;
559 }
Wei Jia2d61e2b2015-05-08 15:23:28 -0700560 if (scp.toleranceSet) {
561 avsync.mTolerance = scp.sync.mTolerance;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700562 updatedSync = true;
563 }
564 if (updatedSync) {
Wei Jia2d61e2b2015-05-08 15:23:28 -0700565 err = mp->setSyncSettings(avsync, scp.frameRateSet ? scp.frameRate : -1.f);
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700566 }
567 }
568 process_media_player_call(
569 env, thiz, err,
570 "java/lang/IllegalStateException", "unexpected error");
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700571}
572
573static jobject
Wei Jia2d61e2b2015-05-08 15:23:28 -0700574android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz)
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700575{
576 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
577 if (mp == NULL) {
578 jniThrowException(env, "java/lang/IllegalStateException", NULL);
579 return NULL;
580 }
581
Wei Jia2d61e2b2015-05-08 15:23:28 -0700582 SyncParams scp;
583 scp.frameRate = -1.f;
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700584 process_media_player_call(
Wei Jia2d61e2b2015-05-08 15:23:28 -0700585 env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate),
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700586 "java/lang/IllegalStateException", "unexpected error");
Dongwon Kang44801272018-05-23 17:38:35 -0700587 if (env->ExceptionCheck()) {
588 return nullptr;
589 }
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700590
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700591 ALOGV("getSyncSettings: %d %d %f %f",
Wei Jia2d61e2b2015-05-08 15:23:28 -0700592 scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate);
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700593
Alice Kuoc2c679d2020-07-30 16:14:48 +0000594 // check params
Wei Jia2d61e2b2015-05-08 15:23:28 -0700595 if (scp.sync.mSource >= AVSYNC_SOURCE_MAX
596 || scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
597 || scp.sync.mTolerance < 0.f
598 || scp.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
Lajos Molnar05ebffe2015-04-29 20:41:19 -0700599 jniThrowException(env, "java/lang/IllegalStateException", NULL);
600 return NULL;
601 }
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700602
Wei Jia2d61e2b2015-05-08 15:23:28 -0700603 scp.syncSourceSet = true;
604 scp.audioAdjustModeSet = true;
605 scp.toleranceSet = true;
606 scp.frameRateSet = scp.frameRate >= 0.f;
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700607
Wei Jia2d61e2b2015-05-08 15:23:28 -0700608 return scp.asJobject(env, gSyncParamsFields);
Lajos Molnarc98f58e2015-04-22 19:28:53 -0700609}
610
611static void
Wei Jiabebeaf92017-04-19 16:22:10 -0700612android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jlong msec, jint mode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613{
614 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
615 if (mp == NULL ) {
616 jniThrowException(env, "java/lang/IllegalStateException", NULL);
617 return;
618 }
Wei Jiabebeaf92017-04-19 16:22:10 -0700619 ALOGV("seekTo: %lld(msec), mode=%d", (long long)msec, mode);
620 process_media_player_call( env, thiz, mp->seekTo((int)msec, (MediaPlayerSeekMode)mode), NULL, NULL );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621}
622
Wei Jiac02f09d2017-09-13 18:19:48 -0700623static void
624android_media_MediaPlayer_notifyAt(JNIEnv *env, jobject thiz, jlong mediaTimeUs)
625{
626 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
627 if (mp == NULL) {
628 jniThrowException(env, "java/lang/IllegalStateException", NULL);
629 return;
630 }
631 ALOGV("notifyAt: %lld", (long long)mediaTimeUs);
632 process_media_player_call( env, thiz, mp->notifyAt((int64_t)mediaTimeUs), NULL, NULL );
633}
634
Ashok Bhat075e9a12014-01-06 13:45:09 +0000635static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz)
637{
638 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
639 if (mp == NULL ) {
640 jniThrowException(env, "java/lang/IllegalStateException", NULL);
641 return 0;
642 }
643 int w;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800644 if (0 != mp->getVideoWidth(&w)) {
Steve Block3762c312012-01-06 19:20:56 +0000645 ALOGE("getVideoWidth failed");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800646 w = 0;
647 }
Steve Block71f2cf12011-10-20 11:56:00 +0100648 ALOGV("getVideoWidth: %d", w);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000649 return (jint) w;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650}
651
Ashok Bhat075e9a12014-01-06 13:45:09 +0000652static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz)
654{
655 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
656 if (mp == NULL ) {
657 jniThrowException(env, "java/lang/IllegalStateException", NULL);
658 return 0;
659 }
660 int h;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800661 if (0 != mp->getVideoHeight(&h)) {
Steve Block3762c312012-01-06 19:20:56 +0000662 ALOGE("getVideoHeight failed");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800663 h = 0;
664 }
Steve Block71f2cf12011-10-20 11:56:00 +0100665 ALOGV("getVideoHeight: %d", h);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000666 return (jint) h;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667}
668
Ray Essick0e0fee12017-01-25 18:01:56 -0800669static jobject
Ray Essickf2d0e402017-03-09 10:17:51 -0800670android_media_MediaPlayer_native_getMetrics(JNIEnv *env, jobject thiz)
Ray Essick0e0fee12017-01-25 18:01:56 -0800671{
672 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
673 if (mp == NULL ) {
674 jniThrowException(env, "java/lang/IllegalStateException", NULL);
675 return 0;
676 }
677
678 Parcel p;
679 int key = FOURCC('m','t','r','X');
680 status_t status = mp->getParameter(key, &p);
681 if (status != OK) {
682 ALOGD("getMetrics() failed: %d", status);
683 return (jobject) NULL;
684 }
685
Ray Essick81fbc5b2019-12-07 06:24:59 -0800686 std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create());
Ray Essick0e0fee12017-01-25 18:01:56 -0800687 item->readFromParcel(p);
Ray Essicke9b9c982019-01-28 20:34:42 -0800688 jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item.get(), NULL);
Ray Essick0e0fee12017-01-25 18:01:56 -0800689
690 return mybundle;
691}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692
Ashok Bhat075e9a12014-01-06 13:45:09 +0000693static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz)
695{
696 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
697 if (mp == NULL ) {
698 jniThrowException(env, "java/lang/IllegalStateException", NULL);
699 return 0;
700 }
701 int msec;
702 process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
Steve Block71f2cf12011-10-20 11:56:00 +0100703 ALOGV("getCurrentPosition: %d (msec)", msec);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000704 return (jint) msec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705}
706
Ashok Bhat075e9a12014-01-06 13:45:09 +0000707static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz)
709{
710 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
711 if (mp == NULL ) {
712 jniThrowException(env, "java/lang/IllegalStateException", NULL);
713 return 0;
714 }
715 int msec;
716 process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
Steve Block71f2cf12011-10-20 11:56:00 +0100717 ALOGV("getDuration: %d (msec)", msec);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000718 return (jint) msec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719}
720
721static void
722android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
723{
Steve Block71f2cf12011-10-20 11:56:00 +0100724 ALOGV("reset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
726 if (mp == NULL ) {
727 jniThrowException(env, "java/lang/IllegalStateException", NULL);
728 return;
729 }
730 process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
731}
732
733static void
Ashok Bhat075e9a12014-01-06 13:45:09 +0000734android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, jint streamtype)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735{
Steve Block71f2cf12011-10-20 11:56:00 +0100736 ALOGV("setAudioStreamType: %d", streamtype);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
738 if (mp == NULL ) {
739 jniThrowException(env, "java/lang/IllegalStateException", NULL);
740 return;
741 }
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800742 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 -0800743}
744
John Spurlock1af30c72014-03-10 08:33:35 -0400745static jint
746android_media_MediaPlayer_getAudioStreamType(JNIEnv *env, jobject thiz)
747{
748 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
749 if (mp == NULL ) {
750 jniThrowException(env, "java/lang/IllegalStateException", NULL);
751 return 0;
752 }
753 audio_stream_type_t streamtype;
754 process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL );
755 ALOGV("getAudioStreamType: %d (streamtype)", streamtype);
756 return (jint) streamtype;
757}
758
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -0700759static jboolean
760android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
761{
762 ALOGV("setParameter: key %d", key);
763 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
764 if (mp == NULL ) {
765 jniThrowException(env, "java/lang/IllegalStateException", NULL);
766 return false;
767 }
768
769 Parcel *request = parcelForJavaObject(env, java_request);
770 status_t err = mp->setParameter(key, *request);
771 if (err == OK) {
772 return true;
773 } else {
774 return false;
775 }
776}
777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778static void
779android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
780{
Steve Block71f2cf12011-10-20 11:56:00 +0100781 ALOGV("setLooping: %d", looping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
783 if (mp == NULL ) {
784 jniThrowException(env, "java/lang/IllegalStateException", NULL);
785 return;
786 }
787 process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL );
788}
789
790static jboolean
791android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz)
792{
Steve Block71f2cf12011-10-20 11:56:00 +0100793 ALOGV("isLooping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
795 if (mp == NULL ) {
796 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000797 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000799 return mp->isLooping() ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800}
801
802static void
Ashok Bhat075e9a12014-01-06 13:45:09 +0000803android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, jfloat leftVolume, jfloat rightVolume)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000805 ALOGV("setVolume: left %f right %f", (float) leftVolume, (float) rightVolume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
807 if (mp == NULL ) {
808 jniThrowException(env, "java/lang/IllegalStateException", NULL);
809 return;
810 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000811 process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812}
813
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700814// Sends the request and reply parcels to the media player via the
815// binder interface.
816static jint
817android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz,
818 jobject java_request, jobject java_reply)
819{
820 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
821 if (media_player == NULL ) {
822 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700823 return UNKNOWN_ERROR;
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700824 }
825
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700826 Parcel *request = parcelForJavaObject(env, java_request);
827 Parcel *reply = parcelForJavaObject(env, java_reply);
828
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700829 // Don't use process_media_player_call which use the async loop to
830 // report errors, instead returns the status.
Ashok Bhat075e9a12014-01-06 13:45:09 +0000831 return (jint) media_player->invoke(*request, reply);
Nicolas Catania20cb94e2009-05-12 23:25:55 -0700832}
833
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700834// Sends the new filter to the client.
835static jint
836android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
837{
838 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
839 if (media_player == NULL ) {
840 jniThrowException(env, "java/lang/IllegalStateException", NULL);
841 return UNKNOWN_ERROR;
842 }
843
844 Parcel *filter = parcelForJavaObject(env, request);
845
Nicolas Catania5d55c712009-07-09 09:21:33 -0700846 if (filter == NULL ) {
847 jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
848 return UNKNOWN_ERROR;
849 }
850
Ashok Bhat075e9a12014-01-06 13:45:09 +0000851 return (jint) media_player->setMetadataFilter(*filter);
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700852}
853
Nicolas Catania5d55c712009-07-09 09:21:33 -0700854static jboolean
855android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
856 jboolean apply_filter, jobject reply)
857{
858 sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
859 if (media_player == NULL ) {
860 jniThrowException(env, "java/lang/IllegalStateException", NULL);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000861 return JNI_FALSE;
Nicolas Catania5d55c712009-07-09 09:21:33 -0700862 }
863
864 Parcel *metadata = parcelForJavaObject(env, reply);
865
866 if (metadata == NULL ) {
867 jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
Ashok Bhat075e9a12014-01-06 13:45:09 +0000868 return JNI_FALSE;
Nicolas Catania5d55c712009-07-09 09:21:33 -0700869 }
870
871 metadata->freeData();
872 // On return metadata is positioned at the beginning of the
873 // metadata. Note however that the parcel actually starts with the
874 // return code so you should not rewind the parcel using
875 // setDataPosition(0).
Ashok Bhat075e9a12014-01-06 13:45:09 +0000876 if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) {
877 return JNI_TRUE;
878 } else {
879 return JNI_FALSE;
880 }
Nicolas Catania5d55c712009-07-09 09:21:33 -0700881}
882
Marco Nelissen4935d052009-08-03 11:12:58 -0700883// This function gets some field IDs, which in turn causes class initialization.
884// It is called from a static block in MediaPlayer, which won't run until the
885// first time an instance of this class is used.
886static void
887android_media_MediaPlayer_native_init(JNIEnv *env)
888{
889 jclass clazz;
890
891 clazz = env->FindClass("android/media/MediaPlayer");
892 if (clazz == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700893 return;
894 }
895
Ashok Bhat075e9a12014-01-06 13:45:09 +0000896 fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
Marco Nelissen4935d052009-08-03 11:12:58 -0700897 if (fields.context == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700898 return;
899 }
900
901 fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
902 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
903 if (fields.post_event == NULL) {
Marco Nelissen4935d052009-08-03 11:12:58 -0700904 return;
905 }
906
Ashok Bhat075e9a12014-01-06 13:45:09 +0000907 fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "J");
Ted Bonkenburg1ee60112011-07-26 09:51:18 -0700908 if (fields.surface_texture == NULL) {
Glenn Kastencc562a32011-02-08 17:26:17 -0800909 return;
910 }
Andreas Huberd5f9fa52013-05-28 14:39:39 -0700911
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700912 env->DeleteLocalRef(clazz);
913
Selim Gurun5ba69be2014-05-07 15:04:40 -0700914 clazz = env->FindClass("android/net/ProxyInfo");
Andreas Huberd5f9fa52013-05-28 14:39:39 -0700915 if (clazz == NULL) {
916 return;
917 }
918
919 fields.proxyConfigGetHost =
920 env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;");
921
922 fields.proxyConfigGetPort =
923 env->GetMethodID(clazz, "getPort", "()I");
924
925 fields.proxyConfigGetExclusionList =
Selim Gurun5ba69be2014-05-07 15:04:40 -0700926 env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;");
Lajos Molnarb3d5fd22015-04-22 13:14:34 -0700927
928 env->DeleteLocalRef(clazz);
929
Hassan Shojania0b52e952017-01-23 09:06:31 -0800930 // Modular DRM
Hassan Shojania0b52e952017-01-23 09:06:31 -0800931 FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
932 if (clazz) {
Hassan Shojania06b25fb2017-02-06 21:09:42 -0800933 GET_METHOD_ID(gStateExceptionFields.init, clazz, "<init>", "(ILjava/lang/String;)V");
934 gStateExceptionFields.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
Hassan Shojania0b52e952017-01-23 09:06:31 -0800935
936 env->DeleteLocalRef(clazz);
937 } else {
Hassan Shojania06b25fb2017-02-06 21:09:42 -0800938 ALOGE("JNI android_media_MediaPlayer_native_init couldn't "
Hassan Shojania0b52e952017-01-23 09:06:31 -0800939 "get clazz android/media/MediaDrm$MediaDrmStateException");
940 }
941
Wei Jia2d61e2b2015-05-08 15:23:28 -0700942 gPlaybackParamsFields.init(env);
943 gSyncParamsFields.init(env);
Andy Hung035d4ec2017-01-24 13:45:02 -0800944 gVolumeShaperFields.init(env);
Marco Nelissen4935d052009-08-03 11:12:58 -0700945}
Nicolas Cataniab2c69392009-07-08 08:57:42 -0700946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947static void
Colin Cross082aec62020-08-27 04:12:26 +0000948android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
Svet Ganov2eebf922021-05-20 15:09:08 +0000949 jobject jAttributionSource)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950{
Steve Block71f2cf12011-10-20 11:56:00 +0100951 ALOGV("native_setup");
Philip P. Moltmannfece2432020-07-17 16:39:54 -0700952
Svet Ganov2eebf922021-05-20 15:09:08 +0000953 Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
954 android::content::AttributionSourceState attributionSource;
955 attributionSource.readFromParcel(parcel);
Santiago Seifert05f95dc2021-11-03 12:12:04 +0000956 sp<MediaPlayer> mp = sp<MediaPlayer>::make(attributionSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 if (mp == NULL) {
958 jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
959 return;
960 }
961
962 // create new listener and give it to MediaPlayer
963 sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
964 mp->setListener(listener);
965
966 // Stow our new C++ MediaPlayer in an opaque field in the Java object.
967 setMediaPlayer(env, thiz, mp);
968}
969
970static void
971android_media_MediaPlayer_release(JNIEnv *env, jobject thiz)
972{
Steve Block71f2cf12011-10-20 11:56:00 +0100973 ALOGV("release");
Gloria Wangd59310d2011-09-14 13:59:45 -0700974 decVideoSurfaceRef(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0);
976 if (mp != NULL) {
977 // this prevents native callbacks after the object is released
978 mp->setListener(0);
979 mp->disconnect();
980 }
981}
982
983static void
984android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
985{
Steve Block71f2cf12011-10-20 11:56:00 +0100986 ALOGV("native_finalize");
Marco Nelissen8dc208472011-09-28 09:21:11 -0700987 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
988 if (mp != NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000989 ALOGW("MediaPlayer finalized without being released");
Marco Nelissen8dc208472011-09-28 09:21:11 -0700990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 android_media_MediaPlayer_release(env, thiz);
992}
993
Glenn Kasten33b84042016-03-08 12:02:55 -0800994static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz,
995 jint sessionId) {
Steve Block71f2cf12011-10-20 11:56:00 +0100996 ALOGV("set_session_id(): %d", sessionId);
Eric Laurent619346f2010-06-21 09:27:30 -0700997 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
998 if (mp == NULL ) {
999 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1000 return;
1001 }
Glenn Kasten33b84042016-03-08 12:02:55 -08001002 process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL,
1003 NULL);
Eric Laurent619346f2010-06-21 09:27:30 -07001004}
1005
1006static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) {
Steve Block71f2cf12011-10-20 11:56:00 +01001007 ALOGV("get_session_id()");
Eric Laurent619346f2010-06-21 09:27:30 -07001008 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1009 if (mp == NULL ) {
1010 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1011 return 0;
1012 }
1013
Ashok Bhat075e9a12014-01-06 13:45:09 +00001014 return (jint) mp->getAudioSessionId();
Eric Laurent619346f2010-06-21 09:27:30 -07001015}
1016
Eric Laurent7070b362010-07-16 07:43:46 -07001017static void
1018android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level)
1019{
Steve Block71f2cf12011-10-20 11:56:00 +01001020 ALOGV("setAuxEffectSendLevel: level %f", level);
Eric Laurent7070b362010-07-16 07:43:46 -07001021 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1022 if (mp == NULL ) {
1023 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1024 return;
1025 }
1026 process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL );
1027}
1028
1029static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env, jobject thiz, jint effectId) {
Steve Block71f2cf12011-10-20 11:56:00 +01001030 ALOGV("attachAuxEffect(): %d", effectId);
Eric Laurent7070b362010-07-16 07:43:46 -07001031 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1032 if (mp == NULL ) {
1033 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1034 return;
1035 }
1036 process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
1037}
1038
Gloria Wangd211f412011-02-19 18:37:57 -08001039static jint
Andreas Huberd2506a52014-01-29 10:32:46 -08001040android_media_MediaPlayer_pullBatteryData(
1041 JNIEnv *env, jobject /* thiz */, jobject java_reply)
Gloria Wangd211f412011-02-19 18:37:57 -08001042{
1043 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
1044 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
1045 if (service.get() == NULL) {
1046 jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService");
1047 return UNKNOWN_ERROR;
1048 }
1049
1050 Parcel *reply = parcelForJavaObject(env, java_reply);
1051
Ashok Bhat075e9a12014-01-06 13:45:09 +00001052 return (jint) service->pullBatteryData(reply);
Gloria Wangd211f412011-02-19 18:37:57 -08001053}
1054
John Grossman720aa282012-02-22 15:38:35 -08001055static jint
1056android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz,
1057 jstring addrString, jint port) {
1058 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1059 if (mp == NULL ) {
1060 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1061 return INVALID_OPERATION;
1062 }
1063
1064 const char *cAddrString = NULL;
1065
1066 if (NULL != addrString) {
1067 cAddrString = env->GetStringUTFChars(addrString, NULL);
1068 if (cAddrString == NULL) { // Out of memory
1069 return NO_MEMORY;
1070 }
1071 }
1072 ALOGV("setRetransmitEndpoint: %s:%d",
1073 cAddrString ? cAddrString : "(null)", port);
1074
1075 status_t ret;
1076 if (cAddrString && (port > 0xFFFF)) {
1077 ret = BAD_VALUE;
1078 } else {
1079 ret = mp->setRetransmitEndpoint(cAddrString,
1080 static_cast<uint16_t>(port));
1081 }
1082
1083 if (NULL != addrString) {
1084 env->ReleaseStringUTFChars(addrString, cAddrString);
1085 }
1086
1087 if (ret == INVALID_OPERATION ) {
1088 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1089 }
1090
Ashok Bhat075e9a12014-01-06 13:45:09 +00001091 return (jint) ret;
John Grossman720aa282012-02-22 15:38:35 -08001092}
1093
Marco Nelissen84b83202012-02-28 16:07:44 -08001094static void
1095android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
1096{
1097 ALOGV("setNextMediaPlayer");
1098 sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz);
1099 if (thisplayer == NULL) {
1100 jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized");
1101 return;
1102 }
1103 sp<MediaPlayer> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player);
1104 if (nextplayer == NULL && java_player != NULL) {
1105 jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized");
1106 return;
1107 }
1108
1109 if (nextplayer == thisplayer) {
1110 jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self");
1111 return;
1112 }
1113 // tie the two players together
1114 process_media_player_call(
1115 env, thiz, thisplayer->setNextMediaPlayer(nextplayer),
1116 "java/lang/IllegalArgumentException",
1117 "setNextMediaPlayer failed." );
1118 ;
1119}
1120
Andy Hung035d4ec2017-01-24 13:45:02 -08001121// Pass through the arguments to the MediaServer player implementation.
1122static jint android_media_MediaPlayer_applyVolumeShaper(JNIEnv *env, jobject thiz,
1123 jobject jconfig, jobject joperation) {
1124 // NOTE: hard code here to prevent platform issues. Must match VolumeShaper.java
1125 const int VOLUME_SHAPER_INVALID_OPERATION = -38;
1126
1127 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1128 if (mp == nullptr) {
1129 return (jint)VOLUME_SHAPER_INVALID_OPERATION;
1130 }
1131
1132 sp<VolumeShaper::Configuration> configuration;
1133 sp<VolumeShaper::Operation> operation;
1134 if (jconfig != nullptr) {
1135 configuration = VolumeShaperHelper::convertJobjectToConfiguration(
1136 env, gVolumeShaperFields, jconfig);
1137 ALOGV("applyVolumeShaper configuration: %s", configuration->toString().c_str());
1138 }
1139 if (joperation != nullptr) {
1140 operation = VolumeShaperHelper::convertJobjectToOperation(
1141 env, gVolumeShaperFields, joperation);
1142 ALOGV("applyVolumeShaper operation: %s", operation->toString().c_str());
1143 }
1144 VolumeShaper::Status status = mp->applyVolumeShaper(configuration, operation);
1145 if (status == INVALID_OPERATION) {
1146 status = VOLUME_SHAPER_INVALID_OPERATION;
1147 }
1148 return (jint)status; // if status < 0 an error, else a VolumeShaper id
1149}
1150
1151// Pass through the arguments to the MediaServer player implementation.
1152static jobject android_media_MediaPlayer_getVolumeShaperState(JNIEnv *env, jobject thiz,
1153 jint id) {
1154 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1155 if (mp == nullptr) {
1156 return (jobject)nullptr;
1157 }
1158
1159 sp<VolumeShaper::State> state = mp->getVolumeShaperState((int)id);
1160 if (state.get() == nullptr) {
1161 return (jobject)nullptr;
1162 }
1163 return VolumeShaperHelper::convertStateToJobject(env, gVolumeShaperFields, state);
1164}
1165
Hassan Shojania0b52e952017-01-23 09:06:31 -08001166/////////////////////////////////////////////////////////////////////////////////////
1167// Modular DRM begin
1168
1169// TODO: investigate if these can be shared with their MediaDrm counterparts
1170static void throwDrmStateException(JNIEnv *env, const char *msg, status_t err)
1171{
1172 ALOGE("Illegal DRM state exception: %s (%d)", msg, err);
1173
Hassan Shojania06b25fb2017-02-06 21:09:42 -08001174 jobject exception = env->NewObject(gStateExceptionFields.classId,
1175 gStateExceptionFields.init, static_cast<int>(err),
Hassan Shojania0b52e952017-01-23 09:06:31 -08001176 env->NewStringUTF(msg));
1177 env->Throw(static_cast<jthrowable>(exception));
1178}
1179
1180// TODO: investigate if these can be shared with their MediaDrm counterparts
1181static bool throwDrmExceptionAsNecessary(JNIEnv *env, status_t err, const char *msg = NULL)
1182{
1183 const char *drmMessage = "Unknown DRM Msg";
1184
1185 switch (err) {
1186 case ERROR_DRM_UNKNOWN:
1187 drmMessage = "General DRM error";
1188 break;
1189 case ERROR_DRM_NO_LICENSE:
1190 drmMessage = "No license";
1191 break;
1192 case ERROR_DRM_LICENSE_EXPIRED:
1193 drmMessage = "License expired";
1194 break;
1195 case ERROR_DRM_SESSION_NOT_OPENED:
1196 drmMessage = "Session not opened";
1197 break;
1198 case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
1199 drmMessage = "Not initialized";
1200 break;
1201 case ERROR_DRM_DECRYPT:
1202 drmMessage = "Decrypt error";
1203 break;
1204 case ERROR_DRM_CANNOT_HANDLE:
1205 drmMessage = "Unsupported scheme or data format";
1206 break;
1207 case ERROR_DRM_TAMPER_DETECTED:
1208 drmMessage = "Invalid state";
1209 break;
1210 default:
1211 break;
1212 }
1213
1214 String8 vendorMessage;
1215 if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
1216 vendorMessage = String8::format("DRM vendor-defined error: %d", err);
Tomasz Wasilczyk3815d342023-08-10 23:54:44 +00001217 drmMessage = vendorMessage.c_str();
Hassan Shojania0b52e952017-01-23 09:06:31 -08001218 }
1219
1220 if (err == BAD_VALUE) {
1221 jniThrowException(env, "java/lang/IllegalArgumentException", msg);
1222 return true;
1223 } else if (err == ERROR_DRM_NOT_PROVISIONED) {
1224 jniThrowException(env, "android/media/NotProvisionedException", msg);
1225 return true;
1226 } else if (err == ERROR_DRM_RESOURCE_BUSY) {
1227 jniThrowException(env, "android/media/ResourceBusyException", msg);
1228 return true;
1229 } else if (err == ERROR_DRM_DEVICE_REVOKED) {
1230 jniThrowException(env, "android/media/DeniedByServerException", msg);
1231 return true;
1232 } else if (err == DEAD_OBJECT) {
1233 jniThrowException(env, "android/media/MediaDrmResetException",
1234 "mediaserver died");
1235 return true;
1236 } else if (err != OK) {
1237 String8 errbuf;
1238 if (drmMessage != NULL) {
1239 if (msg == NULL) {
1240 msg = drmMessage;
1241 } else {
1242 errbuf = String8::format("%s: %s", msg, drmMessage);
Tomasz Wasilczyk3815d342023-08-10 23:54:44 +00001243 msg = errbuf.c_str();
Hassan Shojania0b52e952017-01-23 09:06:31 -08001244 }
1245 }
1246 throwDrmStateException(env, msg, err);
1247 return true;
1248 }
1249 return false;
1250}
1251
Hassan Shojania0b52e952017-01-23 09:06:31 -08001252static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray)
1253{
1254 Vector<uint8_t> vector;
1255 size_t length = env->GetArrayLength(byteArray);
1256 vector.insertAt((size_t)0, length);
1257 env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
1258 return vector;
1259}
1260
Hassan Shojania0b52e952017-01-23 09:06:31 -08001261static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
Hassan Shojania06b25fb2017-02-06 21:09:42 -08001262 jbyteArray uuidObj, jbyteArray drmSessionIdObj)
Hassan Shojania0b52e952017-01-23 09:06:31 -08001263{
1264 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1265 if (mp == NULL) {
1266 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1267 return;
1268 }
1269
1270 if (uuidObj == NULL) {
1271 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1272 return;
1273 }
1274
1275 Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1276
1277 if (uuid.size() != 16) {
1278 jniThrowException(
1279 env,
1280 "java/lang/IllegalArgumentException",
1281 "invalid UUID size, expected 16 bytes");
1282 return;
1283 }
1284
Hassan Shojania06b25fb2017-02-06 21:09:42 -08001285 Vector<uint8_t> drmSessionId = JByteArrayToVector(env, drmSessionIdObj);
1286
1287 if (drmSessionId.size() == 0) {
1288 jniThrowException(
1289 env,
1290 "java/lang/IllegalArgumentException",
1291 "empty drmSessionId");
1292 return;
1293 }
1294
1295 status_t err = mp->prepareDrm(uuid.array(), drmSessionId);
Hassan Shojania0b52e952017-01-23 09:06:31 -08001296 if (err != OK) {
1297 if (err == INVALID_OPERATION) {
1298 jniThrowException(
1299 env,
1300 "java/lang/IllegalStateException",
Hassan Shojania06b25fb2017-02-06 21:09:42 -08001301 "The player must be in prepared state.");
Hassan Shojania0b52e952017-01-23 09:06:31 -08001302 } else if (err == ERROR_DRM_CANNOT_HANDLE) {
1303 jniThrowException(
1304 env,
1305 "android/media/UnsupportedSchemeException",
1306 "Failed to instantiate drm object.");
1307 } else {
1308 throwDrmExceptionAsNecessary(env, err, "Failed to prepare DRM scheme");
1309 }
1310 }
1311}
1312
1313static void android_media_MediaPlayer_releaseDrm(JNIEnv *env, jobject thiz)
1314{
1315 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1316 if (mp == NULL ) {
1317 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1318 return;
1319 }
1320
1321 status_t err = mp->releaseDrm();
1322 if (err != OK) {
1323 if (err == INVALID_OPERATION) {
1324 jniThrowException(
1325 env,
1326 "java/lang/IllegalStateException",
Hassan Shojania06b25fb2017-02-06 21:09:42 -08001327 "Can not release DRM in an active player state.");
Hassan Shojania0b52e952017-01-23 09:06:31 -08001328 }
1329 }
1330}
Hassan Shojania0b52e952017-01-23 09:06:31 -08001331// Modular DRM end
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332// ----------------------------------------------------------------------------
1333
jiabin6e5a6282017-10-06 09:34:23 -07001334/////////////////////////////////////////////////////////////////////////////////////
1335// AudioRouting begin
1336static jboolean android_media_MediaPlayer_setOutputDevice(JNIEnv *env, jobject thiz, jint device_id)
1337{
1338 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1339 if (mp == NULL) {
1340 return false;
1341 }
1342 return mp->setOutputDevice(device_id) == NO_ERROR;
1343}
1344
1345static jint android_media_MediaPlayer_getRoutedDeviceId(JNIEnv *env, jobject thiz)
1346{
1347 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1348 if (mp == NULL) {
1349 return AUDIO_PORT_HANDLE_NONE;
1350 }
1351 return mp->getRoutedDeviceId();
1352}
1353
1354static void android_media_MediaPlayer_enableDeviceCallback(
1355 JNIEnv* env, jobject thiz, jboolean enabled)
1356{
1357 sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1358 if (mp == NULL) {
1359 return;
1360 }
1361
1362 status_t status = mp->enableAudioDeviceCallback(enabled);
1363 if (status != NO_ERROR) {
1364 jniThrowException(env, "java/lang/IllegalStateException", NULL);
1365 ALOGE("enable device callback failed: %d", status);
1366 }
1367}
1368
1369// AudioRouting end
1370// ----------------------------------------------------------------------------
1371
Daniel Micay76f6a862015-09-19 17:31:01 -04001372static const JNINativeMethod gMethods[] = {
James Dong17524dc2011-05-04 13:41:58 -07001373 {
Andreas Huberd2506a52014-01-29 10:32:46 -08001374 "nativeSetDataSource",
1375 "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
1376 "[Ljava/lang/String;)V",
James Dong17524dc2011-05-04 13:41:58 -07001377 (void *)android_media_MediaPlayer_setDataSourceAndHeaders
1378 },
1379
Chris Watkins4eaa2932015-03-20 10:31:42 -07001380 {"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
1381 {"_setDataSource", "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
Ted Bonkenburg1ee60112011-07-26 09:51:18 -07001382 {"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer_setVideoSurface},
Robert Shihc42a96d2014-07-25 11:08:50 -07001383 {"_prepare", "()V", (void *)android_media_MediaPlayer_prepare},
Robert Shih07830aa2015-05-27 18:11:44 -07001384 {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 {"_start", "()V", (void *)android_media_MediaPlayer_start},
1386 {"_stop", "()V", (void *)android_media_MediaPlayer_stop},
1387 {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
1388 {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
Ray Essick10353e32017-04-14 10:22:55 -07001389 {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer_native_getMetrics},
Wei Jia2d61e2b2015-05-08 15:23:28 -07001390 {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
1391 {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
1392 {"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer_setSyncParams},
1393 {"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer_getSyncParams},
Wei Jiabebeaf92017-04-19 16:22:10 -07001394 {"_seekTo", "(JI)V", (void *)android_media_MediaPlayer_seekTo},
Wei Jiac02f09d2017-09-13 18:19:48 -07001395 {"_notifyAt", "(J)V", (void *)android_media_MediaPlayer_notifyAt},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 {"_pause", "()V", (void *)android_media_MediaPlayer_pause},
1397 {"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying},
1398 {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer_getCurrentPosition},
1399 {"getDuration", "()I", (void *)android_media_MediaPlayer_getDuration},
1400 {"_release", "()V", (void *)android_media_MediaPlayer_release},
1401 {"_reset", "()V", (void *)android_media_MediaPlayer_reset},
John Spurlock1af30c72014-03-10 08:33:35 -04001402 {"_setAudioStreamType", "(I)V", (void *)android_media_MediaPlayer_setAudioStreamType},
1403 {"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer_getAudioStreamType},
Jean-Michel Trivi8df982d2014-06-26 12:05:16 -07001404 {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 {"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping},
1406 {"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping},
John Spurlock1af30c72014-03-10 08:33:35 -04001407 {"_setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume},
Nicolas Catania20cb94e2009-05-12 23:25:55 -07001408 {"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
Nicolas Cataniab2c69392009-07-08 08:57:42 -07001409 {"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
Nicolas Catania5d55c712009-07-09 09:21:33 -07001410 {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
Marco Nelissen4935d052009-08-03 11:12:58 -07001411 {"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
Svet Ganov2eebf922021-05-20 15:09:08 +00001412 {"native_setup", "(Ljava/lang/Object;Landroid/os/Parcel;)V",(void *)android_media_MediaPlayer_native_setup},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 {"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
Eric Laurent619346f2010-06-21 09:27:30 -07001414 {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
Eric Laurent53945a42021-01-29 21:24:08 +01001415 {"native_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
John Spurlock1af30c72014-03-10 08:33:35 -04001416 {"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
Eric Laurent7070b362010-07-16 07:43:46 -07001417 {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
Gloria Wangd211f412011-02-19 18:37:57 -08001418 {"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
John Grossman720aa282012-02-22 15:38:35 -08001419 {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint},
Marco Nelissen84b83202012-02-28 16:07:44 -08001420 {"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer},
Andy Hung035d4ec2017-01-24 13:45:02 -08001421 {"native_applyVolumeShaper",
1422 "(Landroid/media/VolumeShaper$Configuration;Landroid/media/VolumeShaper$Operation;)I",
1423 (void *)android_media_MediaPlayer_applyVolumeShaper},
1424 {"native_getVolumeShaperState",
1425 "(I)Landroid/media/VolumeShaper$State;",
1426 (void *)android_media_MediaPlayer_getVolumeShaperState},
Hassan Shojania0b52e952017-01-23 09:06:31 -08001427 // Modular DRM
Hassan Shojania06b25fb2017-02-06 21:09:42 -08001428 { "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer_prepareDrm },
Hassan Shojania0b52e952017-01-23 09:06:31 -08001429 { "_releaseDrm", "()V", (void *)android_media_MediaPlayer_releaseDrm },
jiabin6e5a6282017-10-06 09:34:23 -07001430
1431 // AudioRouting
1432 {"native_setOutputDevice", "(I)Z", (void *)android_media_MediaPlayer_setOutputDevice},
1433 {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaPlayer_getRoutedDeviceId},
1434 {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaPlayer_enableDeviceCallback},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435};
1436
Marco Nelissen4935d052009-08-03 11:12:58 -07001437// This function only registers the native methods
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438static int register_android_media_MediaPlayer(JNIEnv *env)
1439{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 return AndroidRuntime::registerNativeMethods(env,
1441 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
1442}
Zhijun He212e78d2013-06-07 11:36:23 -07001443extern int register_android_media_ImageReader(JNIEnv *env);
Zhijun Hef6a09e52015-02-24 18:12:23 -08001444extern int register_android_media_ImageWriter(JNIEnv *env);
Marco Nelissen5ff11732019-10-17 08:55:52 -07001445extern int register_android_media_JetPlayer(JNIEnv *env);
Andreas Huber8240d922012-04-04 14:06:32 -07001446extern int register_android_media_Crypto(JNIEnv *env);
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001447extern int register_android_media_Drm(JNIEnv *env);
Chong Zhangd5927ae2017-01-03 11:07:18 -08001448extern int register_android_media_Descrambler(JNIEnv *env);
Andreas Huber88572f72012-02-21 11:47:18 -08001449extern int register_android_media_MediaCodec(JNIEnv *env);
1450extern int register_android_media_MediaExtractor(JNIEnv *env);
Andreas Huber5a04bf32012-03-29 16:41:38 -07001451extern int register_android_media_MediaCodecList(JNIEnv *env);
Andreas Huberd2506a52014-01-29 10:32:46 -08001452extern int register_android_media_MediaHTTPConnection(JNIEnv *env);
Andreas Huberbfb9fb12009-12-03 11:31:19 -08001453extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
ztenghui68ccf102013-02-13 14:07:02 -08001454extern int register_android_media_MediaMuxer(JNIEnv *env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455extern int register_android_media_MediaRecorder(JNIEnv *env);
Wei Jia071a8b72015-03-09 16:38:25 -07001456extern int register_android_media_MediaSync(JNIEnv *env);
Sally Qiaba398d2021-12-06 16:37:50 -08001457extern int register_android_media_PublicFormatUtils(JNIEnv *env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458extern int register_android_media_ResampleInputStream(JNIEnv *env);
James Dongc3711942010-01-19 17:45:38 -08001459extern int register_android_media_MediaProfiles(JNIEnv *env);
Mike Lockwood0cd01362010-12-30 11:54:33 -05001460extern int register_android_mtp_MtpDatabase(JNIEnv *env);
Mike Lockwood8182e722010-12-30 15:38:45 -05001461extern int register_android_mtp_MtpDevice(JNIEnv *env);
Mike Lockwood0cd01362010-12-30 11:54:33 -05001462extern int register_android_mtp_MtpServer(JNIEnv *env);
Andreas Huberbfb9fb12009-12-03 11:31:19 -08001463
Andreas Huberd2506a52014-01-29 10:32:46 -08001464jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465{
1466 JNIEnv* env = NULL;
1467 jint result = -1;
1468
1469 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
Steve Block3762c312012-01-06 19:20:56 +00001470 ALOGE("ERROR: GetEnv failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 goto bail;
1472 }
1473 assert(env != NULL);
1474
Zhijun Hef6a09e52015-02-24 18:12:23 -08001475 if (register_android_media_ImageWriter(env) != JNI_OK) {
1476 ALOGE("ERROR: ImageWriter native registration failed");
1477 goto bail;
1478 }
1479
Zhijun He212e78d2013-06-07 11:36:23 -07001480 if (register_android_media_ImageReader(env) < 0) {
1481 ALOGE("ERROR: ImageReader native registration failed");
1482 goto bail;
1483 }
1484
Marco Nelissen5ff11732019-10-17 08:55:52 -07001485 if (register_android_media_JetPlayer(env) < 0) {
1486 ALOGE("ERROR: JetPlayer native registration failed");
1487 goto bail;
1488 }
1489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 if (register_android_media_MediaPlayer(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001491 ALOGE("ERROR: MediaPlayer native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 goto bail;
1493 }
1494
1495 if (register_android_media_MediaRecorder(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001496 ALOGE("ERROR: MediaRecorder native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 goto bail;
1498 }
1499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 if (register_android_media_MediaMetadataRetriever(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001501 ALOGE("ERROR: MediaMetadataRetriever native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 goto bail;
1503 }
1504
Sally Qiaba398d2021-12-06 16:37:50 -08001505 if (register_android_media_PublicFormatUtils(env) < 0) {
1506 ALOGE("ERROR: PublicFormatUtils native registration failed\n");
1507 goto bail;
1508 }
1509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 if (register_android_media_ResampleInputStream(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001511 ALOGE("ERROR: ResampleInputStream native registration failed\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 goto bail;
1513 }
1514
James Dongc3711942010-01-19 17:45:38 -08001515 if (register_android_media_MediaProfiles(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001516 ALOGE("ERROR: MediaProfiles native registration failed");
James Dongc3711942010-01-19 17:45:38 -08001517 goto bail;
1518 }
1519
Mike Lockwood0cd01362010-12-30 11:54:33 -05001520 if (register_android_mtp_MtpDatabase(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001521 ALOGE("ERROR: MtpDatabase native registration failed");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001522 goto bail;
1523 }
1524
Mike Lockwood8182e722010-12-30 15:38:45 -05001525 if (register_android_mtp_MtpDevice(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001526 ALOGE("ERROR: MtpDevice native registration failed");
Mike Lockwood8182e722010-12-30 15:38:45 -05001527 goto bail;
1528 }
1529
Mike Lockwood0cd01362010-12-30 11:54:33 -05001530 if (register_android_mtp_MtpServer(env) < 0) {
Steve Block3762c312012-01-06 19:20:56 +00001531 ALOGE("ERROR: MtpServer native registration failed");
Mike Lockwood81ea83d2010-06-30 17:49:41 -04001532 goto bail;
1533 }
1534
Andreas Huber88572f72012-02-21 11:47:18 -08001535 if (register_android_media_MediaCodec(env) < 0) {
1536 ALOGE("ERROR: MediaCodec native registration failed");
1537 goto bail;
1538 }
1539
Wei Jia071a8b72015-03-09 16:38:25 -07001540 if (register_android_media_MediaSync(env) < 0) {
1541 ALOGE("ERROR: MediaSync native registration failed");
1542 goto bail;
1543 }
1544
Andreas Huber88572f72012-02-21 11:47:18 -08001545 if (register_android_media_MediaExtractor(env) < 0) {
1546 ALOGE("ERROR: MediaCodec native registration failed");
1547 goto bail;
1548 }
1549
ztenghui68ccf102013-02-13 14:07:02 -08001550 if (register_android_media_MediaMuxer(env) < 0) {
1551 ALOGE("ERROR: MediaMuxer native registration failed");
1552 goto bail;
1553 }
1554
Andreas Huber5a04bf32012-03-29 16:41:38 -07001555 if (register_android_media_MediaCodecList(env) < 0) {
1556 ALOGE("ERROR: MediaCodec native registration failed");
1557 goto bail;
1558 }
1559
Andreas Huber8240d922012-04-04 14:06:32 -07001560 if (register_android_media_Crypto(env) < 0) {
1561 ALOGE("ERROR: MediaCodec native registration failed");
1562 goto bail;
1563 }
1564
Jeff Tinker8a0c80f2013-02-08 10:20:44 -08001565 if (register_android_media_Drm(env) < 0) {
1566 ALOGE("ERROR: MediaDrm native registration failed");
1567 goto bail;
1568 }
1569
Chong Zhangd5927ae2017-01-03 11:07:18 -08001570 if (register_android_media_Descrambler(env) < 0) {
1571 ALOGE("ERROR: MediaDescrambler native registration failed");
1572 goto bail;
1573 }
1574
Andreas Huberd2506a52014-01-29 10:32:46 -08001575 if (register_android_media_MediaHTTPConnection(env) < 0) {
1576 ALOGE("ERROR: MediaHTTPConnection native registration failed");
1577 goto bail;
1578 }
1579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 /* success -- return valid version number */
1581 result = JNI_VERSION_1_4;
1582
1583bail:
1584 return result;
1585}
1586
1587// KTHXBYE