Migrate media constants from androidx.media.util.MediaConstants
Adds root extras and metadata extras to MockMediaLibraryService and MockMediaBrowserCompatService and completed test cases for asserting interoperability with a media1 or Media3 browser. PiperOrigin-RevId: 480854842
This commit is contained in:
parent
7e8f0f0918
commit
006a519a0e
@ -40,7 +40,7 @@ project.ext {
|
|||||||
androidxConstraintLayoutVersion = '2.0.4'
|
androidxConstraintLayoutVersion = '2.0.4'
|
||||||
androidxCoreVersion = '1.7.0'
|
androidxCoreVersion = '1.7.0'
|
||||||
androidxFuturesVersion = '1.1.0'
|
androidxFuturesVersion = '1.1.0'
|
||||||
androidxMediaVersion = '1.4.3'
|
androidxMediaVersion = '1.6.0'
|
||||||
androidxMedia2Version = '1.2.0'
|
androidxMedia2Version = '1.2.0'
|
||||||
androidxMultidexVersion = '2.0.1'
|
androidxMultidexVersion = '2.0.1'
|
||||||
androidxRecyclerViewVersion = '1.2.1'
|
androidxRecyclerViewVersion = '1.2.1'
|
||||||
|
@ -15,18 +15,77 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.session;
|
package androidx.media3.session;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcelable;
|
||||||
import android.support.v4.media.session.MediaControllerCompat;
|
import android.support.v4.media.session.MediaControllerCompat;
|
||||||
import android.support.v4.media.session.MediaSessionCompat;
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
import android.support.v4.media.session.PlaybackStateCompat;
|
import android.support.v4.media.session.PlaybackStateCompat;
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
|
import androidx.media3.common.MediaMetadata;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.session.MediaLibraryService.LibraryParams;
|
import androidx.media3.session.MediaLibraryService.LibraryParams;
|
||||||
|
import androidx.media3.session.MediaLibraryService.MediaLibrarySession;
|
||||||
|
|
||||||
/** Constants that can be shared between media session and controller. */
|
/** Constants that can be shared between media session and controller. */
|
||||||
public final class MediaConstants {
|
public final class MediaConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bundle key to indicate a preference that a region of space for the skip to next control should
|
* The legacy error code for expired authentication.
|
||||||
* always be blocked out in the UI, even when the seek to next standard action is not supported.
|
*
|
||||||
|
* <p>Use this error code to indicate an expired authentication when {@linkplain
|
||||||
|
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful
|
||||||
|
* service call.
|
||||||
|
*
|
||||||
|
* @see PlaybackStateCompat#ERROR_CODE_AUTHENTICATION_EXPIRED
|
||||||
|
*/
|
||||||
|
public static final int ERROR_CODE_AUTHENTICATION_EXPIRED_COMPAT = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extras key for the localized error resolution string.
|
||||||
|
*
|
||||||
|
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain
|
||||||
|
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful
|
||||||
|
* service call.
|
||||||
|
*/
|
||||||
|
public static final String EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT =
|
||||||
|
androidx.media.utils.MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extras key for the error resolution intent.
|
||||||
|
*
|
||||||
|
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain
|
||||||
|
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful
|
||||||
|
* service call.
|
||||||
|
*/
|
||||||
|
public static final String EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT_COMPAT =
|
||||||
|
androidx.media.utils.MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used to store a {@link PendingIntent}. When launched, the {@link
|
||||||
|
* PendingIntent} should allow users to resolve the current playback state error.
|
||||||
|
*
|
||||||
|
* <p>Applications must also set the error message and {@link
|
||||||
|
* #EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT} for cases in which the intent cannot be auto
|
||||||
|
* launched.
|
||||||
|
*
|
||||||
|
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain
|
||||||
|
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful
|
||||||
|
* service call. Must be inserted {@linkplain Bundle#putParcelable(String, Parcelable) into the
|
||||||
|
* bundle as a parcelable}.
|
||||||
|
*
|
||||||
|
* <p>TYPE: {@link PendingIntent}.
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_ERROR_RESOLUTION_USING_CAR_APP_LIBRARY_INTENT_COMPAT =
|
||||||
|
androidx.media.utils.MediaConstants
|
||||||
|
.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_USING_CAR_APP_LIBRARY_INTENT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key to indicate a preference that a region of space for the skip to next control
|
||||||
|
* should always be blocked out in the UI, even when the seek to next standard action is not
|
||||||
|
* supported.
|
||||||
*
|
*
|
||||||
* <p>This may be used when the session temporarily disallows {@link
|
* <p>This may be used when the session temporarily disallows {@link
|
||||||
* androidx.media3.common.Player#COMMAND_SEEK_TO_NEXT} by design.
|
* androidx.media3.common.Player#COMMAND_SEEK_TO_NEXT} by design.
|
||||||
@ -39,12 +98,12 @@ public final class MediaConstants {
|
|||||||
* @see androidx.media3.common.Player#COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
|
* @see androidx.media3.common.Player#COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
|
||||||
*/
|
*/
|
||||||
public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_NEXT =
|
public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_NEXT =
|
||||||
"android.media.playback.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_NEXT";
|
androidx.media.utils.MediaConstants.SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bundle key to indicate a preference that a region of space for the skip to previous control
|
* {@link Bundle} key to indicate a preference that a region of space for the skip to previous
|
||||||
* should always be blocked out in the UI, even when the seek to previous standard action is not
|
* control should always be blocked out in the UI, even when the seek to previous standard action
|
||||||
* supported.
|
* is not supported.
|
||||||
*
|
*
|
||||||
* <p>This may be used when the session temporarily disallows {@link
|
* <p>This may be used when the session temporarily disallows {@link
|
||||||
* androidx.media3.common.Player#COMMAND_SEEK_TO_PREVIOUS} by design.
|
* androidx.media3.common.Player#COMMAND_SEEK_TO_PREVIOUS} by design.
|
||||||
@ -57,43 +116,309 @@ public final class MediaConstants {
|
|||||||
* @see androidx.media3.common.Player#COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
|
* @see androidx.media3.common.Player#COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
|
||||||
*/
|
*/
|
||||||
public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV =
|
public static final String EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV =
|
||||||
"android.media.playback.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_PREVIOUS";
|
androidx.media.utils.MediaConstants.SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The extras key for the localized error resolution string.
|
* {@link Bundle} key used in {@link MediaMetadata#extras} to indicate the playback completion
|
||||||
|
* status of the corresponding {@link MediaItem}.
|
||||||
*
|
*
|
||||||
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@link
|
* <p>TYPE: int. Possible values are separate constants.
|
||||||
* LibraryResult#ofError(int, LibraryParams) creating a LibraryResult} for an unsuccessful service
|
|
||||||
* call.
|
|
||||||
*
|
*
|
||||||
* @see
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
* androidx.media.utils.MediaConstants#PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED
|
||||||
|
* @see #EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
|
||||||
|
* @see #EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
|
||||||
*/
|
*/
|
||||||
public static final String EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT =
|
@UnstableApi
|
||||||
"android.media.extras.ERROR_RESOLUTION_ACTION_LABEL";
|
public static final String EXTRAS_KEY_COMPLETION_STATUS =
|
||||||
/**
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
* The extras key for the error resolution intent.
|
|
||||||
*
|
|
||||||
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@link
|
|
||||||
* LibraryResult#ofError(int, LibraryParams) creating a LibraryResult} for an unsuccessful service
|
|
||||||
* call.
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* androidx.media.utils.MediaConstants#PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT
|
|
||||||
*/
|
|
||||||
public static final String EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT_COMPAT =
|
|
||||||
"android.media.extras.ERROR_RESOLUTION_ACTION_INTENT";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The legacy error code for expired authentication.
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate that the corresponding
|
||||||
|
* {@link MediaItem} has not been played by the user.
|
||||||
*
|
*
|
||||||
* <p>Use this error code to indicate an expired authentication when {@link
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
* LibraryResult#ofError(int, LibraryParams) creating a LibraryResult} for an unsuccessful service
|
* @see MediaMetadata#extras
|
||||||
* call.
|
* @see #EXTRAS_KEY_COMPLETION_STATUS
|
||||||
*
|
|
||||||
* @see PlaybackStateCompat#ERROR_CODE_AUTHENTICATION_EXPIRED
|
|
||||||
*/
|
*/
|
||||||
public static final int ERROR_CODE_AUTHENTICATION_EXPIRED_COMPAT = 3;
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate that the corresponding
|
||||||
|
* {@link MediaItem} has been partially played by the user.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_KEY_COMPLETION_STATUS
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED =
|
||||||
|
androidx.media.utils.MediaConstants
|
||||||
|
.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate that the corresponding
|
||||||
|
* {@link MediaItem} has been fully played by the user.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_KEY_COMPLETION_STATUS
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link MediaMetadata#extras} to indicate an amount of completion
|
||||||
|
* progress for the corresponding {@link MediaItem}. This extra augments {@link
|
||||||
|
* #EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED the partially played status} by indicating how
|
||||||
|
* much has been played by the user.
|
||||||
|
*
|
||||||
|
* <p>TYPE: double, a value between 0.0 and 1.0, inclusive. 0.0 indicates no completion progress
|
||||||
|
* (item is not started) and 1.0 indicates full completion progress (item is fully played). Values
|
||||||
|
* in between indicate partial progress (for example, 0.75 indicates the item is 75% complete).
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_COMPLETION_PERCENTAGE =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used to indicate a preference about how playable instances of {@link
|
||||||
|
* MediaItem} are presented.
|
||||||
|
*
|
||||||
|
* <p>If exposed through {@link LibraryParams#extras} of the {@link LibraryResult} returned by
|
||||||
|
* {@link MediaBrowser#getLibraryRoot}, the preference applies to all playable items within the
|
||||||
|
* browse tree.
|
||||||
|
*
|
||||||
|
* <p>If exposed through {@link MediaMetadata#extras} of a {@linkplain MediaMetadata#folderType
|
||||||
|
* browsable media item}, the preference applies to only the immediate playable children. It takes
|
||||||
|
* precedence over preferences received with {@link MediaBrowser#getLibraryRoot}.
|
||||||
|
*
|
||||||
|
* <p>TYPE: int. Possible values are separate constants.
|
||||||
|
*
|
||||||
|
* @see MediaBrowser#getLibraryRoot(LibraryParams)
|
||||||
|
* @see LibraryResult#params
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_CONTENT_STYLE_PLAYABLE =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used to indicate a preference about how browsable instances of {@link
|
||||||
|
* MediaItem} are presented.
|
||||||
|
*
|
||||||
|
* <p>If exposed through {@link LibraryParams#extras} of the {@link LibraryResult} returned by
|
||||||
|
* {@link MediaBrowser#getLibraryRoot}, the preference applies to all browsable items within the
|
||||||
|
* browse tree.
|
||||||
|
*
|
||||||
|
* <p>If exposed through {@link MediaMetadata#extras} of a {@linkplain MediaMetadata#folderType
|
||||||
|
* browsable media item}, the preference applies to only the immediate browsable children. It
|
||||||
|
* takes precedence over preferences received with {@link
|
||||||
|
* MediaBrowser#getLibraryRoot(LibraryParams)}.
|
||||||
|
*
|
||||||
|
* <p>TYPE: int. Possible values are separate constants.
|
||||||
|
*
|
||||||
|
* @see MediaBrowser#getLibraryRoot(LibraryParams)
|
||||||
|
* @see LibraryResult#params
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_CONTENT_STYLE_BROWSABLE =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link MediaMetadata#extras} to indicate a preference about how the
|
||||||
|
* corresponding {@link MediaItem} is presented.
|
||||||
|
*
|
||||||
|
* <p>This preference takes precedence over those expressed by {@link
|
||||||
|
* #EXTRAS_KEY_CONTENT_STYLE_PLAYABLE} and {@link #EXTRAS_KEY_CONTENT_STYLE_BROWSABLE}.
|
||||||
|
*
|
||||||
|
* <p>TYPE: int. Possible values are separate constants.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM
|
||||||
|
* @see #EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate a preference that certain
|
||||||
|
* instances of {@link MediaItem} should be presented as list items.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
|
||||||
|
* @see #EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate a preference that certain
|
||||||
|
* instances of {@link MediaItem} should be presented as grid items.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
|
||||||
|
* @see #EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate a preference that
|
||||||
|
* browsable instances of {@link MediaItem} should be presented as "category" list items. This
|
||||||
|
* means the items provide icons that render well when they do <strong>not</strong> fill all of
|
||||||
|
* the available area.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used in {@link MediaMetadata#extras} to indicate a preference that
|
||||||
|
* browsable instances of {@link MediaItem} should be presented as "category" grid items. This
|
||||||
|
* means the items provide icons that render well when they do <strong>not</strong> fill all of
|
||||||
|
* the available area.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
* @see #EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final int EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link MediaMetadata#extras} to indicate that certain instances of
|
||||||
|
* {@link MediaItem} are related as a group, with a title that is specified through the bundle
|
||||||
|
* value. Items that are children of the same browsable node and have the same title are members
|
||||||
|
* of the same group. An app may present a group's items as a contiguous block and display the
|
||||||
|
* title alongside the group.
|
||||||
|
*
|
||||||
|
* <p>TYPE: String. Should be human readable and localized.
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE =
|
||||||
|
androidx.media.utils.MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link MediaMetadata#extras} to indicate that the corresponding
|
||||||
|
* {@link MediaItem} has explicit content (that is, user discretion is advised when viewing or
|
||||||
|
* listening to this content).
|
||||||
|
*
|
||||||
|
* <p>TYPE: long (to enable, use value {@link #EXTRAS_VALUE_ATTRIBUTE_PRESENT})
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi public static final String EXTRAS_KEY_IS_EXPLICIT = "android.media.IS_EXPLICIT";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link MediaMetadata#extras} to indicate that the corresponding
|
||||||
|
* {@link MediaItem} is an advertisement.
|
||||||
|
*
|
||||||
|
* <p>TYPE: long (to enable, use value {@link #EXTRAS_VALUE_ATTRIBUTE_PRESENT})
|
||||||
|
*
|
||||||
|
* @see MediaMetadata.Builder#setExtras(Bundle)
|
||||||
|
* @see MediaMetadata#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_IS_ADVERTISEMENT =
|
||||||
|
androidx.media.utils.MediaConstants.METADATA_KEY_IS_ADVERTISEMENT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} value used to indicate the presence of an attribute described by its
|
||||||
|
* corresponding key.
|
||||||
|
*/
|
||||||
|
@UnstableApi public static final long EXTRAS_VALUE_ATTRIBUTE_PRESENT = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link LibraryParams#extras} passed to {@link
|
||||||
|
* MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession, MediaSession.ControllerInfo,
|
||||||
|
* LibraryParams)} to indicate the maximum number of children of the root node that can be
|
||||||
|
* supported by the {@link MediaBrowser}. Excess root children may be omitted or made less
|
||||||
|
* discoverable.
|
||||||
|
*
|
||||||
|
* <p>TYPE: int
|
||||||
|
*
|
||||||
|
* @see MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
|
||||||
|
* MediaSession.ControllerInfo, LibraryParams)
|
||||||
|
* @see LibraryParams#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_ROOT_CHILDREN_LIMIT =
|
||||||
|
androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used in {@link LibraryParams#extras} passed by the {@link MediaBrowser} as
|
||||||
|
* root hints to {@link MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
|
||||||
|
* MediaSession.ControllerInfo, LibraryParams)} to indicate the recommended size, in pixels, for
|
||||||
|
* media art bitmaps. Much smaller images may not render well, and much larger images may cause
|
||||||
|
* inefficient resource consumption.
|
||||||
|
*
|
||||||
|
* @see MediaBrowser#getLibraryRoot(LibraryParams)
|
||||||
|
* @see MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
|
||||||
|
* MediaSession.ControllerInfo, LibraryParams)
|
||||||
|
* @see LibraryParams#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_MEDIA_ART_SIZE_PIXELS =
|
||||||
|
androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_MEDIA_ART_SIZE_PIXELS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Bundle} key used to indicate that the media app that provides the service supports
|
||||||
|
* showing a settings page.
|
||||||
|
*
|
||||||
|
* <p>Use this key to populate the {@link LibraryParams#extras} of the {@link LibraryResult}
|
||||||
|
* returned by {@link MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
|
||||||
|
* MediaSession.ControllerInfo, LibraryParams)}. Use this key with {@link
|
||||||
|
* Bundle#putParcelable(String, Parcelable)} to put a {@link PendingIntent} that is created using
|
||||||
|
* {@code CarPendingIntent#getCarApp()}.
|
||||||
|
*
|
||||||
|
* <p>The {@link Intent} carried by the pending intent needs to have the component name set to a
|
||||||
|
* <a href="http://developer.android.com/training/cars/apps#create-carappservice">Car App Library
|
||||||
|
* service</a> that needs to exist in the same application package as the media browser service.
|
||||||
|
*
|
||||||
|
* <p>TYPE: {@link PendingIntent}.
|
||||||
|
*
|
||||||
|
* @see MediaLibrarySession.Callback#onGetLibraryRoot(MediaLibrarySession,
|
||||||
|
* MediaSession.ControllerInfo, LibraryParams)
|
||||||
|
* @see LibraryParams#extras
|
||||||
|
*/
|
||||||
|
@UnstableApi
|
||||||
|
public static final String EXTRAS_KEY_APPLICATION_PREFERENCES_USING_CAR_APP_LIBRARY_INTENT =
|
||||||
|
androidx.media.utils.MediaConstants
|
||||||
|
.BROWSER_SERVICE_EXTRAS_KEY_APPLICATION_PREFERENCES_USING_CAR_APP_LIBRARY_INTENT;
|
||||||
|
|
||||||
/* package */ static final String SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED =
|
/* package */ static final String SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED =
|
||||||
"androidx.media3.session.SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED";
|
"androidx.media3.session.SESSION_COMMAND_ON_CAPTIONING_ENABLED_CHANGED";
|
||||||
|
@ -26,6 +26,8 @@ public class MediaBrowserConstants {
|
|||||||
|
|
||||||
public static final String ROOT_ID = "rootId";
|
public static final String ROOT_ID = "rootId";
|
||||||
public static final Bundle ROOT_EXTRAS = new Bundle();
|
public static final Bundle ROOT_EXTRAS = new Bundle();
|
||||||
|
public static final String ROOT_EXTRAS_KEY = "root_extras_key";
|
||||||
|
public static final int ROOT_EXTRAS_VALUE = 4321;
|
||||||
|
|
||||||
public static final String MEDIA_ID_GET_BROWSABLE_ITEM = "media_id_get_browsable_item";
|
public static final String MEDIA_ID_GET_BROWSABLE_ITEM = "media_id_get_browsable_item";
|
||||||
public static final String MEDIA_ID_GET_PLAYABLE_ITEM = "media_id_get_playable_item";
|
public static final String MEDIA_ID_GET_PLAYABLE_ITEM = "media_id_get_playable_item";
|
||||||
@ -71,7 +73,7 @@ public class MediaBrowserConstants {
|
|||||||
public static final String CUSTOM_ACTION_ASSERT_PARAMS = "assertParams";
|
public static final String CUSTOM_ACTION_ASSERT_PARAMS = "assertParams";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ROOT_EXTRAS.putString(ROOT_ID, ROOT_ID);
|
ROOT_EXTRAS.putInt(ROOT_EXTRAS_KEY, ROOT_EXTRAS_VALUE);
|
||||||
|
|
||||||
CUSTOM_ACTION_EXTRAS.putString(CUSTOM_ACTION, CUSTOM_ACTION);
|
CUSTOM_ACTION_EXTRAS.putString(CUSTOM_ACTION, CUSTOM_ACTION);
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ public class MediaBrowserServiceCompatConstants {
|
|||||||
public static final String TEST_CONNECT_REJECTED = "testConnect_rejected";
|
public static final String TEST_CONNECT_REJECTED = "testConnect_rejected";
|
||||||
public static final String TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE =
|
public static final String TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE =
|
||||||
"testOnChildrenChanged_subscribeAndUnsubscribe";
|
"testOnChildrenChanged_subscribeAndUnsubscribe";
|
||||||
|
public static final String TEST_GET_LIBRARY_ROOT = "getLibraryRoot_correctExtraKeyAndValue";
|
||||||
|
public static final String TEST_GET_CHILDREN = "getChildren_correctMetadataExtras";
|
||||||
|
|
||||||
private MediaBrowserServiceCompatConstants() {}
|
private MediaBrowserServiceCompatConstants() {}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.session;
|
package androidx.media3.session;
|
||||||
|
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.METADATA_ARTWORK_URI;
|
import static androidx.media3.test.session.common.CommonConstants.METADATA_ARTWORK_URI;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.METADATA_DESCRIPTION;
|
import static androidx.media3.test.session.common.CommonConstants.METADATA_DESCRIPTION;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.METADATA_EXTRA_KEY;
|
import static androidx.media3.test.session.common.CommonConstants.METADATA_EXTRA_KEY;
|
||||||
@ -38,6 +40,8 @@ import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_I
|
|||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID_LONG_LIST;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID_LONG_LIST;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID_NO_CHILDREN;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID_NO_CHILDREN;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_KEY;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_VALUE;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY_EMPTY_RESULT;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.SEARCH_QUERY_EMPTY_RESULT;
|
||||||
@ -67,6 +71,7 @@ import androidx.media3.test.session.common.TestUtils;
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.ext.truth.os.BundleSubject;
|
import androidx.test.ext.truth.os.BundleSubject;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
@ -96,6 +101,11 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
|
|||||||
});
|
});
|
||||||
connectAndWait();
|
connectAndWait();
|
||||||
assertThat(browserCompat.getRoot()).isEqualTo(ROOT_ID);
|
assertThat(browserCompat.getRoot()).isEqualTo(ROOT_ID);
|
||||||
|
assertThat(
|
||||||
|
browserCompat
|
||||||
|
.getExtras()
|
||||||
|
.getInt(ROOT_EXTRAS_KEY, /* defaultValue= */ ROOT_EXTRAS_VALUE + 1))
|
||||||
|
.isEqualTo(ROOT_EXTRAS_VALUE);
|
||||||
|
|
||||||
// Note: Cannot use equals() here because browser compat's extra contains server version,
|
// Note: Cannot use equals() here because browser compat's extra contains server version,
|
||||||
// extra binder, and extra messenger.
|
// extra binder, and extra messenger.
|
||||||
@ -202,22 +212,18 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
|
|||||||
@Test
|
@Test
|
||||||
public void getChildren() throws InterruptedException {
|
public void getChildren() throws InterruptedException {
|
||||||
String testParentId = PARENT_ID;
|
String testParentId = PARENT_ID;
|
||||||
|
|
||||||
connectAndWait();
|
connectAndWait();
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
List<MediaItem> receivedChildren = new ArrayList<>();
|
||||||
|
final String[] receivedParentId = new String[1];
|
||||||
|
|
||||||
browserCompat.subscribe(
|
browserCompat.subscribe(
|
||||||
testParentId,
|
testParentId,
|
||||||
new SubscriptionCallback() {
|
new SubscriptionCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onChildrenLoaded(String parentId, List<MediaItem> children) {
|
public void onChildrenLoaded(String parentId, List<MediaItem> children) {
|
||||||
assertThat(parentId).isEqualTo(testParentId);
|
receivedParentId[0] = parentId;
|
||||||
assertThat(children).isNotNull();
|
receivedChildren.addAll(children);
|
||||||
assertThat(children.size()).isEqualTo(GET_CHILDREN_RESULT.size());
|
|
||||||
|
|
||||||
// Compare the given results with originals.
|
|
||||||
for (int i = 0; i < children.size(); i++) {
|
|
||||||
assertThat(children.get(i).getMediaId()).isEqualTo(GET_CHILDREN_RESULT.get(i));
|
|
||||||
}
|
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +232,23 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
|
|||||||
assertWithMessage("").fail();
|
assertWithMessage("").fail();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
|
assertThat(receivedParentId[0]).isEqualTo(testParentId);
|
||||||
|
assertThat(receivedChildren).hasSize(GET_CHILDREN_RESULT.size());
|
||||||
|
// Compare the given results with originals.
|
||||||
|
for (int i = 0; i < receivedChildren.size(); i++) {
|
||||||
|
MediaItem mediaItem = receivedChildren.get(i);
|
||||||
|
assertThat(mediaItem.getMediaId()).isEqualTo(GET_CHILDREN_RESULT.get(i));
|
||||||
|
assertThat(
|
||||||
|
mediaItem
|
||||||
|
.getDescription()
|
||||||
|
.getExtras()
|
||||||
|
.getInt(
|
||||||
|
EXTRAS_KEY_COMPLETION_STATUS,
|
||||||
|
/* defaultValue= */ EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + 1))
|
||||||
|
.isEqualTo(EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -17,12 +17,17 @@ package androidx.media3.session;
|
|||||||
|
|
||||||
import static androidx.media3.session.LibraryResult.RESULT_ERROR_BAD_VALUE;
|
import static androidx.media3.session.LibraryResult.RESULT_ERROR_BAD_VALUE;
|
||||||
import static androidx.media3.session.LibraryResult.RESULT_SUCCESS;
|
import static androidx.media3.session.LibraryResult.RESULT_SUCCESS;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA3_LIBRARY_SERVICE;
|
import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA3_LIBRARY_SERVICE;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.CUSTOM_ACTION_ASSERT_PARAMS;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.CUSTOM_ACTION_ASSERT_PARAMS;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.LONG_LIST_COUNT;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.LONG_LIST_COUNT;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.NOTIFY_CHILDREN_CHANGED_EXTRAS;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.NOTIFY_CHILDREN_CHANGED_EXTRAS;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.NOTIFY_CHILDREN_CHANGED_ITEM_COUNT;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.NOTIFY_CHILDREN_CHANGED_ITEM_COUNT;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_KEY;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_VALUE;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ALL;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ALL;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ALL_WITH_NON_SUBSCRIBED_ID;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.SUBSCRIBE_ID_NOTIFY_CHILDREN_CHANGED_TO_ALL_WITH_NON_SUBSCRIBED_ID;
|
||||||
@ -98,6 +103,45 @@ public class MediaBrowserListenerTest extends MediaControllerListenerTest {
|
|||||||
assertThat(TestUtils.equals(ROOT_EXTRAS, result.params.extras)).isTrue();
|
assertThat(TestUtils.equals(ROOT_EXTRAS, result.params.extras)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getLibraryRoot_correctExtraKeyAndValue() throws Exception {
|
||||||
|
MediaBrowser browser = createBrowser();
|
||||||
|
|
||||||
|
LibraryResult<MediaItem> resultForLibraryRoot =
|
||||||
|
threadTestRule
|
||||||
|
.getHandler()
|
||||||
|
.postAndSync(() -> browser.getLibraryRoot(new LibraryParams.Builder().build()))
|
||||||
|
.get(TIMEOUT_MS, MILLISECONDS);
|
||||||
|
|
||||||
|
Bundle extras = resultForLibraryRoot.params.extras;
|
||||||
|
|
||||||
|
assertThat(extras.getInt(ROOT_EXTRAS_KEY, /* defaultValue= */ ROOT_EXTRAS_VALUE + 1))
|
||||||
|
.isEqualTo(ROOT_EXTRAS_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getChildren_correctMetadataExtras() throws Exception {
|
||||||
|
LibraryParams params = MediaTestUtils.createLibraryParams();
|
||||||
|
MediaBrowser browser = createBrowser();
|
||||||
|
|
||||||
|
LibraryResult<ImmutableList<MediaItem>> libraryResult =
|
||||||
|
threadTestRule
|
||||||
|
.getHandler()
|
||||||
|
.postAndSync(
|
||||||
|
() -> browser.getChildren(PARENT_ID, /* page= */ 4, /* pageSize= */ 10, params))
|
||||||
|
.get(TIMEOUT_MS, MILLISECONDS);
|
||||||
|
|
||||||
|
assertThat(libraryResult.resultCode).isEqualTo(RESULT_SUCCESS);
|
||||||
|
assertThat(libraryResult.value).isNotEmpty();
|
||||||
|
for (MediaItem mediaItem : libraryResult.value) {
|
||||||
|
int status =
|
||||||
|
mediaItem.mediaMetadata.extras.getInt(
|
||||||
|
EXTRAS_KEY_COMPLETION_STATUS,
|
||||||
|
/* defaultValue= */ EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + 1);
|
||||||
|
assertThat(status).isEqualTo(EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getItem_browsable() throws Exception {
|
public void getItem_browsable() throws Exception {
|
||||||
String mediaId = MediaBrowserConstants.MEDIA_ID_GET_BROWSABLE_ITEM;
|
String mediaId = MediaBrowserConstants.MEDIA_ID_GET_BROWSABLE_ITEM;
|
||||||
@ -144,14 +188,15 @@ public class MediaBrowserListenerTest extends MediaControllerListenerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getChildren() throws Exception {
|
public void getChildren_correctLibraryResultWithExtras() throws Exception {
|
||||||
String parentId = MediaBrowserConstants.PARENT_ID;
|
String parentId = PARENT_ID;
|
||||||
int page = 4;
|
int page = 4;
|
||||||
int pageSize = 10;
|
int pageSize = 10;
|
||||||
LibraryParams params = MediaTestUtils.createLibraryParams();
|
LibraryParams params = MediaTestUtils.createLibraryParams();
|
||||||
|
|
||||||
MediaBrowser browser = createBrowser();
|
MediaBrowser browser = createBrowser();
|
||||||
setExpectedLibraryParam(browser, params);
|
setExpectedLibraryParam(browser, params);
|
||||||
|
|
||||||
LibraryResult<ImmutableList<MediaItem>> result =
|
LibraryResult<ImmutableList<MediaItem>> result =
|
||||||
threadTestRule
|
threadTestRule
|
||||||
.getHandler()
|
.getHandler()
|
||||||
@ -159,7 +204,6 @@ public class MediaBrowserListenerTest extends MediaControllerListenerTest {
|
|||||||
.get(TIMEOUT_MS, MILLISECONDS);
|
.get(TIMEOUT_MS, MILLISECONDS);
|
||||||
assertThat(result.resultCode).isEqualTo(RESULT_SUCCESS);
|
assertThat(result.resultCode).isEqualTo(RESULT_SUCCESS);
|
||||||
MediaTestUtils.assertLibraryParamsEquals(params, result.params);
|
MediaTestUtils.assertLibraryParamsEquals(params, result.params);
|
||||||
|
|
||||||
MediaTestUtils.assertPaginatedListHasIds(
|
MediaTestUtils.assertPaginatedListHasIds(
|
||||||
result.value, MediaBrowserConstants.GET_CHILDREN_RESULT, page, pageSize);
|
result.value, MediaBrowserConstants.GET_CHILDREN_RESULT, page, pageSize);
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,15 @@
|
|||||||
package androidx.media3.session;
|
package androidx.media3.session;
|
||||||
|
|
||||||
import static androidx.media3.session.LibraryResult.RESULT_SUCCESS;
|
import static androidx.media3.session.LibraryResult.RESULT_SUCCESS;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA_BROWSER_SERVICE_COMPAT;
|
import static androidx.media3.test.session.common.CommonConstants.MOCK_MEDIA_BROWSER_SERVICE_COMPAT;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.PARENT_ID;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_KEY;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS_VALUE;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_CONNECT_REJECTED;
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_CONNECT_REJECTED;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_CHILDREN;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_LIBRARY_ROOT;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE;
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE;
|
||||||
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
|
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@ -25,13 +32,16 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
|||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media.MediaBrowserServiceCompat;
|
import androidx.media.MediaBrowserServiceCompat;
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.session.MediaLibraryService.LibraryParams;
|
import androidx.media3.session.MediaLibraryService.LibraryParams;
|
||||||
import androidx.media3.test.session.common.HandlerThreadTestRule;
|
import androidx.media3.test.session.common.HandlerThreadTestRule;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.LargeTest;
|
import androidx.test.filters.LargeTest;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
@ -137,4 +147,56 @@ public class MediaBrowserListenerWithMediaBrowserServiceCompatTest {
|
|||||||
// Wait for some time. Exception will be thrown in the listener if error happens.
|
// Wait for some time. Exception will be thrown in the listener if error happens.
|
||||||
Thread.sleep(TIMEOUT_MS);
|
Thread.sleep(TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getLibraryRoot_correctExtraKeyAndValue() throws Exception {
|
||||||
|
remoteService.setProxyForTest(TEST_GET_LIBRARY_ROOT);
|
||||||
|
MediaBrowser browser = createBrowser(/* listener= */ null);
|
||||||
|
|
||||||
|
LibraryResult<MediaItem> resultForLibraryRoot =
|
||||||
|
threadTestRule
|
||||||
|
.getHandler()
|
||||||
|
.postAndSync(() -> browser.getLibraryRoot(new LibraryParams.Builder().build()))
|
||||||
|
.get(TIMEOUT_MS, MILLISECONDS);
|
||||||
|
|
||||||
|
Bundle extras = resultForLibraryRoot.params.extras;
|
||||||
|
assertThat(extras.getInt(ROOT_EXTRAS_KEY, ROOT_EXTRAS_VALUE + 1)).isEqualTo(ROOT_EXTRAS_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getChildren_correctMetadataExtras() throws Exception {
|
||||||
|
LibraryParams params = MediaTestUtils.createLibraryParams();
|
||||||
|
remoteService.setProxyForTest(TEST_GET_CHILDREN);
|
||||||
|
MediaBrowser browser = createBrowser(/* listener= */ null);
|
||||||
|
|
||||||
|
LibraryResult<ImmutableList<MediaItem>> libraryResult =
|
||||||
|
threadTestRule
|
||||||
|
.getHandler()
|
||||||
|
.postAndSync(
|
||||||
|
() -> browser.getChildren(PARENT_ID, /* page= */ 4, /* pageSize= */ 10, params))
|
||||||
|
.get(TIMEOUT_MS, MILLISECONDS);
|
||||||
|
|
||||||
|
assertThat(libraryResult.resultCode).isEqualTo(RESULT_SUCCESS);
|
||||||
|
assertThat(libraryResult.value).hasSize(MockMediaBrowserServiceCompat.MEDIA_ITEMS.size());
|
||||||
|
for (int i = 0; i < libraryResult.value.size(); i++) {
|
||||||
|
int status =
|
||||||
|
libraryResult
|
||||||
|
.value
|
||||||
|
.get(i)
|
||||||
|
.mediaMetadata
|
||||||
|
.extras
|
||||||
|
.getInt(
|
||||||
|
EXTRAS_KEY_COMPLETION_STATUS,
|
||||||
|
/* defaultValue= */ EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + 1);
|
||||||
|
int expectedStatus =
|
||||||
|
MockMediaBrowserServiceCompat.MEDIA_ITEMS
|
||||||
|
.get(i)
|
||||||
|
.getDescription()
|
||||||
|
.getExtras()
|
||||||
|
.getInt(
|
||||||
|
EXTRAS_KEY_COMPLETION_STATUS,
|
||||||
|
/* defaultValue= */ EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED + 1);
|
||||||
|
assertThat(status).isEqualTo(expectedStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,21 +15,33 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.session;
|
package androidx.media3.session;
|
||||||
|
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
|
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_EXTRAS;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserConstants.ROOT_ID;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_CONNECT_REJECTED;
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_CONNECT_REJECTED;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_CHILDREN;
|
||||||
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_GET_LIBRARY_ROOT;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE;
|
import static androidx.media3.test.session.common.MediaBrowserServiceCompatConstants.TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.support.v4.media.MediaBrowserCompat;
|
||||||
import android.support.v4.media.MediaBrowserCompat.MediaItem;
|
import android.support.v4.media.MediaBrowserCompat.MediaItem;
|
||||||
|
import android.support.v4.media.MediaDescriptionCompat;
|
||||||
import android.support.v4.media.session.MediaSessionCompat;
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
import android.support.v4.media.session.MediaSessionCompat.Callback;
|
import android.support.v4.media.session.MediaSessionCompat.Callback;
|
||||||
import androidx.annotation.GuardedBy;
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.media.MediaBrowserServiceCompat;
|
import androidx.media.MediaBrowserServiceCompat;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.test.session.common.IRemoteMediaBrowserServiceCompat;
|
import androidx.media3.test.session.common.IRemoteMediaBrowserServiceCompat;
|
||||||
|
import androidx.media3.test.session.common.MediaBrowserServiceCompatConstants;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -38,6 +50,12 @@ import java.util.List;
|
|||||||
@UnstableApi
|
@UnstableApi
|
||||||
public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable list of media items sent to controllers for {@link
|
||||||
|
* MediaBrowserServiceCompatConstants#TEST_GET_CHILDREN}.
|
||||||
|
*/
|
||||||
|
public static final ImmutableList<MediaItem> MEDIA_ITEMS = createMediaItems();
|
||||||
|
|
||||||
private static final String TAG = "MockMBSCompat";
|
private static final String TAG = "MockMBSCompat";
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
@ -226,6 +244,12 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
|||||||
case TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE:
|
case TEST_ON_CHILDREN_CHANGED_SUBSCRIBE_AND_UNSUBSCRIBE:
|
||||||
setProxyForTestOnChildrenChanged_subscribeAndUnsubscribe();
|
setProxyForTestOnChildrenChanged_subscribeAndUnsubscribe();
|
||||||
break;
|
break;
|
||||||
|
case TEST_GET_LIBRARY_ROOT:
|
||||||
|
setProxyForTestGetLibraryRoot_correctExtraKeyAndValue();
|
||||||
|
break;
|
||||||
|
case TEST_GET_CHILDREN:
|
||||||
|
setProxyForTestGetChildren_correctMetadataExtras();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unknown testName: " + testName);
|
throw new IllegalArgumentException("Unknown testName: " + testName);
|
||||||
}
|
}
|
||||||
@ -257,5 +281,54 @@ public class MockMediaBrowserServiceCompat extends MediaBrowserServiceCompat {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setProxyForTestGetChildren_correctMetadataExtras() {
|
||||||
|
setMediaBrowserServiceProxy(
|
||||||
|
new MockMediaBrowserServiceCompat.Proxy() {
|
||||||
|
@Override
|
||||||
|
public void onLoadChildren(String parentId, Result<List<MediaItem>> result) {
|
||||||
|
onLoadChildren(parentId, result, new Bundle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadChildren(
|
||||||
|
String parentId, Result<List<MediaItem>> result, Bundle bundle) {
|
||||||
|
result.sendResult(MEDIA_ITEMS);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setProxyForTestGetLibraryRoot_correctExtraKeyAndValue() {
|
||||||
|
setMediaBrowserServiceProxy(
|
||||||
|
new MockMediaBrowserServiceCompat.Proxy() {
|
||||||
|
@Override
|
||||||
|
public BrowserRoot onGetRoot(
|
||||||
|
String clientPackageName, int clientUid, Bundle rootHints) {
|
||||||
|
return new BrowserRoot(ROOT_ID, ROOT_EXTRAS);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableList<MediaItem> createMediaItems() {
|
||||||
|
int[] completionStates =
|
||||||
|
new int[] {
|
||||||
|
EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED,
|
||||||
|
EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED,
|
||||||
|
EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
|
||||||
|
};
|
||||||
|
ImmutableList.Builder<MediaItem> builder = new ImmutableList.Builder<>();
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
extras.putInt(EXTRAS_KEY_COMPLETION_STATUS, completionStates[i]);
|
||||||
|
builder.add(
|
||||||
|
new MediaBrowserCompat.MediaItem(
|
||||||
|
new MediaDescriptionCompat.Builder()
|
||||||
|
.setMediaId("media-id-" + i)
|
||||||
|
.setExtras(extras)
|
||||||
|
.build(),
|
||||||
|
/* flags= */ 0));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,10 @@
|
|||||||
package androidx.media3.session;
|
package androidx.media3.session;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_COMPLETION_STATUS;
|
||||||
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT_COMPAT;
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT_COMPAT;
|
||||||
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT;
|
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT;
|
||||||
|
import static androidx.media3.session.MediaConstants.EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED;
|
||||||
import static androidx.media3.session.MediaTestUtils.assertLibraryParamsEquals;
|
import static androidx.media3.session.MediaTestUtils.assertLibraryParamsEquals;
|
||||||
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
|
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
|
||||||
import static androidx.media3.test.session.common.MediaBrowserConstants.CUSTOM_ACTION;
|
import static androidx.media3.test.session.common.MediaBrowserConstants.CUSTOM_ACTION;
|
||||||
@ -63,7 +65,6 @@ import androidx.media3.common.MediaMetadata;
|
|||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.session.MediaLibraryService.MediaLibrarySession;
|
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo;
|
import androidx.media3.session.MediaSession.ControllerInfo;
|
||||||
import androidx.media3.test.session.common.CommonConstants;
|
import androidx.media3.test.session.common.CommonConstants;
|
||||||
import androidx.media3.test.session.common.TestHandler;
|
import androidx.media3.test.session.common.TestHandler;
|
||||||
@ -425,10 +426,13 @@ public class MockMediaLibraryService extends MediaLibraryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static MediaItem createPlayableMediaItem(String mediaId) {
|
private static MediaItem createPlayableMediaItem(String mediaId) {
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
extras.putInt(EXTRAS_KEY_COMPLETION_STATUS, EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED);
|
||||||
MediaMetadata mediaMetadata =
|
MediaMetadata mediaMetadata =
|
||||||
new MediaMetadata.Builder()
|
new MediaMetadata.Builder()
|
||||||
.setFolderType(MediaMetadata.FOLDER_TYPE_NONE)
|
.setFolderType(MediaMetadata.FOLDER_TYPE_NONE)
|
||||||
.setIsPlayable(true)
|
.setIsPlayable(true)
|
||||||
|
.setExtras(extras)
|
||||||
.build();
|
.build();
|
||||||
return new MediaItem.Builder().setMediaId(mediaId).setMediaMetadata(mediaMetadata).build();
|
return new MediaItem.Builder().setMediaId(mediaId).setMediaMetadata(mediaMetadata).build();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user