diff options
Diffstat (limited to 'androidx/media/MockMediaLibraryService2.java')
-rw-r--r-- | androidx/media/MockMediaLibraryService2.java | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/androidx/media/MockMediaLibraryService2.java b/androidx/media/MockMediaLibraryService2.java new file mode 100644 index 00000000..8f5d5bba --- /dev/null +++ b/androidx/media/MockMediaLibraryService2.java @@ -0,0 +1,237 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.media; + +import static org.junit.Assert.assertEquals; + +import android.content.ComponentName; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback; +import androidx.media.MediaSession2.ControllerInfo; +import androidx.media.MediaSession2.SessionCallback; +import androidx.media.TestUtils.SyncHandler; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import javax.annotation.concurrent.GuardedBy; + +/** + * Mock implementation of {@link MediaLibraryService2} for testing. + */ +public class MockMediaLibraryService2 extends MediaLibraryService2 { + // Keep in sync with the AndroidManifest.xml + public static final String ID = "TestLibrary"; + + public static final String ROOT_ID = "rootId"; + public static final Bundle EXTRAS = new Bundle(); + + public static final String MEDIA_ID_GET_ITEM = "media_id_get_item"; + + public static final String PARENT_ID = "parent_id"; + public static final String PARENT_ID_NO_CHILDREN = "parent_id_no_children"; + public static final String PARENT_ID_ERROR = "parent_id_error"; + + public static final List<MediaItem2> GET_CHILDREN_RESULT = new ArrayList<>(); + public static final int CHILDREN_COUNT = 100; + + public static final String SEARCH_QUERY = "search_query"; + public static final String SEARCH_QUERY_TAKES_TIME = "search_query_takes_time"; + public static final int SEARCH_TIME_IN_MS = 5000; + public static final String SEARCH_QUERY_EMPTY_RESULT = "search_query_empty_result"; + + public static final List<MediaItem2> SEARCH_RESULT = new ArrayList<>(); + public static final int SEARCH_RESULT_COUNT = 50; + + // TODO(jaewan): Uncomment here after DataSourceDesc.builder is ready. +// private static final DataSourceDesc DATA_SOURCE_DESC = +// new DataSourceDesc.Builder().setDataSource(new FileDescriptor()).build(); + private static final DataSourceDesc DATA_SOURCE_DESC = null; + + private static final String TAG = "MockMediaLibrarySvc2"; + + static { + EXTRAS.putString(ROOT_ID, ROOT_ID); + } + @GuardedBy("MockMediaLibraryService2.class") + private static SessionToken2 sToken; + + private MediaLibrarySession mSession; + + public MockMediaLibraryService2() { + super(); + GET_CHILDREN_RESULT.clear(); + String getChildrenMediaIdPrefix = "get_children_media_id_"; + for (int i = 0; i < CHILDREN_COUNT; i++) { + GET_CHILDREN_RESULT.add(createMediaItem(getChildrenMediaIdPrefix + i)); + } + + SEARCH_RESULT.clear(); + String getSearchResultMediaIdPrefix = "get_search_result_media_id_"; + for (int i = 0; i < SEARCH_RESULT_COUNT; i++) { + SEARCH_RESULT.add(createMediaItem(getSearchResultMediaIdPrefix + i)); + } + } + + @Override + public void onCreate() { + TestServiceRegistry.getInstance().setServiceInstance(this); + super.onCreate(); + } + + @Override + public MediaLibrarySession onCreateSession(String sessionId) { + final MockPlayer player = new MockPlayer(1); + final SyncHandler handler = (SyncHandler) TestServiceRegistry.getInstance().getHandler(); + final Executor executor = new Executor() { + @Override + public void execute(Runnable runnable) { + handler.post(runnable); + } + }; + SessionCallback callback = TestServiceRegistry.getInstance().getSessionCallback(); + MediaLibrarySessionCallback librarySessionCallback; + if (callback instanceof MediaLibrarySessionCallback) { + librarySessionCallback = (MediaLibrarySessionCallback) callback; + } else { + // Callback hasn't set. Use default callback + librarySessionCallback = new TestLibrarySessionCallback(); + } + mSession = new MediaLibrarySession.Builder(MockMediaLibraryService2.this, executor, + librarySessionCallback).setPlayer(player).setId(sessionId).build(); + return mSession; + } + + @Override + public void onDestroy() { + super.onDestroy(); + TestServiceRegistry.getInstance().cleanUp(); + } + + public static SessionToken2 getToken(Context context) { + synchronized (MockMediaLibraryService2.class) { + if (sToken == null) { + sToken = new SessionToken2(context, new ComponentName( + context.getPackageName(), MockMediaLibraryService2.class.getName())); + assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, sToken.getType()); + } + return sToken; + } + } + + private class TestLibrarySessionCallback extends MediaLibrarySessionCallback { + @Override + public LibraryRoot onGetLibraryRoot(MediaLibrarySession session, ControllerInfo controller, + Bundle rootHints) { + return new LibraryRoot(ROOT_ID, EXTRAS); + } + + @Override + public MediaItem2 onGetItem(MediaLibrarySession session, ControllerInfo controller, + String mediaId) { + if (MEDIA_ID_GET_ITEM.equals(mediaId)) { + return createMediaItem(mediaId); + } else { + return null; + } + } + + @Override + public List<MediaItem2> onGetChildren(MediaLibrarySession session, + ControllerInfo controller, String parentId, int page, int pageSize, Bundle extras) { + if (PARENT_ID.equals(parentId)) { + return getPaginatedResult(GET_CHILDREN_RESULT, page, pageSize); + } else if (PARENT_ID_ERROR.equals(parentId)) { + return null; + } + // Includes the case of PARENT_ID_NO_CHILDREN. + return new ArrayList<>(); + } + + @Override + public void onSearch(MediaLibrarySession session, final ControllerInfo controllerInfo, + final String query, final Bundle extras) { + if (SEARCH_QUERY.equals(query)) { + mSession.notifySearchResultChanged(controllerInfo, query, SEARCH_RESULT_COUNT, + extras); + } else if (SEARCH_QUERY_TAKES_TIME.equals(query)) { + // Searching takes some time. Notify after 5 seconds. + Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() { + @Override + public void run() { + mSession.notifySearchResultChanged( + controllerInfo, query, SEARCH_RESULT_COUNT, extras); + } + }, SEARCH_TIME_IN_MS, TimeUnit.MILLISECONDS); + } else if (SEARCH_QUERY_EMPTY_RESULT.equals(query)) { + mSession.notifySearchResultChanged(controllerInfo, query, 0, extras); + } else { + // TODO: For the error case, how should we notify the browser? + } + } + + @Override + public List<MediaItem2> onGetSearchResult(MediaLibrarySession session, + ControllerInfo controllerInfo, String query, int page, int pageSize, + Bundle extras) { + if (SEARCH_QUERY.equals(query)) { + return getPaginatedResult(SEARCH_RESULT, page, pageSize); + } else { + return null; + } + } + } + + private List<MediaItem2> getPaginatedResult(List<MediaItem2> items, int page, int pageSize) { + if (items == null) { + return null; + } else if (items.size() == 0) { + return new ArrayList<>(); + } + + final int totalItemCount = items.size(); + int fromIndex = (page - 1) * pageSize; + int toIndex = Math.min(page * pageSize, totalItemCount); + + List<MediaItem2> paginatedResult = new ArrayList<>(); + try { + // The case of (fromIndex >= totalItemCount) will throw exception below. + paginatedResult = items.subList(fromIndex, toIndex); + } catch (IndexOutOfBoundsException | IllegalArgumentException ex) { + Log.d(TAG, "Result is empty for given pagination arguments: totalItemCount=" + + totalItemCount + ", page=" + page + ", pageSize=" + pageSize, ex); + } + return paginatedResult; + } + + private MediaItem2 createMediaItem(String mediaId) { + Context context = MockMediaLibraryService2.this; + return new MediaItem2.Builder(0 /* Flags */) + .setMediaId(mediaId) + .setDataSourceDesc(DATA_SOURCE_DESC) + .setMetadata(new MediaMetadata2.Builder() + .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId) + .build()) + .build(); + } +} |