diff options
Diffstat (limited to 'TestMediaApp')
7 files changed, 140 insertions, 32 deletions
diff --git a/TestMediaApp/assets/media_items/advanced.json b/TestMediaApp/assets/media_items/advanced.json index 9266a1c..cebe0f1 100644 --- a/TestMediaApp/assets/media_items/advanced.json +++ b/TestMediaApp/assets/media_items/advanced.json @@ -39,6 +39,15 @@ }, { "FLAGS": "browsable", + "PLAYABLE_HINT": "LIST", + "METADATA": { + "MEDIA_ID": "advanced toggles", + "DISPLAY_TITLE": "Node toggles (hide/show specific nodes)" + }, + "INCLUDE":"media_items/toggles.json" + }, + { + "FLAGS": "browsable", "BROWSABLE_HINT": "GRID_CATEGORY", "METADATA": { "MEDIA_ID": "advanced art nodes", diff --git a/TestMediaApp/assets/media_items/toggles.json b/TestMediaApp/assets/media_items/toggles.json new file mode 100644 index 0000000..c12be00 --- /dev/null +++ b/TestMediaApp/assets/media_items/toggles.json @@ -0,0 +1,66 @@ +{ + "FLAGS": "browsable", + + "METADATA": { + "MEDIA_ID": "toggles", + "DISPLAY_TITLE": "Toggles" + }, + + "CHILDREN": [ + { + "FLAGS": "playable", + "METADATA": { + "MEDIA_ID": "toggles Toggle Empty tab", + "DISPLAY_TITLE": "Toggle Empty tab on play", + "DURATION": 3000000 + }, + "EVENTS": [ + { "STATE": "PLAYING", "TOGGLE_ITEM": "only_nodes empty node 1" } + ] + }, + { + "FLAGS": "playable", + "METADATA": { + "MEDIA_ID": "toggles Toggle node toggles", + "DISPLAY_TITLE": "Toggle Node toggles node on play", + "DURATION": 3000000 + }, + "EVENTS": [ + { "STATE": "PLAYING", "TOGGLE_ITEM": "advanced toggles" } + ] + }, + { + "FLAGS": "playable", + "METADATA": { + "MEDIA_ID": "toggles Toggle Album Art", + "DISPLAY_TITLE": "Toggle Album Art on play", + "DURATION": 3000000 + }, + "EVENTS": [ + { "STATE": "PLAYING", "TOGGLE_ITEM": "advanced art nodes" } + ] + }, + { + "FLAGS": "playable", + "METADATA": { + "MEDIA_ID": "toggles Toggle Nature 64", + "DISPLAY_TITLE": "Toggle Nature 64 on play", + "DURATION": 3000000 + }, + "EVENTS": [ + { "STATE": "PLAYING", "TOGGLE_ITEM": "album_art/art_nodes nature 64" } + ] + }, + { + "FLAGS": "playable", + "METADATA": { + "MEDIA_ID": "toggles Toggle Advanced tab", + "DISPLAY_TITLE": "Toggle Advanced tab on play", + "DURATION": 3000000 + }, + "EVENTS": [ + { "STATE": "PLAYING", "TOGGLE_ITEM": "only_nodes advanced" } + ] + } + ] +}
\ No newline at end of file diff --git a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaBrowser.java b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaBrowser.java index 61b3a31..c187448 100644 --- a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaBrowser.java +++ b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaBrowser.java @@ -33,7 +33,6 @@ import androidx.annotation.Nullable; import androidx.media.MediaBrowserServiceCompat; import com.android.car.media.testmediaapp.loader.TmaLoader; -import com.android.car.media.testmediaapp.prefs.TmaEnumPrefs; import com.android.car.media.testmediaapp.prefs.TmaEnumPrefs.TmaAccountType; import com.android.car.media.testmediaapp.prefs.TmaEnumPrefs.TmaBrowseNodeType; import com.android.car.media.testmediaapp.prefs.TmaEnumPrefs.TmaReplyDelay; @@ -41,6 +40,7 @@ import com.android.car.media.testmediaapp.prefs.TmaPrefs; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -148,7 +148,7 @@ public class TmaBrowser extends MediaBrowserServiceCompat { getResources().getString(R.string.no_account), getResources().getString(R.string.select_account), TmaMediaEvent.ResolutionIntent.PREFS, - TmaMediaEvent.Action.NONE, 0, null)); + TmaMediaEvent.Action.NONE, 0, null, null)); } else { // TODO don't reset error in all cases... PlaybackStateCompat.Builder playbackState = new PlaybackStateCompat.Builder(); @@ -193,6 +193,10 @@ public class TmaBrowser extends MediaBrowserServiceCompat { getMediaItemsWithDelay(ROOT_ID, result, query); } + private TmaMediaItem getRoot() { + return mLibrary.getRoot(mPrefs.mRootNodeType.getValue()); + } + private void getMediaItemsWithDelay(@NonNull String parentId, @NonNull Result<List<MediaItem>> result, @Nullable String filter) { // TODO: allow per item override of the delay ? @@ -202,7 +206,7 @@ public class TmaBrowser extends MediaBrowserServiceCompat { if (TmaAccountType.NONE.equals(mPrefs.mAccountType.getValue())) { node = null; } else if (ROOT_ID.equals(parentId)) { - node = mLibrary.getRoot(mPrefs.mRootNodeType.getValue()); + node = getRoot(); } else { node = mLibrary.getMediaItemById(parentId); } @@ -224,7 +228,11 @@ public class TmaBrowser extends MediaBrowserServiceCompat { int selfUpdateDelay = node.getSelfUpdateDelay(); int toShow = (selfUpdateDelay > 0) ? 1 + node.mRevealCounter : childrenCount; for (int childIndex = 0 ; childIndex < toShow; childIndex++) { - items.add(children.get(childIndex).toMediaItem()); + TmaMediaItem child = children.get(childIndex); + if (child.mIsHidden) { + continue; + } + items.add(child.toMediaItem()); } result.sendResult(items); @@ -250,6 +258,9 @@ public class TmaBrowser extends MediaBrowserServiceCompat { } for (TmaMediaItem child : node.getChildren()) { + if (child.mIsHidden) { + continue; + } MediaItem item = child.toMediaItem(); CharSequence title = item.getDescription().getTitle(); if (title != null) { @@ -265,6 +276,20 @@ public class TmaBrowser extends MediaBrowserServiceCompat { } } + void toggleItem(@Nullable TmaMediaItem item) { + if (item == null) { + return; + } + item.mIsHidden = !item.mIsHidden; + if (item.getParent() != null) { + String parentId = item.getParent().getMediaId(); + if (Objects.equals(parentId, getRoot().getMediaId())) { + parentId = ROOT_ID; + } + notifyChildrenChanged(parentId); + } + } + private class UpdateNodeTask implements Runnable { private final String mNodeId; diff --git a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaEvent.java b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaEvent.java index 491f940..8fe30ef 100644 --- a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaEvent.java +++ b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaEvent.java @@ -53,7 +53,7 @@ public class TmaMediaEvent { public static final TmaMediaEvent INSTANT_PLAYBACK = new TmaMediaEvent(EventState.PLAYING, StateErrorCode.UNKNOWN_ERROR, null, null, - ResolutionIntent.NONE, Action.NONE, 0, null); + ResolutionIntent.NONE, Action.NONE, 0, null, null); /** The name of each entry is the value used in the json file. */ public enum EventState { @@ -120,10 +120,11 @@ public class TmaMediaEvent { /** How long to wait before sending the event to the app. */ final int mPostDelayMs; private final String mExceptionClass; + final String mMediaItemIdToToggle; public TmaMediaEvent(EventState state, StateErrorCode errorCode, String errorMessage, String actionLabel, ResolutionIntent resolutionIntent, Action action, int postDelayMs, - String exceptionClass) { + String exceptionClass, String mediaItemIdToToggle) { mState = state; mErrorCode = errorCode; mErrorMessage = errorMessage; @@ -132,6 +133,7 @@ public class TmaMediaEvent { mAction = action; mPostDelayMs = postDelayMs; mExceptionClass = exceptionClass; + mMediaItemIdToToggle = mediaItemIdToToggle; } boolean premiumAccountRequired() { diff --git a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaItem.java b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaItem.java index e2cb533..a759eb4 100644 --- a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaItem.java +++ b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaMediaItem.java @@ -78,9 +78,9 @@ public class TmaMediaItem { /** Internally modifiable list (for includes). */ - private final List<TmaMediaItem> mChildren; - /** Read only list. */ - private final List<TmaMediaItem> mPlayableChildren; + private final List<TmaMediaItem> mChildren = new ArrayList<>(); + /** Internally modifiable list (for includes). */ + private final List<TmaMediaItem> mPlayableChildren = new ArrayList<>(); /** Read only list. */ final List<TmaCustomAction> mCustomActions; /** Read only list. Events triggered when starting the playback. */ @@ -91,6 +91,7 @@ public class TmaMediaItem { private @Nullable TmaMediaItem mParent; int mHearts; int mRevealCounter; + boolean mIsHidden = false; public TmaMediaItem(int flags, ContentStyle playableStyle, ContentStyle browsableStyle, @@ -103,17 +104,9 @@ public class TmaMediaItem { mMediaMetadata = metadata; mSelfUpdateMs = selfUpdateMs; mCustomActions = Collections.unmodifiableList(customActions); - mChildren = children; mMediaEvents = Collections.unmodifiableList(mediaEvents); mInclude = include; - List<TmaMediaItem> playableChildren = new ArrayList<>(children.size()); - for (TmaMediaItem child: mChildren) { - child.setParent(this); - if ((child.mFlags & FLAG_PLAYABLE) != 0) { - playableChildren.add(child); - } - } - mPlayableChildren = Collections.unmodifiableList(playableChildren); + setChildren(children); } private void setParent(@Nullable TmaMediaItem parent) { @@ -171,6 +164,16 @@ public class TmaMediaItem { void setChildren(List<TmaMediaItem> children) { mChildren.clear(); mChildren.addAll(children); + + List<TmaMediaItem> playableChildren = new ArrayList<>(children.size()); + for (TmaMediaItem child: mChildren) { + child.setParent(this); + if ((child.mFlags & FLAG_PLAYABLE) != 0) { + playableChildren.add(child); + } + } + mPlayableChildren.clear(); + mPlayableChildren.addAll(playableChildren); } void updateSessionMetadata(MediaSessionCompat session) { diff --git a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaPlayer.java b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaPlayer.java index 65cc787..43cf3af 100644 --- a/TestMediaApp/src/com/android/car/media/testmediaapp/TmaPlayer.java +++ b/TestMediaApp/src/com/android/car/media/testmediaapp/TmaPlayer.java @@ -32,7 +32,6 @@ import static android.support.v4.media.session.PlaybackStateCompat.STATE_ERROR; import androidx.annotation.Nullable; import android.app.PendingIntent; -import android.content.Context; import android.content.Intent; import android.media.AudioFocusRequest; import android.media.AudioManager; @@ -40,6 +39,7 @@ import android.os.Bundle; import android.os.Handler; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; +import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -59,7 +59,7 @@ public class TmaPlayer extends MediaSessionCompat.Callback { private static final String TAG = "TmaPlayer"; - private final Context mContext; + private final TmaBrowser mBrowser; private final TmaPrefs mPrefs; private final TmaLibrary mLibrary; private final AudioManager mAudioManager; @@ -78,10 +78,10 @@ public class TmaPlayer extends MediaSessionCompat.Callback { private TmaMediaItem mActiveItem; private int mNextEventIndex = -1; - TmaPlayer(Context context, TmaLibrary library, AudioManager audioManager, Handler handler, + TmaPlayer(TmaBrowser browser, TmaLibrary library, AudioManager audioManager, Handler handler, MediaSessionCompat session) { - mContext = context; - mPrefs = TmaPrefs.getInstance(mContext); + mBrowser = browser; + mPrefs = TmaPrefs.getInstance(mBrowser); mLibrary = library; mAudioManager = audioManager; mHandler = handler; @@ -101,9 +101,9 @@ public class TmaPlayer extends MediaSessionCompat.Callback { .setActions(addActions(ACTION_PAUSE)); if (ResolutionIntent.PREFS.equals(event.mResolutionIntent)) { Intent prefsIntent = new Intent(); - prefsIntent.setClass(mContext, TmaPrefsActivity.class); + prefsIntent.setClass(mBrowser, TmaPrefsActivity.class); prefsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, prefsIntent, 0); + PendingIntent pendingIntent = PendingIntent.getActivity(mBrowser, 0, prefsIntent, 0); Bundle extras = new Bundle(); extras.putString(MediaKeys.ERROR_RESOLUTION_ACTION_LABEL, event.mActionLabel); @@ -119,7 +119,7 @@ public class TmaPlayer extends MediaSessionCompat.Callback { private void setActiveItemState(PlaybackStateCompat.Builder state) { if (mActiveItem != null) { for (TmaCustomAction action : mActiveItem.mCustomActions) { - String name = mContext.getResources().getString(action.mNameId); + String name = mBrowser.getResources().getString(action.mNameId); state.addCustomAction(action.mId, name, action.mIcon); } state.setActiveQueueItemId(mActiveItem.getQueueId()); @@ -249,14 +249,14 @@ public class TmaPlayer extends MediaSessionCompat.Callback { mActiveItem.mHearts--; toast("" + mActiveItem.mHearts); } else if (TmaCustomAction.REQUEST_LOCATION.mId.equals(action)) { - mContext.startService(new Intent(mContext, TmaForegroundService.class)); + mBrowser.startService(new Intent(mBrowser, TmaForegroundService.class)); } } } /** Note: this is for quick feedback implementation, media apps should avoid toasts... */ private void toast(String message) { - Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); + Toast.makeText(mBrowser, message, Toast.LENGTH_LONG).show(); } private boolean audioFocusGranted() { @@ -268,6 +268,9 @@ public class TmaPlayer extends MediaSessionCompat.Callback { TmaMediaEvent event = mActiveItem.mMediaEvents.get(mNextEventIndex); event.maybeThrow(); + if (!TextUtils.isEmpty(event.mMediaItemIdToToggle)) { + mBrowser.toggleItem(mLibrary.getMediaItemById(event.mMediaItemIdToToggle)); + } if (event.premiumAccountRequired() && TmaAccountType.PAID.equals(mPrefs.mAccountType.getValue())) { diff --git a/TestMediaApp/src/com/android/car/media/testmediaapp/loader/TmaMediaEventReader.java b/TestMediaApp/src/com/android/car/media/testmediaapp/loader/TmaMediaEventReader.java index 2222afa..4926146 100644 --- a/TestMediaApp/src/com/android/car/media/testmediaapp/loader/TmaMediaEventReader.java +++ b/TestMediaApp/src/com/android/car/media/testmediaapp/loader/TmaMediaEventReader.java @@ -21,8 +21,6 @@ import static com.android.car.media.testmediaapp.loader.TmaLoaderUtils.getEnum; import static com.android.car.media.testmediaapp.loader.TmaLoaderUtils.getInt; import static com.android.car.media.testmediaapp.loader.TmaLoaderUtils.getString; -import android.util.Log; - import androidx.annotation.Nullable; import com.android.car.media.testmediaapp.TmaMediaEvent; @@ -57,7 +55,8 @@ class TmaMediaEventReader { ACTION, /** How long to wait before sending the event to the app. */ POST_DELAY_MS, - THROW_EXCEPTION + THROW_EXCEPTION, + TOGGLE_ITEM, } private static TmaMediaEventReader sInstance; @@ -92,6 +91,7 @@ class TmaMediaEventReader { getEnum(json, Keys.INTENT, mResolutionIntents, ResolutionIntent.NONE), getEnum(json, Keys.ACTION, mActions, Action.NONE), getInt(json, Keys.POST_DELAY_MS), - getString(json, Keys.THROW_EXCEPTION)); + getString(json, Keys.THROW_EXCEPTION), + getString(json, Keys.TOGGLE_ITEM)); } } |