• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright 2007, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "MediaPlayer-JNI"
20 #include "utils/Log.h"
21 
22 #include <media/mediaplayer.h>
23 #include <media/AudioResamplerPublic.h>
24 #include <media/IMediaHTTPService.h>
25 #include <media/MediaPlayerInterface.h>
26 #include <media/MediaMetricsItem.h>
27 #include <media/stagefright/foundation/ByteUtils.h>  // for FOURCC definition
28 #include <stdio.h>
29 #include <assert.h>
30 #include <limits.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <utils/threads.h>
34 #include "jni.h"
35 #include <nativehelper/JNIPlatformHelp.h>
36 #include <nativehelper/ScopedUtfChars.h>
37 #include "android_runtime/AndroidRuntime.h"
38 #include "android_runtime/android_view_Surface.h"
39 #include "android_runtime/Log.h"
40 #include "utils/Errors.h"  // for status_t
41 #include "utils/KeyedVector.h"
42 #include "utils/String8.h"
43 #include "android_media_MediaDataSource.h"
44 #include "android_media_MediaMetricsJNI.h"
45 #include "android_media_PlaybackParams.h"
46 #include "android_media_SyncParams.h"
47 #include "android_media_VolumeShaper.h"
48 #include "android_media_Streams.h"
49 
50 #include "android_os_Parcel.h"
51 #include "android_util_Binder.h"
52 #include <binder/Parcel.h>
53 #include <gui/IGraphicBufferProducer.h>
54 #include <gui/Surface.h>
55 #include <binder/IPCThreadState.h>
56 #include <binder/IServiceManager.h>
57 
58 #include "android_util_Binder.h"
59 
60 // Modular DRM begin
61 #define FIND_CLASS(var, className) \
62 var = env->FindClass(className); \
63 LOG_FATAL_IF(! (var), "Unable to find class " className);
64 
65 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
66 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
67 LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
68 
69 struct StateExceptionFields {
70     jmethodID init;
71     jclass classId;
72 };
73 
74 static StateExceptionFields gStateExceptionFields;
75 // Modular DRM end
76 
77 // ----------------------------------------------------------------------------
78 
79 using namespace android;
80 
81 using media::VolumeShaper;
82 
83 // ----------------------------------------------------------------------------
84 
85 struct fields_t {
86     jfieldID    context;
87     jfieldID    surface_texture;
88 
89     jmethodID   post_event;
90 
91     jmethodID   proxyConfigGetHost;
92     jmethodID   proxyConfigGetPort;
93     jmethodID   proxyConfigGetExclusionList;
94 };
95 static fields_t fields;
96 
97 static PlaybackParams::fields_t gPlaybackParamsFields;
98 static SyncParams::fields_t gSyncParamsFields;
99 static VolumeShaperHelper::fields_t gVolumeShaperFields;
100 
101 static Mutex sLock;
102 
103 // ----------------------------------------------------------------------------
104 // ref-counted object for callbacks
105 class JNIMediaPlayerListener: public MediaPlayerListener
106 {
107 public:
108     JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);
109     ~JNIMediaPlayerListener();
110     virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
111 private:
112     JNIMediaPlayerListener();
113     jclass      mClass;     // Reference to MediaPlayer class
114     jobject     mObject;    // Weak ref to MediaPlayer Java object to call on
115 };
116 
JNIMediaPlayerListener(JNIEnv * env,jobject thiz,jobject weak_thiz)117 JNIMediaPlayerListener::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) {
124         ALOGE("Can't find android/media/MediaPlayer");
125         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 
~JNIMediaPlayerListener()135 JNIMediaPlayerListener::~JNIMediaPlayerListener()
136 {
137     // remove global references
138     JNIEnv *env = AndroidRuntime::getJNIEnv();
139     env->DeleteGlobalRef(mObject);
140     env->DeleteGlobalRef(mClass);
141 }
142 
notify(int msg,int ext1,int ext2,const Parcel * obj)143 void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
144 {
145     JNIEnv *env = AndroidRuntime::getJNIEnv();
146     if (obj && obj->dataSize() > 0) {
147         jobject jParcel = createJavaParcelObject(env);
148         if (jParcel != NULL) {
149             Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
150             nativeParcel->setData(obj->data(), obj->dataSize());
151             env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
152                     msg, ext1, ext2, jParcel);
153             env->DeleteLocalRef(jParcel);
154         }
155     } else {
156         env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
157                 msg, ext1, ext2, NULL);
158     }
159     if (env->ExceptionCheck()) {
160         ALOGW("An exception occurred while notifying an event.");
161         LOGW_EX(env);
162         env->ExceptionClear();
163     }
164 }
165 
166 // ----------------------------------------------------------------------------
167 
getMediaPlayer(JNIEnv * env,jobject thiz)168 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
169 {
170     Mutex::Autolock l(sLock);
171     MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context);
172     return sp<MediaPlayer>(p);
173 }
174 
setMediaPlayer(JNIEnv * env,jobject thiz,const sp<MediaPlayer> & player)175 static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
176 {
177     Mutex::Autolock l(sLock);
178     sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context);
179     if (player.get()) {
180         player->incStrong((void*)setMediaPlayer);
181     }
182     if (old != 0) {
183         old->decStrong((void*)setMediaPlayer);
184     }
185     env->SetLongField(thiz, fields.context, (jlong)player.get());
186     return old;
187 }
188 
189 // 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
191 // opStatus is not OK, this method throws the given exception to the client
192 // application.
process_media_player_call(JNIEnv * env,jobject thiz,status_t opStatus,const char * exception,const char * message)193 static 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);
203         } else if ( opStatus == (status_t) BAD_VALUE ) {
204             jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
205         } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
206             jniThrowException(env, "java/lang/SecurityException", NULL);
207         } 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 
221 static void
android_media_MediaPlayer_setDataSourceAndHeaders(JNIEnv * env,jobject thiz,jobject httpServiceBinderObj,jstring path,jobjectArray keys,jobjectArray values)222 android_media_MediaPlayer_setDataSourceAndHeaders(
223         JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
224         jobjectArray keys, jobjectArray values) {
225 
226     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 
237     const char *tmp = env->GetStringUTFChars(path, NULL);
238     if (tmp == NULL) {  // Out of memory
239         return;
240     }
241     ALOGV("setDataSource: path %s", tmp);
242 
243     String8 pathStr(tmp);
244     env->ReleaseStringUTFChars(path, tmp);
245     tmp = NULL;
246 
247     // We build a KeyedVector out of the key and val arrays
248     KeyedVector<String8, String8> headersVector;
249     if (!ConvertKeyValueArraysToKeyedVector(
250             env, keys, values, &headersVector)) {
251         return;
252     }
253 
254     sp<IMediaHTTPService> httpService;
255     if (httpServiceBinderObj != NULL) {
256         sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
257         httpService = interface_cast<IMediaHTTPService>(binder);
258     }
259 
260     status_t opStatus =
261         mp->setDataSource(
262                 httpService,
263                 pathStr,
264                 headersVector.size() > 0? &headersVector : NULL);
265 
266     process_media_player_call(
267             env, thiz, opStatus, "java/io/IOException",
268             "setDataSource failed." );
269 }
270 
271 static void
android_media_MediaPlayer_setDataSourceFD(JNIEnv * env,jobject thiz,jobject fileDescriptor,jlong offset,jlong length)272 android_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     }
284     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
285     ALOGV("setDataSourceFD: fd %d", fd);
286     process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
287 }
288 
289 static void
android_media_MediaPlayer_setDataSourceCallback(JNIEnv * env,jobject thiz,jobject dataSource)290 android_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 
306 static sp<IGraphicBufferProducer>
getVideoSurfaceTexture(JNIEnv * env,jobject thiz)307 getVideoSurfaceTexture(JNIEnv* env, jobject thiz) {
308     IGraphicBufferProducer * const p = (IGraphicBufferProducer*)env->GetLongField(thiz, fields.surface_texture);
309     return sp<IGraphicBufferProducer>(p);
310 }
311 
312 static void
decVideoSurfaceRef(JNIEnv * env,jobject thiz)313 decVideoSurfaceRef(JNIEnv *env, jobject thiz)
314 {
315     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
316     if (mp == NULL) {
317         return;
318     }
319 
320     sp<IGraphicBufferProducer> old_st = getVideoSurfaceTexture(env, thiz);
321     if (old_st != NULL) {
322         old_st->decStrong((void*)decVideoSurfaceRef);
323     }
324 }
325 
326 static void
setVideoSurface(JNIEnv * env,jobject thiz,jobject jsurface,jboolean mediaPlayerMustBeAlive)327 setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface, jboolean mediaPlayerMustBeAlive)
328 {
329     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
330     if (mp == NULL) {
331         if (mediaPlayerMustBeAlive) {
332             jniThrowException(env, "java/lang/IllegalStateException", NULL);
333         }
334         return;
335     }
336 
337     decVideoSurfaceRef(env, thiz);
338 
339     sp<IGraphicBufferProducer> new_st;
340     if (jsurface) {
341         sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
342         if (surface != NULL) {
343             new_st = surface->getIGraphicBufferProducer();
344             if (new_st == NULL) {
345                 jniThrowException(env, "java/lang/IllegalArgumentException",
346                     "The surface does not have a binding SurfaceTexture!");
347                 return;
348             }
349             new_st->incStrong((void*)decVideoSurfaceRef);
350         } else {
351             jniThrowException(env, "java/lang/IllegalArgumentException",
352                     "The surface has been released");
353             return;
354         }
355     }
356 
357     env->SetLongField(thiz, fields.surface_texture, (jlong)new_st.get());
358 
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);
364 }
365 
366 static void
android_media_MediaPlayer_setVideoSurface(JNIEnv * env,jobject thiz,jobject jsurface)367 android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface)
368 {
369     setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
370 }
371 
372 static jint
android_media_MediaPlayer_prepare(JNIEnv * env,jobject thiz,jobject piidParcel)373 android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz, jobject piidParcel)
374 {
375     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
376     if (mp == nullptr) {
377         jniThrowException(env, "java/lang/IllegalStateException", NULL);
378         return UNKNOWN_ERROR;
379     }
380 
381     // Handle the case where the display surface was set before the mp was
382     // initialized. We try again to make it stick.
383     sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
384     mp->setVideoSurfaceTexture(st);
385 
386     process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
387 
388     if (env->ExceptionCheck()) {
389         return UNKNOWN_ERROR;
390     }
391 
392     // update the piid
393     Parcel *request = parcelForJavaObject(env, piidParcel);
394     auto reply = std::make_unique<Parcel>();
395     return static_cast<jint>(mp->invoke(*request, reply.get()));
396 }
397 
398 static jint
android_media_MediaPlayer_prepareAsync(JNIEnv * env,jobject thiz,jobject piidParcel)399 android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz, jobject piidParcel)
400 {
401     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
402     if (mp == nullptr) {
403         jniThrowException(env, "java/lang/IllegalStateException", NULL);
404         return UNKNOWN_ERROR;
405     }
406 
407     // Handle the case where the display surface was set before the mp was
408     // initialized. We try again to make it stick.
409     sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);
410     mp->setVideoSurfaceTexture(st);
411 
412     process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
413 
414     if (env->ExceptionCheck()) {
415         return UNKNOWN_ERROR;
416     }
417 
418     // update the piid
419     Parcel *request = parcelForJavaObject(env, piidParcel);
420     auto reply = std::make_unique<Parcel>();
421     return static_cast<jint>(mp->invoke(*request, reply.get()));
422 }
423 
424 static void
android_media_MediaPlayer_start(JNIEnv * env,jobject thiz)425 android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
426 {
427     ALOGV("start");
428     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
429     if (mp == NULL ) {
430         jniThrowException(env, "java/lang/IllegalStateException", NULL);
431         return;
432     }
433     process_media_player_call( env, thiz, mp->start(), NULL, NULL );
434 }
435 
436 static void
android_media_MediaPlayer_stop(JNIEnv * env,jobject thiz)437 android_media_MediaPlayer_stop(JNIEnv *env, jobject thiz)
438 {
439     ALOGV("stop");
440     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
441     if (mp == NULL ) {
442         jniThrowException(env, "java/lang/IllegalStateException", NULL);
443         return;
444     }
445     process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
446 }
447 
448 static void
android_media_MediaPlayer_pause(JNIEnv * env,jobject thiz)449 android_media_MediaPlayer_pause(JNIEnv *env, jobject thiz)
450 {
451     ALOGV("pause");
452     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
453     if (mp == NULL ) {
454         jniThrowException(env, "java/lang/IllegalStateException", NULL);
455         return;
456     }
457     process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
458 }
459 
460 static jboolean
android_media_MediaPlayer_isPlaying(JNIEnv * env,jobject thiz)461 android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz)
462 {
463     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
464     if (mp == NULL ) {
465         jniThrowException(env, "java/lang/IllegalStateException", NULL);
466         return JNI_FALSE;
467     }
468     const jboolean is_playing = mp->isPlaying();
469 
470     ALOGV("isPlaying: %d", is_playing);
471     return is_playing;
472 }
473 
474 static void
android_media_MediaPlayer_setPlaybackParams(JNIEnv * env,jobject thiz,jobject params)475 android_media_MediaPlayer_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params)
476 {
477     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
478     if (mp == NULL) {
479         jniThrowException(env, "java/lang/IllegalStateException", NULL);
480         return;
481     }
482 
483     PlaybackParams pbp;
484     pbp.fillFromJobject(env, gPlaybackParamsFields, params);
485     ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u",
486             pbp.speedSet, pbp.audioRate.mSpeed,
487             pbp.pitchSet, pbp.audioRate.mPitch,
488             pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode,
489             pbp.audioStretchModeSet, pbp.audioRate.mStretchMode);
490 
491     AudioPlaybackRate rate;
492     status_t err = mp->getPlaybackSettings(&rate);
493     if (err == OK) {
494         bool updatedRate = false;
495         if (pbp.speedSet) {
496             rate.mSpeed = pbp.audioRate.mSpeed;
497             updatedRate = true;
498         }
499         if (pbp.pitchSet) {
500             rate.mPitch = pbp.audioRate.mPitch;
501             updatedRate = true;
502         }
503         if (pbp.audioFallbackModeSet) {
504             rate.mFallbackMode = pbp.audioRate.mFallbackMode;
505             updatedRate = true;
506         }
507         if (pbp.audioStretchModeSet) {
508             rate.mStretchMode = pbp.audioRate.mStretchMode;
509             updatedRate = true;
510         }
511         if (updatedRate) {
512             err = mp->setPlaybackSettings(rate);
513         }
514     }
515     process_media_player_call(
516             env, thiz, err,
517             "java/lang/IllegalStateException", "unexpected error");
518 }
519 
520 static jobject
android_media_MediaPlayer_getPlaybackParams(JNIEnv * env,jobject thiz)521 android_media_MediaPlayer_getPlaybackParams(JNIEnv *env, jobject thiz)
522 {
523     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
524     if (mp == NULL) {
525         jniThrowException(env, "java/lang/IllegalStateException", NULL);
526         return NULL;
527     }
528 
529     PlaybackParams pbp;
530     AudioPlaybackRate &audioRate = pbp.audioRate;
531     process_media_player_call(
532             env, thiz, mp->getPlaybackSettings(&audioRate),
533             "java/lang/IllegalStateException", "unexpected error");
534     if (env->ExceptionCheck()) {
535         return nullptr;
536     }
537     ALOGV("getPlaybackSettings: %f %f %d %d",
538             audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
539 
540     pbp.speedSet = true;
541     pbp.pitchSet = true;
542     pbp.audioFallbackModeSet = true;
543     pbp.audioStretchModeSet = true;
544 
545     return pbp.asJobject(env, gPlaybackParamsFields);
546 }
547 
548 static void
android_media_MediaPlayer_setSyncParams(JNIEnv * env,jobject thiz,jobject params)549 android_media_MediaPlayer_setSyncParams(JNIEnv *env, jobject thiz, jobject params)
550 {
551     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
552     if (mp == NULL) {
553         jniThrowException(env, "java/lang/IllegalStateException", NULL);
554         return;
555     }
556 
557     SyncParams scp;
558     scp.fillFromJobject(env, gSyncParamsFields, params);
559     ALOGV("setSyncParams: %d:%d %d:%d %d:%f %d:%f",
560           scp.syncSourceSet, scp.sync.mSource,
561           scp.audioAdjustModeSet, scp.sync.mAudioAdjustMode,
562           scp.toleranceSet, scp.sync.mTolerance,
563           scp.frameRateSet, scp.frameRate);
564 
565     AVSyncSettings avsync;
566     float videoFrameRate;
567     status_t err = mp->getSyncSettings(&avsync, &videoFrameRate);
568     if (err == OK) {
569         bool updatedSync = scp.frameRateSet;
570         if (scp.syncSourceSet) {
571             avsync.mSource = scp.sync.mSource;
572             updatedSync = true;
573         }
574         if (scp.audioAdjustModeSet) {
575             avsync.mAudioAdjustMode = scp.sync.mAudioAdjustMode;
576             updatedSync = true;
577         }
578         if (scp.toleranceSet) {
579             avsync.mTolerance = scp.sync.mTolerance;
580             updatedSync = true;
581         }
582         if (updatedSync) {
583             err = mp->setSyncSettings(avsync, scp.frameRateSet ? scp.frameRate : -1.f);
584         }
585     }
586     process_media_player_call(
587             env, thiz, err,
588             "java/lang/IllegalStateException", "unexpected error");
589 }
590 
591 static jobject
android_media_MediaPlayer_getSyncParams(JNIEnv * env,jobject thiz)592 android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz)
593 {
594     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
595     if (mp == NULL) {
596         jniThrowException(env, "java/lang/IllegalStateException", NULL);
597         return NULL;
598     }
599 
600     SyncParams scp;
601     scp.frameRate = -1.f;
602     process_media_player_call(
603             env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate),
604             "java/lang/IllegalStateException", "unexpected error");
605     if (env->ExceptionCheck()) {
606         return nullptr;
607     }
608 
609     ALOGV("getSyncSettings: %d %d %f %f",
610             scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate);
611 
612     // check params
613     if (scp.sync.mSource >= AVSYNC_SOURCE_MAX
614             || scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
615             || scp.sync.mTolerance < 0.f
616             || scp.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
617         jniThrowException(env,  "java/lang/IllegalStateException", NULL);
618         return NULL;
619     }
620 
621     scp.syncSourceSet = true;
622     scp.audioAdjustModeSet = true;
623     scp.toleranceSet = true;
624     scp.frameRateSet = scp.frameRate >= 0.f;
625 
626     return scp.asJobject(env, gSyncParamsFields);
627 }
628 
629 static void
android_media_MediaPlayer_seekTo(JNIEnv * env,jobject thiz,jlong msec,jint mode)630 android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jlong msec, jint mode)
631 {
632     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
633     if (mp == NULL ) {
634         jniThrowException(env, "java/lang/IllegalStateException", NULL);
635         return;
636     }
637     ALOGV("seekTo: %lld(msec), mode=%d", (long long)msec, mode);
638     process_media_player_call( env, thiz, mp->seekTo((int)msec, (MediaPlayerSeekMode)mode), NULL, NULL );
639 }
640 
641 static void
android_media_MediaPlayer_notifyAt(JNIEnv * env,jobject thiz,jlong mediaTimeUs)642 android_media_MediaPlayer_notifyAt(JNIEnv *env, jobject thiz, jlong mediaTimeUs)
643 {
644     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
645     if (mp == NULL) {
646         jniThrowException(env, "java/lang/IllegalStateException", NULL);
647         return;
648     }
649     ALOGV("notifyAt: %lld", (long long)mediaTimeUs);
650     process_media_player_call( env, thiz, mp->notifyAt((int64_t)mediaTimeUs), NULL, NULL );
651 }
652 
653 static jint
android_media_MediaPlayer_getVideoWidth(JNIEnv * env,jobject thiz)654 android_media_MediaPlayer_getVideoWidth(JNIEnv *env, jobject thiz)
655 {
656     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
657     if (mp == NULL ) {
658         jniThrowException(env, "java/lang/IllegalStateException", NULL);
659         return 0;
660     }
661     int w;
662     if (0 != mp->getVideoWidth(&w)) {
663         ALOGE("getVideoWidth failed");
664         w = 0;
665     }
666     ALOGV("getVideoWidth: %d", w);
667     return (jint) w;
668 }
669 
670 static jint
android_media_MediaPlayer_getVideoHeight(JNIEnv * env,jobject thiz)671 android_media_MediaPlayer_getVideoHeight(JNIEnv *env, jobject thiz)
672 {
673     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
674     if (mp == NULL ) {
675         jniThrowException(env, "java/lang/IllegalStateException", NULL);
676         return 0;
677     }
678     int h;
679     if (0 != mp->getVideoHeight(&h)) {
680         ALOGE("getVideoHeight failed");
681         h = 0;
682     }
683     ALOGV("getVideoHeight: %d", h);
684     return (jint) h;
685 }
686 
687 static jobject
android_media_MediaPlayer_native_getMetrics(JNIEnv * env,jobject thiz)688 android_media_MediaPlayer_native_getMetrics(JNIEnv *env, jobject thiz)
689 {
690     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
691     if (mp == NULL ) {
692         jniThrowException(env, "java/lang/IllegalStateException", NULL);
693         return 0;
694     }
695 
696     Parcel p;
697     int key = FOURCC('m','t','r','X');
698     status_t status = mp->getParameter(key, &p);
699     if (status != OK) {
700         ALOGD("getMetrics() failed: %d", status);
701         return (jobject) NULL;
702     }
703 
704     std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create());
705     item->readFromParcel(p);
706     jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item.get(), NULL);
707 
708     return mybundle;
709 }
710 
711 static jint
android_media_MediaPlayer_getCurrentPosition(JNIEnv * env,jobject thiz)712 android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz)
713 {
714     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
715     if (mp == NULL ) {
716         jniThrowException(env, "java/lang/IllegalStateException", NULL);
717         return 0;
718     }
719     int msec;
720     process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL );
721     ALOGV("getCurrentPosition: %d (msec)", msec);
722     return (jint) msec;
723 }
724 
725 static jint
android_media_MediaPlayer_getDuration(JNIEnv * env,jobject thiz)726 android_media_MediaPlayer_getDuration(JNIEnv *env, jobject thiz)
727 {
728     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
729     if (mp == NULL ) {
730         jniThrowException(env, "java/lang/IllegalStateException", NULL);
731         return 0;
732     }
733     int msec;
734     process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL );
735     ALOGV("getDuration: %d (msec)", msec);
736     return (jint) msec;
737 }
738 
739 static void
android_media_MediaPlayer_reset(JNIEnv * env,jobject thiz)740 android_media_MediaPlayer_reset(JNIEnv *env, jobject thiz)
741 {
742     ALOGV("reset");
743     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
744     if (mp == NULL ) {
745         jniThrowException(env, "java/lang/IllegalStateException", NULL);
746         return;
747     }
748     process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
749 }
750 
751 static void
android_media_MediaPlayer_setAudioStreamType(JNIEnv * env,jobject thiz,jint streamtype)752 android_media_MediaPlayer_setAudioStreamType(JNIEnv *env, jobject thiz, jint streamtype)
753 {
754     ALOGV("setAudioStreamType: %d", streamtype);
755     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
756     if (mp == NULL ) {
757         jniThrowException(env, "java/lang/IllegalStateException", NULL);
758         return;
759     }
760     process_media_player_call( env, thiz, mp->setAudioStreamType((audio_stream_type_t) streamtype) , NULL, NULL );
761 }
762 
763 static jint
android_media_MediaPlayer_getAudioStreamType(JNIEnv * env,jobject thiz)764 android_media_MediaPlayer_getAudioStreamType(JNIEnv *env, jobject thiz)
765 {
766     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
767     if (mp == NULL ) {
768         jniThrowException(env, "java/lang/IllegalStateException", NULL);
769         return 0;
770     }
771     audio_stream_type_t streamtype;
772     process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL );
773     ALOGV("getAudioStreamType: %d (streamtype)", streamtype);
774     return (jint) streamtype;
775 }
776 
777 static jboolean
android_media_MediaPlayer_setParameter(JNIEnv * env,jobject thiz,jint key,jobject java_request)778 android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
779 {
780     ALOGV("setParameter: key %d", key);
781     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
782     if (mp == NULL ) {
783         jniThrowException(env, "java/lang/IllegalStateException", NULL);
784         return false;
785     }
786 
787     Parcel *request = parcelForJavaObject(env, java_request);
788     status_t err = mp->setParameter(key, *request);
789     if (err == OK) {
790         return true;
791     } else {
792         return false;
793     }
794 }
795 
796 static void
android_media_MediaPlayer_setLooping(JNIEnv * env,jobject thiz,jboolean looping)797 android_media_MediaPlayer_setLooping(JNIEnv *env, jobject thiz, jboolean looping)
798 {
799     ALOGV("setLooping: %d", looping);
800     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
801     if (mp == NULL ) {
802         jniThrowException(env, "java/lang/IllegalStateException", NULL);
803         return;
804     }
805     process_media_player_call( env, thiz, mp->setLooping(looping), NULL, NULL );
806 }
807 
808 static jboolean
android_media_MediaPlayer_isLooping(JNIEnv * env,jobject thiz)809 android_media_MediaPlayer_isLooping(JNIEnv *env, jobject thiz)
810 {
811     ALOGV("isLooping");
812     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
813     if (mp == NULL ) {
814         jniThrowException(env, "java/lang/IllegalStateException", NULL);
815         return JNI_FALSE;
816     }
817     return mp->isLooping() ? JNI_TRUE : JNI_FALSE;
818 }
819 
820 static void
android_media_MediaPlayer_setVolume(JNIEnv * env,jobject thiz,jfloat leftVolume,jfloat rightVolume)821 android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, jfloat leftVolume, jfloat rightVolume)
822 {
823     ALOGV("setVolume: left %f  right %f", (float) leftVolume, (float) rightVolume);
824     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
825     if (mp == NULL ) {
826         jniThrowException(env, "java/lang/IllegalStateException", NULL);
827         return;
828     }
829     process_media_player_call( env, thiz, mp->setVolume((float) leftVolume, (float) rightVolume), NULL, NULL );
830 }
831 
832 // Sends the request and reply parcels to the media player via the
833 // binder interface.
834 static jint
android_media_MediaPlayer_invoke(JNIEnv * env,jobject thiz,jobject java_request,jobject java_reply)835 android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz,
836                                  jobject java_request, jobject java_reply)
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 *request = parcelForJavaObject(env, java_request);
845     Parcel *reply = parcelForJavaObject(env, java_reply);
846 
847     // Don't use process_media_player_call which use the async loop to
848     // report errors, instead returns the status.
849     return (jint) media_player->invoke(*request, reply);
850 }
851 
852 // Sends the new filter to the client.
853 static jint
android_media_MediaPlayer_setMetadataFilter(JNIEnv * env,jobject thiz,jobject request)854 android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
855 {
856     sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
857     if (media_player == NULL ) {
858         jniThrowException(env, "java/lang/IllegalStateException", NULL);
859         return UNKNOWN_ERROR;
860     }
861 
862     Parcel *filter = parcelForJavaObject(env, request);
863 
864     if (filter == NULL ) {
865         jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
866         return UNKNOWN_ERROR;
867     }
868 
869     return (jint) media_player->setMetadataFilter(*filter);
870 }
871 
872 static jboolean
android_media_MediaPlayer_getMetadata(JNIEnv * env,jobject thiz,jboolean update_only,jboolean apply_filter,jobject reply)873 android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
874                                       jboolean apply_filter, jobject reply)
875 {
876     sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
877     if (media_player == NULL ) {
878         jniThrowException(env, "java/lang/IllegalStateException", NULL);
879         return JNI_FALSE;
880     }
881 
882     Parcel *metadata = parcelForJavaObject(env, reply);
883 
884     if (metadata == NULL ) {
885         jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
886         return JNI_FALSE;
887     }
888 
889     metadata->freeData();
890     // On return metadata is positioned at the beginning of the
891     // metadata. Note however that the parcel actually starts with the
892     // return code so you should not rewind the parcel using
893     // setDataPosition(0).
894     if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) {
895         return JNI_TRUE;
896     } else {
897         return JNI_FALSE;
898     }
899 }
900 
901 // This function gets some field IDs, which in turn causes class initialization.
902 // It is called from a static block in MediaPlayer, which won't run until the
903 // first time an instance of this class is used.
904 static void
android_media_MediaPlayer_native_init(JNIEnv * env)905 android_media_MediaPlayer_native_init(JNIEnv *env)
906 {
907     jclass clazz;
908 
909     clazz = env->FindClass("android/media/MediaPlayer");
910     if (clazz == NULL) {
911         return;
912     }
913 
914     fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
915     if (fields.context == NULL) {
916         return;
917     }
918 
919     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
920                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
921     if (fields.post_event == NULL) {
922         return;
923     }
924 
925     fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "J");
926     if (fields.surface_texture == NULL) {
927         return;
928     }
929 
930     env->DeleteLocalRef(clazz);
931 
932     clazz = env->FindClass("android/net/ProxyInfo");
933     if (clazz == NULL) {
934         return;
935     }
936 
937     fields.proxyConfigGetHost =
938         env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;");
939 
940     fields.proxyConfigGetPort =
941         env->GetMethodID(clazz, "getPort", "()I");
942 
943     fields.proxyConfigGetExclusionList =
944         env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;");
945 
946     env->DeleteLocalRef(clazz);
947 
948     // Modular DRM
949     FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
950     if (clazz) {
951         GET_METHOD_ID(gStateExceptionFields.init, clazz, "<init>", "(ILjava/lang/String;)V");
952         gStateExceptionFields.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
953 
954         env->DeleteLocalRef(clazz);
955     } else {
956         ALOGE("JNI android_media_MediaPlayer_native_init couldn't "
957               "get clazz android/media/MediaDrm$MediaDrmStateException");
958     }
959 
960     gPlaybackParamsFields.init(env);
961     gSyncParamsFields.init(env);
962     gVolumeShaperFields.init(env);
963 }
964 
965 static void
android_media_MediaPlayer_native_setup(JNIEnv * env,jobject thiz,jobject weak_this,jobject jAttributionSource,jint jAudioSessionId)966 android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
967                                        jobject jAttributionSource,
968                                        jint jAudioSessionId)
969 {
970     ALOGV("native_setup");
971 
972     Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
973     android::content::AttributionSourceState attributionSource;
974     attributionSource.readFromParcel(parcel);
975     sp<MediaPlayer> mp = sp<MediaPlayer>::make(
976         attributionSource, static_cast<audio_session_t>(jAudioSessionId));
977     if (mp == NULL) {
978         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
979         return;
980     }
981 
982     // create new listener and give it to MediaPlayer
983     sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
984     mp->setListener(listener);
985 
986     // Stow our new C++ MediaPlayer in an opaque field in the Java object.
987     setMediaPlayer(env, thiz, mp);
988 }
989 
990 static void
android_media_MediaPlayer_release(JNIEnv * env,jobject thiz)991 android_media_MediaPlayer_release(JNIEnv *env, jobject thiz)
992 {
993     ALOGV("release");
994     decVideoSurfaceRef(env, thiz);
995     sp<MediaPlayer> mp = setMediaPlayer(env, thiz, 0);
996     if (mp != NULL) {
997         // this prevents native callbacks after the object is released
998         mp->setListener(0);
999         mp->disconnect();
1000     }
1001 }
1002 
1003 static void
android_media_MediaPlayer_native_finalize(JNIEnv * env,jobject thiz)1004 android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
1005 {
1006     ALOGV("native_finalize");
1007     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1008     if (mp != NULL) {
1009         ALOGW("MediaPlayer finalized without being released");
1010     }
1011     android_media_MediaPlayer_release(env, thiz);
1012 }
1013 
android_media_MediaPlayer_set_audio_session_id(JNIEnv * env,jobject thiz,jint sessionId)1014 static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz,
1015         jint sessionId) {
1016     ALOGV("set_session_id(): %d", sessionId);
1017     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1018     if (mp == NULL ) {
1019         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1020         return;
1021     }
1022     process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL,
1023             NULL);
1024 }
1025 
android_media_MediaPlayer_get_audio_session_id(JNIEnv * env,jobject thiz)1026 static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env,  jobject thiz) {
1027     ALOGV("get_session_id()");
1028     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1029     if (mp == NULL ) {
1030         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1031         return 0;
1032     }
1033 
1034     return (jint) mp->getAudioSessionId();
1035 }
1036 
1037 static void
android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv * env,jobject thiz,jfloat level)1038 android_media_MediaPlayer_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level)
1039 {
1040     ALOGV("setAuxEffectSendLevel: level %f", level);
1041     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1042     if (mp == NULL ) {
1043         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1044         return;
1045     }
1046     process_media_player_call( env, thiz, mp->setAuxEffectSendLevel(level), NULL, NULL );
1047 }
1048 
android_media_MediaPlayer_attachAuxEffect(JNIEnv * env,jobject thiz,jint effectId)1049 static void android_media_MediaPlayer_attachAuxEffect(JNIEnv *env,  jobject thiz, jint effectId) {
1050     ALOGV("attachAuxEffect(): %d", effectId);
1051     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1052     if (mp == NULL ) {
1053         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1054         return;
1055     }
1056     process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
1057 }
1058 
1059 static jint
android_media_MediaPlayer_pullBatteryData(JNIEnv * env,jobject,jobject java_reply)1060 android_media_MediaPlayer_pullBatteryData(
1061         JNIEnv *env, jobject /* thiz */, jobject java_reply)
1062 {
1063     sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
1064     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
1065     if (service.get() == NULL) {
1066         jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService");
1067         return UNKNOWN_ERROR;
1068     }
1069 
1070     Parcel *reply = parcelForJavaObject(env, java_reply);
1071 
1072     return (jint) service->pullBatteryData(reply);
1073 }
1074 
1075 static jint
android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv * env,jobject thiz,jstring addrString,jint port)1076 android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz,
1077                                                 jstring addrString, jint port) {
1078     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1079     if (mp == NULL ) {
1080         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1081         return INVALID_OPERATION;
1082     }
1083 
1084     const char *cAddrString = NULL;
1085 
1086     if (NULL != addrString) {
1087         cAddrString = env->GetStringUTFChars(addrString, NULL);
1088         if (cAddrString == NULL) {  // Out of memory
1089             return NO_MEMORY;
1090         }
1091     }
1092     ALOGV("setRetransmitEndpoint: %s:%d",
1093             cAddrString ? cAddrString : "(null)", port);
1094 
1095     status_t ret;
1096     if (cAddrString && (port > 0xFFFF)) {
1097         ret = BAD_VALUE;
1098     } else {
1099         ret = mp->setRetransmitEndpoint(cAddrString,
1100                 static_cast<uint16_t>(port));
1101     }
1102 
1103     if (NULL != addrString) {
1104         env->ReleaseStringUTFChars(addrString, cAddrString);
1105     }
1106 
1107     if (ret == INVALID_OPERATION ) {
1108         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1109     }
1110 
1111     return (jint) ret;
1112 }
1113 
1114 static void
android_media_MediaPlayer_setNextMediaPlayer(JNIEnv * env,jobject thiz,jobject java_player)1115 android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
1116 {
1117     ALOGV("setNextMediaPlayer");
1118     sp<MediaPlayer> thisplayer = getMediaPlayer(env, thiz);
1119     if (thisplayer == NULL) {
1120         jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized");
1121         return;
1122     }
1123     sp<MediaPlayer> nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player);
1124     if (nextplayer == NULL && java_player != NULL) {
1125         jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized");
1126         return;
1127     }
1128 
1129     if (nextplayer == thisplayer) {
1130         jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self");
1131         return;
1132     }
1133     // tie the two players together
1134     process_media_player_call(
1135             env, thiz, thisplayer->setNextMediaPlayer(nextplayer),
1136             "java/lang/IllegalArgumentException",
1137             "setNextMediaPlayer failed." );
1138     ;
1139 }
1140 
1141 // Pass through the arguments to the MediaServer player implementation.
android_media_MediaPlayer_applyVolumeShaper(JNIEnv * env,jobject thiz,jobject jconfig,jobject joperation)1142 static jint android_media_MediaPlayer_applyVolumeShaper(JNIEnv *env, jobject thiz,
1143         jobject jconfig, jobject joperation) {
1144     // NOTE: hard code here to prevent platform issues. Must match VolumeShaper.java
1145     const int VOLUME_SHAPER_INVALID_OPERATION = -38;
1146 
1147     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1148     if (mp == nullptr) {
1149         return (jint)VOLUME_SHAPER_INVALID_OPERATION;
1150     }
1151 
1152     sp<VolumeShaper::Configuration> configuration;
1153     sp<VolumeShaper::Operation> operation;
1154     if (jconfig != nullptr) {
1155         configuration = VolumeShaperHelper::convertJobjectToConfiguration(
1156                 env, gVolumeShaperFields, jconfig);
1157         ALOGV("applyVolumeShaper configuration: %s", configuration->toString().c_str());
1158     }
1159     if (joperation != nullptr) {
1160         operation = VolumeShaperHelper::convertJobjectToOperation(
1161                 env, gVolumeShaperFields, joperation);
1162         ALOGV("applyVolumeShaper operation: %s", operation->toString().c_str());
1163     }
1164     VolumeShaper::Status status = mp->applyVolumeShaper(configuration, operation);
1165     if (status == INVALID_OPERATION) {
1166         status = VOLUME_SHAPER_INVALID_OPERATION;
1167     }
1168     return (jint)status; // if status < 0 an error, else a VolumeShaper id
1169 }
1170 
1171 // Pass through the arguments to the MediaServer player implementation.
android_media_MediaPlayer_getVolumeShaperState(JNIEnv * env,jobject thiz,jint id)1172 static jobject android_media_MediaPlayer_getVolumeShaperState(JNIEnv *env, jobject thiz,
1173         jint id) {
1174     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1175     if (mp == nullptr) {
1176         return (jobject)nullptr;
1177     }
1178 
1179     sp<VolumeShaper::State> state = mp->getVolumeShaperState((int)id);
1180     if (state.get() == nullptr) {
1181         return (jobject)nullptr;
1182     }
1183     return VolumeShaperHelper::convertStateToJobject(env, gVolumeShaperFields, state);
1184 }
1185 
1186 /////////////////////////////////////////////////////////////////////////////////////
1187 // Modular DRM begin
1188 
1189 // TODO: investigate if these can be shared with their MediaDrm counterparts
throwDrmStateException(JNIEnv * env,const char * msg,status_t err)1190 static void throwDrmStateException(JNIEnv *env, const char *msg, status_t err)
1191 {
1192     ALOGE("Illegal DRM state exception: %s (%d)", msg, err);
1193 
1194     jobject exception = env->NewObject(gStateExceptionFields.classId,
1195             gStateExceptionFields.init, static_cast<int>(err),
1196             env->NewStringUTF(msg));
1197     env->Throw(static_cast<jthrowable>(exception));
1198 }
1199 
1200 // TODO: investigate if these can be shared with their MediaDrm counterparts
throwDrmExceptionAsNecessary(JNIEnv * env,status_t err,const char * msg=NULL)1201 static bool throwDrmExceptionAsNecessary(JNIEnv *env, status_t err, const char *msg = NULL)
1202 {
1203     const char *drmMessage = "Unknown DRM Msg";
1204 
1205     switch (err) {
1206     case ERROR_DRM_UNKNOWN:
1207         drmMessage = "General DRM error";
1208         break;
1209     case ERROR_DRM_NO_LICENSE:
1210         drmMessage = "No license";
1211         break;
1212     case ERROR_DRM_LICENSE_EXPIRED:
1213         drmMessage = "License expired";
1214         break;
1215     case ERROR_DRM_SESSION_NOT_OPENED:
1216         drmMessage = "Session not opened";
1217         break;
1218     case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
1219         drmMessage = "Not initialized";
1220         break;
1221     case ERROR_DRM_DECRYPT:
1222         drmMessage = "Decrypt error";
1223         break;
1224     case ERROR_DRM_CANNOT_HANDLE:
1225         drmMessage = "Unsupported scheme or data format";
1226         break;
1227     case ERROR_DRM_TAMPER_DETECTED:
1228         drmMessage = "Invalid state";
1229         break;
1230     default:
1231         break;
1232     }
1233 
1234     String8 vendorMessage;
1235     if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
1236         vendorMessage = String8::format("DRM vendor-defined error: %d", err);
1237         drmMessage = vendorMessage.string();
1238     }
1239 
1240     if (err == BAD_VALUE) {
1241         jniThrowException(env, "java/lang/IllegalArgumentException", msg);
1242         return true;
1243     } else if (err == ERROR_DRM_NOT_PROVISIONED) {
1244         jniThrowException(env, "android/media/NotProvisionedException", msg);
1245         return true;
1246     } else if (err == ERROR_DRM_RESOURCE_BUSY) {
1247         jniThrowException(env, "android/media/ResourceBusyException", msg);
1248         return true;
1249     } else if (err == ERROR_DRM_DEVICE_REVOKED) {
1250         jniThrowException(env, "android/media/DeniedByServerException", msg);
1251         return true;
1252     } else if (err == DEAD_OBJECT) {
1253         jniThrowException(env, "android/media/MediaDrmResetException",
1254                           "mediaserver died");
1255         return true;
1256     } else if (err != OK) {
1257         String8 errbuf;
1258         if (drmMessage != NULL) {
1259             if (msg == NULL) {
1260                 msg = drmMessage;
1261             } else {
1262                 errbuf = String8::format("%s: %s", msg, drmMessage);
1263                 msg = errbuf.string();
1264             }
1265         }
1266         throwDrmStateException(env, msg, err);
1267         return true;
1268     }
1269     return false;
1270 }
1271 
JByteArrayToVector(JNIEnv * env,jbyteArray const & byteArray)1272 static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray)
1273 {
1274     Vector<uint8_t> vector;
1275     size_t length = env->GetArrayLength(byteArray);
1276     vector.insertAt((size_t)0, length);
1277     env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
1278     return vector;
1279 }
1280 
android_media_MediaPlayer_prepareDrm(JNIEnv * env,jobject thiz,jbyteArray uuidObj,jbyteArray drmSessionIdObj)1281 static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
1282                     jbyteArray uuidObj, jbyteArray drmSessionIdObj)
1283 {
1284     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1285     if (mp == NULL) {
1286         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1287         return;
1288     }
1289 
1290     if (uuidObj == NULL) {
1291         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1292         return;
1293     }
1294 
1295     Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
1296 
1297     if (uuid.size() != 16) {
1298         jniThrowException(
1299                           env,
1300                           "java/lang/IllegalArgumentException",
1301                           "invalid UUID size, expected 16 bytes");
1302         return;
1303     }
1304 
1305     Vector<uint8_t> drmSessionId = JByteArrayToVector(env, drmSessionIdObj);
1306 
1307     if (drmSessionId.size() == 0) {
1308         jniThrowException(
1309                           env,
1310                           "java/lang/IllegalArgumentException",
1311                           "empty drmSessionId");
1312         return;
1313     }
1314 
1315     status_t err = mp->prepareDrm(uuid.array(), drmSessionId);
1316     if (err != OK) {
1317         if (err == INVALID_OPERATION) {
1318             jniThrowException(
1319                               env,
1320                               "java/lang/IllegalStateException",
1321                               "The player must be in prepared state.");
1322         } else if (err == ERROR_DRM_CANNOT_HANDLE) {
1323             jniThrowException(
1324                               env,
1325                               "android/media/UnsupportedSchemeException",
1326                               "Failed to instantiate drm object.");
1327         } else {
1328             throwDrmExceptionAsNecessary(env, err, "Failed to prepare DRM scheme");
1329         }
1330     }
1331 }
1332 
android_media_MediaPlayer_releaseDrm(JNIEnv * env,jobject thiz)1333 static void android_media_MediaPlayer_releaseDrm(JNIEnv *env, jobject thiz)
1334 {
1335     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1336     if (mp == NULL ) {
1337         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1338         return;
1339     }
1340 
1341     status_t err = mp->releaseDrm();
1342     if (err != OK) {
1343         if (err == INVALID_OPERATION) {
1344             jniThrowException(
1345                               env,
1346                               "java/lang/IllegalStateException",
1347                               "Can not release DRM in an active player state.");
1348         }
1349     }
1350 }
1351 // Modular DRM end
1352 // ----------------------------------------------------------------------------
1353 
1354 /////////////////////////////////////////////////////////////////////////////////////
1355 // AudioRouting begin
android_media_MediaPlayer_setOutputDevice(JNIEnv * env,jobject thiz,jint device_id)1356 static jboolean android_media_MediaPlayer_setOutputDevice(JNIEnv *env, jobject thiz, jint device_id)
1357 {
1358     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1359     if (mp == NULL) {
1360         return false;
1361     }
1362     return mp->setOutputDevice(device_id) == NO_ERROR;
1363 }
1364 
android_media_MediaPlayer_getRoutedDeviceId(JNIEnv * env,jobject thiz)1365 static jint android_media_MediaPlayer_getRoutedDeviceId(JNIEnv *env, jobject thiz)
1366 {
1367     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1368     if (mp == NULL) {
1369         return AUDIO_PORT_HANDLE_NONE;
1370     }
1371     return mp->getRoutedDeviceId();
1372 }
1373 
android_media_MediaPlayer_enableDeviceCallback(JNIEnv * env,jobject thiz,jboolean enabled)1374 static void android_media_MediaPlayer_enableDeviceCallback(
1375         JNIEnv* env, jobject thiz, jboolean enabled)
1376 {
1377     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
1378     if (mp == NULL) {
1379         return;
1380     }
1381 
1382     status_t status = mp->enableAudioDeviceCallback(enabled);
1383     if (status != NO_ERROR) {
1384         jniThrowException(env, "java/lang/IllegalStateException", NULL);
1385         ALOGE("enable device callback failed: %d", status);
1386     }
1387 }
1388 
1389 // AudioRouting end
1390 // ----------------------------------------------------------------------------
1391 
1392 static const JNINativeMethod gMethods[] = {
1393     {
1394         "nativeSetDataSource",
1395         "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
1396         "[Ljava/lang/String;)V",
1397         (void *)android_media_MediaPlayer_setDataSourceAndHeaders
1398     },
1399 
1400     {"_setDataSource",      "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
1401     {"_setDataSource",      "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
1402     {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer_setVideoSurface},
1403     {"_prepare",            "(Landroid/os/Parcel;)I",           (void *)android_media_MediaPlayer_prepare},
1404     {"_prepareAsync",       "(Landroid/os/Parcel;)I",           (void *)android_media_MediaPlayer_prepareAsync},
1405     {"_start",              "()V",                              (void *)android_media_MediaPlayer_start},
1406     {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
1407     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
1408     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
1409     {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer_native_getMetrics},
1410     {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
1411     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
1412     {"setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer_setSyncParams},
1413     {"getSyncParams",     "()Landroid/media/SyncParams;",   (void *)android_media_MediaPlayer_getSyncParams},
1414     {"_seekTo",             "(JI)V",                            (void *)android_media_MediaPlayer_seekTo},
1415     {"_notifyAt",           "(J)V",                             (void *)android_media_MediaPlayer_notifyAt},
1416     {"_pause",              "()V",                              (void *)android_media_MediaPlayer_pause},
1417     {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer_isPlaying},
1418     {"getCurrentPosition",  "()I",                              (void *)android_media_MediaPlayer_getCurrentPosition},
1419     {"getDuration",         "()I",                              (void *)android_media_MediaPlayer_getDuration},
1420     {"_release",            "()V",                              (void *)android_media_MediaPlayer_release},
1421     {"_reset",              "()V",                              (void *)android_media_MediaPlayer_reset},
1422     {"_setAudioStreamType", "(I)V",                             (void *)android_media_MediaPlayer_setAudioStreamType},
1423     {"_getAudioStreamType", "()I",                              (void *)android_media_MediaPlayer_getAudioStreamType},
1424     {"setParameter",        "(ILandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer_setParameter},
1425     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer_setLooping},
1426     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer_isLooping},
1427     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer_setVolume},
1428     {"native_invoke",       "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
1429     {"native_setMetadataFilter", "(Landroid/os/Parcel;)I",      (void *)android_media_MediaPlayer_setMetadataFilter},
1430     {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer_getMetadata},
1431     {"native_init",         "()V",                              (void *)android_media_MediaPlayer_native_init},
1432     {"native_setup",
1433         "(Ljava/lang/Object;Landroid/os/Parcel;I)V",
1434         (void *)android_media_MediaPlayer_native_setup},
1435     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer_native_finalize},
1436     {"getAudioSessionId",   "()I",                              (void *)android_media_MediaPlayer_get_audio_session_id},
1437     {"native_setAudioSessionId",   "(I)V",                      (void *)android_media_MediaPlayer_set_audio_session_id},
1438     {"_setAuxEffectSendLevel", "(F)V",                          (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
1439     {"attachAuxEffect",     "(I)V",                             (void *)android_media_MediaPlayer_attachAuxEffect},
1440     {"native_pullBatteryData", "(Landroid/os/Parcel;)I",        (void *)android_media_MediaPlayer_pullBatteryData},
1441     {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I",  (void *)android_media_MediaPlayer_setRetransmitEndpoint},
1442     {"setNextMediaPlayer",  "(Landroid/media/MediaPlayer;)V",   (void *)android_media_MediaPlayer_setNextMediaPlayer},
1443     {"native_applyVolumeShaper",
1444                             "(Landroid/media/VolumeShaper$Configuration;Landroid/media/VolumeShaper$Operation;)I",
1445                                                                 (void *)android_media_MediaPlayer_applyVolumeShaper},
1446     {"native_getVolumeShaperState",
1447                             "(I)Landroid/media/VolumeShaper$State;",
1448                                                                 (void *)android_media_MediaPlayer_getVolumeShaperState},
1449     // Modular DRM
1450     { "_prepareDrm", "([B[B)V",                                 (void *)android_media_MediaPlayer_prepareDrm },
1451     { "_releaseDrm", "()V",                                     (void *)android_media_MediaPlayer_releaseDrm },
1452 
1453     // AudioRouting
1454     {"native_setOutputDevice", "(I)Z",                          (void *)android_media_MediaPlayer_setOutputDevice},
1455     {"native_getRoutedDeviceId", "()I",                         (void *)android_media_MediaPlayer_getRoutedDeviceId},
1456     {"native_enableDeviceCallback", "(Z)V",                     (void *)android_media_MediaPlayer_enableDeviceCallback},
1457 };
1458 
1459 // This function only registers the native methods
register_android_media_MediaPlayer(JNIEnv * env)1460 static int register_android_media_MediaPlayer(JNIEnv *env)
1461 {
1462     return AndroidRuntime::registerNativeMethods(env,
1463                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
1464 }
1465 extern int register_android_media_ImageReader(JNIEnv *env);
1466 extern int register_android_media_ImageWriter(JNIEnv *env);
1467 extern int register_android_media_JetPlayer(JNIEnv *env);
1468 extern int register_android_media_Crypto(JNIEnv *env);
1469 extern int register_android_media_Drm(JNIEnv *env);
1470 extern int register_android_media_Descrambler(JNIEnv *env);
1471 extern int register_android_media_MediaCodec(JNIEnv *env);
1472 extern int register_android_media_MediaExtractor(JNIEnv *env);
1473 extern int register_android_media_MediaCodecList(JNIEnv *env);
1474 extern int register_android_media_MediaHTTPConnection(JNIEnv *env);
1475 extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
1476 extern int register_android_media_MediaMuxer(JNIEnv *env);
1477 extern int register_android_media_MediaRecorder(JNIEnv *env);
1478 extern int register_android_media_MediaSync(JNIEnv *env);
1479 extern int register_android_media_PublicFormatUtils(JNIEnv *env);
1480 extern int register_android_media_ResampleInputStream(JNIEnv *env);
1481 extern int register_android_media_MediaProfiles(JNIEnv *env);
1482 extern int register_android_mtp_MtpDatabase(JNIEnv *env);
1483 extern int register_android_mtp_MtpDevice(JNIEnv *env);
1484 extern int register_android_mtp_MtpServer(JNIEnv *env);
1485 
JNI_OnLoad(JavaVM * vm,void *)1486 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
1487 {
1488     JNIEnv* env = NULL;
1489     jint result = -1;
1490 
1491     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
1492         ALOGE("ERROR: GetEnv failed\n");
1493         goto bail;
1494     }
1495     assert(env != NULL);
1496 
1497     if (register_android_media_ImageWriter(env) != JNI_OK) {
1498         ALOGE("ERROR: ImageWriter native registration failed");
1499         goto bail;
1500     }
1501 
1502     if (register_android_media_ImageReader(env) < 0) {
1503         ALOGE("ERROR: ImageReader native registration failed");
1504         goto bail;
1505     }
1506 
1507     if (register_android_media_JetPlayer(env) < 0) {
1508         ALOGE("ERROR: JetPlayer native registration failed");
1509         goto bail;
1510     }
1511 
1512     if (register_android_media_MediaPlayer(env) < 0) {
1513         ALOGE("ERROR: MediaPlayer native registration failed\n");
1514         goto bail;
1515     }
1516 
1517     if (register_android_media_MediaRecorder(env) < 0) {
1518         ALOGE("ERROR: MediaRecorder native registration failed\n");
1519         goto bail;
1520     }
1521 
1522     if (register_android_media_MediaMetadataRetriever(env) < 0) {
1523         ALOGE("ERROR: MediaMetadataRetriever native registration failed\n");
1524         goto bail;
1525     }
1526 
1527     if (register_android_media_PublicFormatUtils(env) < 0) {
1528         ALOGE("ERROR: PublicFormatUtils native registration failed\n");
1529         goto bail;
1530     }
1531 
1532     if (register_android_media_ResampleInputStream(env) < 0) {
1533         ALOGE("ERROR: ResampleInputStream native registration failed\n");
1534         goto bail;
1535     }
1536 
1537     if (register_android_media_MediaProfiles(env) < 0) {
1538         ALOGE("ERROR: MediaProfiles native registration failed");
1539         goto bail;
1540     }
1541 
1542     if (register_android_mtp_MtpDatabase(env) < 0) {
1543         ALOGE("ERROR: MtpDatabase native registration failed");
1544         goto bail;
1545     }
1546 
1547     if (register_android_mtp_MtpDevice(env) < 0) {
1548         ALOGE("ERROR: MtpDevice native registration failed");
1549         goto bail;
1550     }
1551 
1552     if (register_android_mtp_MtpServer(env) < 0) {
1553         ALOGE("ERROR: MtpServer native registration failed");
1554         goto bail;
1555     }
1556 
1557     if (register_android_media_MediaCodec(env) < 0) {
1558         ALOGE("ERROR: MediaCodec native registration failed");
1559         goto bail;
1560     }
1561 
1562     if (register_android_media_MediaSync(env) < 0) {
1563         ALOGE("ERROR: MediaSync native registration failed");
1564         goto bail;
1565     }
1566 
1567     if (register_android_media_MediaExtractor(env) < 0) {
1568         ALOGE("ERROR: MediaCodec native registration failed");
1569         goto bail;
1570     }
1571 
1572     if (register_android_media_MediaMuxer(env) < 0) {
1573         ALOGE("ERROR: MediaMuxer native registration failed");
1574         goto bail;
1575     }
1576 
1577     if (register_android_media_MediaCodecList(env) < 0) {
1578         ALOGE("ERROR: MediaCodec native registration failed");
1579         goto bail;
1580     }
1581 
1582     if (register_android_media_Crypto(env) < 0) {
1583         ALOGE("ERROR: MediaCodec native registration failed");
1584         goto bail;
1585     }
1586 
1587     if (register_android_media_Drm(env) < 0) {
1588         ALOGE("ERROR: MediaDrm native registration failed");
1589         goto bail;
1590     }
1591 
1592     if (register_android_media_Descrambler(env) < 0) {
1593         ALOGE("ERROR: MediaDescrambler native registration failed");
1594         goto bail;
1595     }
1596 
1597     if (register_android_media_MediaHTTPConnection(env) < 0) {
1598         ALOGE("ERROR: MediaHTTPConnection native registration failed");
1599         goto bail;
1600     }
1601 
1602     /* success -- return valid version number */
1603     result = JNI_VERSION_1_4;
1604 
1605 bail:
1606     return result;
1607 }
1608 
1609 // KTHXBYE
1610