From 128875996598b9cfa91bad137d3a73dfcb4a2aed Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Tue, 20 Feb 2018 15:01:52 -0800 Subject: [PATCH] MediaPlayer2: use long type for media time. add getAudioAttributes add srcId for DRM callbacks remove setNextMediaPlayer Test: MediaPlayer2 plays Bug: 63934228 Change-Id: Ibc890a9cb2a29ab58ae7eed25f41e96e04ccafcc --- api/current.txt | 11 +-- media/java/android/media/MediaPlayer2.java | 52 +++++-------- .../java/android/media/MediaPlayer2Impl.java | 49 +++++------- media/jni/android_media_MediaPlayer2.cpp | 74 +++++++++---------- 4 files changed, 81 insertions(+), 105 deletions(-) diff --git a/api/current.txt b/api/current.txt index f6f152031fb19..5811f6ce09b26 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24070,13 +24070,14 @@ package android.media { method public static final android.media.MediaPlayer2 create(); method public abstract void deselectTrack(int); method public abstract android.media.DataSourceDesc editPlaylistItem(int, android.media.DataSourceDesc); + method public abstract android.media.AudioAttributes getAudioAttributes(); method public abstract int getAudioSessionId(); method public abstract android.media.DataSourceDesc getCurrentDataSource(); method public abstract int getCurrentPlaylistItemIndex(); - method public abstract int getCurrentPosition(); + method public abstract long getCurrentPosition(); method public abstract android.media.MediaPlayer2.DrmInfo getDrmInfo(); method public abstract java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer2.NoDrmSchemeException; - method public abstract int getDuration(); + method public abstract long getDuration(); method public abstract android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map) throws android.media.MediaPlayer2.NoDrmSchemeException; method public abstract int getLoopingMode(); method public abstract android.os.PersistableBundle getMetrics(); @@ -24162,8 +24163,8 @@ package android.media { public static abstract class MediaPlayer2.DrmEventCallback { ctor public MediaPlayer2.DrmEventCallback(); - method public void onDrmInfo(android.media.MediaPlayer2, android.media.MediaPlayer2.DrmInfo); - method public void onDrmPrepared(android.media.MediaPlayer2, int); + method public void onDrmInfo(android.media.MediaPlayer2, long, android.media.MediaPlayer2.DrmInfo); + method public void onDrmPrepared(android.media.MediaPlayer2, long, int); } public static abstract class MediaPlayer2.DrmInfo { @@ -24201,7 +24202,7 @@ package android.media { } public static abstract interface MediaPlayer2.OnDrmConfigHelper { - method public abstract void onDrmConfig(android.media.MediaPlayer2); + method public abstract void onDrmConfig(android.media.MediaPlayer2, long); } public static abstract class MediaPlayer2.ProvisioningNetworkErrorException extends android.media.MediaDrmException { diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java index 2f3d972ae6e24..144666003508e 100644 --- a/media/java/android/media/MediaPlayer2.java +++ b/media/java/android/media/MediaPlayer2.java @@ -1223,7 +1223,7 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener * * @return the current position in milliseconds */ - public abstract int getCurrentPosition(); + public abstract long getCurrentPosition(); /** * Gets the duration of the file. @@ -1231,7 +1231,7 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener * @return the duration in milliseconds, if no duration is available * (for example, if streaming live content), -1 is returned. */ - public abstract int getDuration(); + public abstract long getDuration(); /** * Gets the media metadata. @@ -1277,27 +1277,6 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener return 0; } - /** - * Set the MediaPlayer2 to start when this MediaPlayer2 finishes playback - * (i.e. reaches the end of the stream). - * The media framework will attempt to transition from this player to - * the next as seamlessly as possible. The next player can be set at - * any time before completion, but shall be after setDataSource has been - * called successfully. The next player must be prepared by the - * app, and the application should not call play() on it. - * The next MediaPlayer2 must be different from 'this'. An exception - * will be thrown if next == this. - * The application may call setNextMediaPlayer(null) to indicate no - * next player should be started at the end of playback. - * If the current player is looping, it will keep looping and the next - * player will not be started. - * - * @param next the player to start after this one completes playback. - * - * @hide - */ - public void setNextMediaPlayer(MediaPlayer2 next) { } - /** * Resets the MediaPlayer2 to its uninitialized state. After calling * this method, you will have to initialize it again by setting the @@ -1325,6 +1304,13 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener */ public abstract void setAudioAttributes(AudioAttributes attributes); + /** + * Gets the audio attributes for this MediaPlayer2. + * @return attributes a set of audio attributes + * @throws IllegalArgumentException if the attributes are null or invalid. + */ + public abstract AudioAttributes getAudioAttributes(); + /** * Sets the player to be looping or non-looping. * @@ -2029,8 +2015,9 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener * Called to give the app the opportunity to configure DRM before the session is created * * @param mp the {@code MediaPlayer2} associated with this callback + * @param srcId the Id of this data source */ - public void onDrmConfig(MediaPlayer2 mp); + public void onDrmConfig(MediaPlayer2 mp, long srcId); } /** @@ -2051,24 +2038,25 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener /** * Called to indicate DRM info is available * - * @param mp the {@code MediaPlayer2} associated with this callback - * @param drmInfo DRM info of the source including PSSH, and subset - * of crypto schemes supported by this device + * @param mp the {@code MediaPlayer2} associated with this callback + * @param srcId the Id of this data source + * @param drmInfo DRM info of the source including PSSH, and subset + * of crypto schemes supported by this device */ - public void onDrmInfo(MediaPlayer2 mp, DrmInfo drmInfo) { } + public void onDrmInfo(MediaPlayer2 mp, long srcId, DrmInfo drmInfo) { } /** * Called to notify the client that {@code prepareDrm} is finished and ready for key request/response. * - * @param mp the {@code MediaPlayer2} associated with this callback - * @param status the result of DRM preparation which can be + * @param mp the {@code MediaPlayer2} associated with this callback + * @param srcId the Id of this data source + * @param status the result of DRM preparation which can be * {@link #PREPARE_DRM_STATUS_SUCCESS}, * {@link #PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR}, * {@link #PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR}, or * {@link #PREPARE_DRM_STATUS_PREPARATION_ERROR}. */ - public void onDrmPrepared(MediaPlayer2 mp, @PrepareDrmStatusCode int status) { } - + public void onDrmPrepared(MediaPlayer2 mp, long srcId, @PrepareDrmStatusCode int status) { } } /** diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 1b21b5bc2afdf..7794e08f074ca 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -1889,7 +1889,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { * @return the current position in milliseconds */ @Override - public native int getCurrentPosition(); + public native long getCurrentPosition(); /** * Gets the duration of the file. @@ -1898,7 +1898,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { * (for example, if streaming live content), -1 is returned. */ @Override - public native int getDuration(); + public native long getDuration(); /** * Gets the media metadata. @@ -1985,28 +1985,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return native_setMetadataFilter(request); } - /** - * Set the MediaPlayer2 to start when this MediaPlayer2 finishes playback - * (i.e. reaches the end of the stream). - * The media framework will attempt to transition from this player to - * the next as seamlessly as possible. The next player can be set at - * any time before completion, but shall be after setDataSource has been - * called successfully. The next player must be prepared by the - * app, and the application should not call play() on it. - * The next MediaPlayer2 must be different from 'this'. An exception - * will be thrown if next == this. - * The application may call setNextMediaPlayer(null) to indicate no - * next player should be started at the end of playback. - * If the current player is looping, it will keep looping and the next - * player will not be started. - * - * @param next the player to start after this one completes playback. - * - * @hide - */ - @Override - public native void setNextMediaPlayer(MediaPlayer2 next); - /** * Resets the MediaPlayer2 to its uninitialized state. After calling * this method, you will have to initialize it again by setting the @@ -2078,10 +2056,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { * @param key key indicates the parameter to be set. * @param value value of the parameter to be set. * @return true if the parameter is set successfully, false otherwise - * {@hide} */ private native boolean setParameter(int key, Parcel value); + private native Parcel getParameter(int key); + /** * Sets the audio attributes for this MediaPlayer2. * See {@link AudioAttributes} for how to build and configure an instance of this class. @@ -2105,6 +2084,14 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { pattributes.recycle(); } + @Override + public AudioAttributes getAudioAttributes() { + Parcel pattributes = getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES); + AudioAttributes attributes = AudioAttributes.CREATOR.createFromParcel(pattributes); + pattributes.recycle(); + return attributes; + } + /** * Sets the player to be looping or non-looping. * @@ -3211,11 +3198,12 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } // notifying the client outside the lock + // TODO: get srcId if (drmInfo != null) { synchronized (mEventCbLock) { for (Pair cb : mDrmEventCallbackRecords) { cb.first.execute(() -> cb.second.onDrmInfo( - mMediaPlayer, drmInfo)); + mMediaPlayer, 0, drmInfo)); } } } @@ -3747,8 +3735,9 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // call the callback outside the lock + // TODO: get srcId if (mOnDrmConfigHelper != null) { - mOnDrmConfigHelper.onDrmConfig(this); + mOnDrmConfigHelper.onDrmConfig(this, 0); } synchronized (mDrmLock) { @@ -3818,11 +3807,12 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // if finished successfully without provisioning, call the callback outside the lock + // TODO: get srcId if (allDoneWithoutProvisioning) { synchronized (mDrmEventCbLock) { for (Pair cb : mDrmEventCallbackRecords) { cb.first.execute(() -> cb.second.onDrmPrepared( - this, PREPARE_DRM_STATUS_SUCCESS)); + this, 0, PREPARE_DRM_STATUS_SUCCESS)); } } } @@ -4488,9 +4478,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } // synchronized // calling the callback outside the lock + // TODO: get srcId synchronized (mDrmEventCbLock) { for (Pair cb : mDrmEventCallbackRecords) { - cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, status)); + cb.first.execute(() -> cb.second.onDrmPrepared(mediaPlayer, 0, status)); } } } else { // blocking mode already has the lock diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp index cf115a4f8d438..2258c78f18a0d 100644 --- a/media/jni/android_media_MediaPlayer2.cpp +++ b/media/jni/android_media_MediaPlayer2.cpp @@ -760,7 +760,8 @@ android_media_MediaPlayer2_seekTo(JNIEnv *env, jobject thiz, jlong msec, jint mo return; } ALOGV("seekTo: %lld(msec), mode=%d", (long long)msec, mode); - process_media_player_call( env, thiz, mp->seekTo((int)msec, (MediaPlayer2SeekMode)mode), NULL, NULL ); + process_media_player_call(env, thiz, mp->seekTo((int64_t)msec, (MediaPlayer2SeekMode)mode), + NULL, NULL); } static void @@ -838,7 +839,7 @@ android_media_MediaPlayer2_native_getMetrics(JNIEnv *env, jobject thiz) return mybundle; } -static jint +static jlong android_media_MediaPlayer2_getCurrentPosition(JNIEnv *env, jobject thiz) { sp mp = getMediaPlayer(env, thiz); @@ -846,13 +847,13 @@ android_media_MediaPlayer2_getCurrentPosition(JNIEnv *env, jobject thiz) jniThrowException(env, "java/lang/IllegalStateException", NULL); return 0; } - int msec; + int64_t msec; process_media_player_call( env, thiz, mp->getCurrentPosition(&msec), NULL, NULL ); - ALOGV("getCurrentPosition: %d (msec)", msec); - return (jint) msec; + ALOGV("getCurrentPosition: %lld (msec)", (long long)msec); + return (jlong) msec; } -static jint +static jlong android_media_MediaPlayer2_getDuration(JNIEnv *env, jobject thiz) { sp mp = getMediaPlayer(env, thiz); @@ -860,10 +861,10 @@ android_media_MediaPlayer2_getDuration(JNIEnv *env, jobject thiz) jniThrowException(env, "java/lang/IllegalStateException", NULL); return 0; } - int msec; + int64_t msec; process_media_player_call( env, thiz, mp->getDuration(&msec), NULL, NULL ); - ALOGV("getDuration: %d (msec)", msec); - return (jint) msec; + ALOGV("getDuration: %lld (msec)", (long long)msec); + return (jlong) msec; } static void @@ -911,6 +912,28 @@ android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, job } } +static jobject +android_media_MediaPlayer2_getParameter(JNIEnv *env, jobject thiz, jint key) +{ + ALOGV("getParameter: key %d", key); + sp mp = getMediaPlayer(env, thiz); + if (mp == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", NULL); + return NULL; + } + + jobject jParcel = createJavaParcelObject(env); + if (jParcel != NULL) { + Parcel* nativeParcel = parcelForJavaObject(env, jParcel); + status_t err = mp->getParameter(key, nativeParcel); + if (err != OK) { + env->DeleteLocalRef(jParcel); + return NULL; + } + } + return jParcel; +} + static void android_media_MediaPlayer2_setLooping(JNIEnv *env, jobject thiz, jboolean looping) { @@ -1171,33 +1194,6 @@ static void android_media_MediaPlayer2_attachAuxEffect(JNIEnv *env, jobject thi process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL ); } -static void -android_media_MediaPlayer2_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player) -{ - ALOGV("setNextMediaPlayer"); - sp thisplayer = getMediaPlayer(env, thiz); - if (thisplayer == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", "This player not initialized"); - return; - } - sp nextplayer = (java_player == NULL) ? NULL : getMediaPlayer(env, java_player); - if (nextplayer == NULL && java_player != NULL) { - jniThrowException(env, "java/lang/IllegalStateException", "That player not initialized"); - return; - } - - if (nextplayer == thisplayer) { - jniThrowException(env, "java/lang/IllegalArgumentException", "Next player can't be self"); - return; - } - // tie the two players together - process_media_player_call( - env, thiz, thisplayer->setNextMediaPlayer(nextplayer), - "java/lang/IllegalArgumentException", - "setNextMediaPlayer failed." ); - ; -} - ///////////////////////////////////////////////////////////////////////////////////// // Modular DRM begin @@ -1498,12 +1494,13 @@ static const JNINativeMethod gMethods[] = { {"_notifyAt", "(J)V", (void *)android_media_MediaPlayer2_notifyAt}, {"_pause", "()V", (void *)android_media_MediaPlayer2_pause}, {"isPlaying", "()Z", (void *)android_media_MediaPlayer2_isPlaying}, - {"getCurrentPosition", "()I", (void *)android_media_MediaPlayer2_getCurrentPosition}, - {"getDuration", "()I", (void *)android_media_MediaPlayer2_getDuration}, + {"getCurrentPosition", "()J", (void *)android_media_MediaPlayer2_getCurrentPosition}, + {"getDuration", "()J", (void *)android_media_MediaPlayer2_getDuration}, {"_release", "()V", (void *)android_media_MediaPlayer2_release}, {"_reset", "()V", (void *)android_media_MediaPlayer2_reset}, {"_getAudioStreamType", "()I", (void *)android_media_MediaPlayer2_getAudioStreamType}, {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer2_setParameter}, + {"getParameter", "(I)Landroid/os/Parcel;", (void *)android_media_MediaPlayer2_getParameter}, {"setLooping", "(Z)V", (void *)android_media_MediaPlayer2_setLooping}, {"isLooping", "()Z", (void *)android_media_MediaPlayer2_isLooping}, {"_setVolume", "(FF)V", (void *)android_media_MediaPlayer2_setVolume}, @@ -1517,7 +1514,6 @@ static const JNINativeMethod gMethods[] = { {"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_set_audio_session_id}, {"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer2_setAuxEffectSendLevel}, {"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer2_attachAuxEffect}, - {"setNextMediaPlayer", "(Landroid/media/MediaPlayer2;)V", (void *)android_media_MediaPlayer2_setNextMediaPlayer}, // Modular DRM { "_prepareDrm", "([B[B)V", (void *)android_media_MediaPlayer2_prepareDrm }, { "_releaseDrm", "()V", (void *)android_media_MediaPlayer2_releaseDrm },