1 /* 2 * Copyright 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.support.mediacompat.service; 18 19 import static android.support.mediacompat.testlib.MediaBrowserConstants.CUSTOM_ACTION; 20 import static android.support.mediacompat.testlib.MediaBrowserConstants.CUSTOM_ACTION_FOR_ERROR; 21 import static android.support.mediacompat.testlib.MediaBrowserConstants.EXTRAS_KEY; 22 import static android.support.mediacompat.testlib.MediaBrowserConstants.EXTRAS_VALUE; 23 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN; 24 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_CHILDREN_DELAYED; 25 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INCLUDE_METADATA; 26 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_INVALID; 27 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_ID_ROOT; 28 import static android.support.mediacompat.testlib.MediaBrowserConstants.MEDIA_METADATA; 29 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY; 30 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_ERROR; 31 import static android.support.mediacompat.testlib.MediaBrowserConstants.SEARCH_QUERY_FOR_NO_RESULT; 32 33 import static org.junit.Assert.assertNull; 34 35 import android.os.Bundle; 36 import android.support.annotation.NonNull; 37 import android.support.v4.media.MediaBrowserCompat.MediaItem; 38 import android.support.v4.media.MediaBrowserServiceCompat; 39 import android.support.v4.media.MediaDescriptionCompat; 40 import android.support.v4.media.MediaMetadataCompat; 41 import android.support.v4.media.session.MediaSessionCompat; 42 43 import java.util.ArrayList; 44 import java.util.Collections; 45 import java.util.List; 46 47 /** 48 * Stub implementation of {@link android.support.v4.media.MediaBrowserServiceCompat}. 49 */ 50 public class StubMediaBrowserServiceCompat extends MediaBrowserServiceCompat { 51 52 public static StubMediaBrowserServiceCompat sInstance; 53 54 public static MediaSessionCompat sSession; 55 private Bundle mExtras; 56 private Result<List<MediaItem>> mPendingLoadChildrenResult; 57 private Result<MediaItem> mPendingLoadItemResult; 58 private Bundle mPendingRootHints; 59 60 public Bundle mCustomActionExtras; 61 public Result<Bundle> mCustomActionResult; 62 63 @Override 64 public void onCreate() { 65 super.onCreate(); 66 sInstance = this; 67 sSession = new MediaSessionCompat(this, "StubMediaBrowserServiceCompat"); 68 setSessionToken(sSession.getSessionToken()); 69 } 70 71 @Override 72 public void onDestroy() { 73 super.onDestroy(); 74 sSession.release(); 75 sSession = null; 76 } 77 78 @Override 79 public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) { 80 mExtras = new Bundle(); 81 mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE); 82 return new BrowserRoot(MEDIA_ID_ROOT, mExtras); 83 } 84 85 @Override 86 public void onLoadChildren(final String parentId, final Result<List<MediaItem>> result) { 87 List<MediaItem> mediaItems = new ArrayList<>(); 88 if (MEDIA_ID_ROOT.equals(parentId)) { 89 Bundle rootHints = getBrowserRootHints(); 90 for (String id : MEDIA_ID_CHILDREN) { 91 mediaItems.add(createMediaItem(id)); 92 } 93 result.sendResult(mediaItems); 94 } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentId)) { 95 assertNull(mPendingLoadChildrenResult); 96 mPendingLoadChildrenResult = result; 97 mPendingRootHints = getBrowserRootHints(); 98 result.detach(); 99 } else if (MEDIA_ID_INVALID.equals(parentId)) { 100 result.sendResult(null); 101 } 102 } 103 104 @Override 105 public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaItem>> result, 106 @NonNull Bundle options) { 107 if (MEDIA_ID_INCLUDE_METADATA.equals(parentId)) { 108 // Test unparcelling the Bundle. 109 MediaMetadataCompat metadata = options.getParcelable(MEDIA_METADATA); 110 if (metadata == null) { 111 super.onLoadChildren(parentId, result, options); 112 } else { 113 List<MediaItem> mediaItems = new ArrayList<>(); 114 mediaItems.add(new MediaItem(metadata.getDescription(), MediaItem.FLAG_PLAYABLE)); 115 result.sendResult(mediaItems); 116 } 117 } else { 118 super.onLoadChildren(parentId, result, options); 119 } 120 } 121 122 @Override 123 public void onLoadItem(String itemId, Result<MediaItem> result) { 124 if (MEDIA_ID_CHILDREN_DELAYED.equals(itemId)) { 125 mPendingLoadItemResult = result; 126 mPendingRootHints = getBrowserRootHints(); 127 result.detach(); 128 return; 129 } 130 131 if (MEDIA_ID_INVALID.equals(itemId)) { 132 result.sendResult(null); 133 return; 134 } 135 136 for (String id : MEDIA_ID_CHILDREN) { 137 if (id.equals(itemId)) { 138 result.sendResult(createMediaItem(id)); 139 return; 140 } 141 } 142 143 // Test the case where onLoadItem is not implemented. 144 super.onLoadItem(itemId, result); 145 } 146 147 @Override 148 public void onSearch(String query, Bundle extras, Result<List<MediaItem>> result) { 149 if (SEARCH_QUERY_FOR_NO_RESULT.equals(query)) { 150 result.sendResult(Collections.<MediaItem>emptyList()); 151 } else if (SEARCH_QUERY_FOR_ERROR.equals(query)) { 152 result.sendResult(null); 153 } else if (SEARCH_QUERY.equals(query)) { 154 List<MediaItem> items = new ArrayList<>(); 155 for (String id : MEDIA_ID_CHILDREN) { 156 if (id.contains(query)) { 157 items.add(createMediaItem(id)); 158 } 159 } 160 result.sendResult(items); 161 } 162 } 163 164 @Override 165 public void onCustomAction(String action, Bundle extras, Result<Bundle> result) { 166 mCustomActionResult = result; 167 mCustomActionExtras = extras; 168 if (CUSTOM_ACTION_FOR_ERROR.equals(action)) { 169 result.sendError(null); 170 } else if (CUSTOM_ACTION.equals(action)) { 171 result.detach(); 172 } 173 } 174 175 public void sendDelayedNotifyChildrenChanged() { 176 if (mPendingLoadChildrenResult != null) { 177 mPendingLoadChildrenResult.sendResult(Collections.<MediaItem>emptyList()); 178 mPendingRootHints = null; 179 mPendingLoadChildrenResult = null; 180 } 181 } 182 183 public void sendDelayedItemLoaded() { 184 if (mPendingLoadItemResult != null) { 185 mPendingLoadItemResult.sendResult(new MediaItem(new MediaDescriptionCompat.Builder() 186 .setMediaId(MEDIA_ID_CHILDREN_DELAYED).setExtras(mPendingRootHints).build(), 187 MediaItem.FLAG_BROWSABLE)); 188 mPendingRootHints = null; 189 mPendingLoadItemResult = null; 190 } 191 } 192 193 private MediaItem createMediaItem(String id) { 194 return new MediaItem(new MediaDescriptionCompat.Builder().setMediaId(id).build(), 195 MediaItem.FLAG_BROWSABLE); 196 } 197 } 198