1daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang/*
2daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * Copyright 2018 The Android Open Source Project
3daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang *
4daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * Licensed under the Apache License, Version 2.0 (the "License");
5daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * you may not use this file except in compliance with the License.
6daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * You may obtain a copy of the License at
7daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang *
8daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang *      http://www.apache.org/licenses/LICENSE-2.0
9daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang *
10daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * Unless required by applicable law or agreed to in writing, software
11daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * distributed under the License is distributed on an "AS IS" BASIS,
12daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * See the License for the specific language governing permissions and
14daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * limitations under the License.
15daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang */
16daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
17daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangpackage androidx.media;
18daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
19daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static androidx.media.MockMediaLibraryService2.EXTRAS;
20daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static androidx.media.MockMediaLibraryService2.ROOT_ID;
21daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
22daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static junit.framework.Assert.assertEquals;
23daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static junit.framework.Assert.assertFalse;
24daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static junit.framework.Assert.assertNotNull;
25daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static junit.framework.Assert.assertNull;
26daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static junit.framework.Assert.assertTrue;
27daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static junit.framework.Assert.fail;
28daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
29daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport static org.junit.Assert.assertNotEquals;
30daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
31daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport android.content.Context;
32c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kimimport android.os.Build;
33daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport android.os.Bundle;
34daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport android.os.Process;
35daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport android.os.ResultReceiver;
3603c696e779afb0f54668a8f76b0944ab3f1c9a29Hyundo Moonimport android.support.test.filters.LargeTest;
37c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kimimport android.support.test.filters.SdkSuppress;
38daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport android.support.test.filters.SmallTest;
39daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport android.support.test.runner.AndroidJUnit4;
40daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
41daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.annotation.CallSuper;
42daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.annotation.GuardedBy;
43daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.annotation.NonNull;
44daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.annotation.Nullable;
45daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.media.MediaBrowser2.BrowserCallback;
46daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.media.MediaController2.ControllerCallback;
47daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.media.MediaLibraryService2.MediaLibrarySession;
48daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
49daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.media.MediaSession2.CommandButton;
50daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport androidx.media.MediaSession2.ControllerInfo;
51daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
52daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport junit.framework.Assert;
53daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
54daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport org.junit.Ignore;
55daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport org.junit.Test;
56daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport org.junit.runner.RunWith;
57daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
58daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport java.lang.reflect.Method;
59daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport java.util.List;
60daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport java.util.concurrent.CountDownLatch;
61daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport java.util.concurrent.TimeUnit;
62daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangimport java.util.concurrent.atomic.AtomicReference;
63daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
64daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang/**
65daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * Tests {@link MediaBrowser2}.
66daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * <p>
67daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * This test inherits {@link MediaController2Test} to ensure that inherited APIs from
68daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang * {@link MediaController2} works cleanly.
69daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang */
70daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang// TODO(jaewan): Implement host-side test so browser and service can run in different processes.
710607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
72daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang@RunWith(AndroidJUnit4.class)
73daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang@SmallTest
74daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kangpublic class MediaBrowser2Test extends MediaController2Test {
75daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    private static final String TAG = "MediaBrowser2Test";
76daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
77daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Override
78daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    TestControllerInterface onCreateController(final @NonNull SessionToken2 token,
79c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim            final @Nullable ControllerCallback callback) throws InterruptedException {
80daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final AtomicReference<TestControllerInterface> controller = new AtomicReference<>();
81daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        sHandler.postAndSync(new Runnable() {
82daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
83daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void run() {
84daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                // Create controller on the test handler, for changing MediaBrowserCompat's Handler
85daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                // Looper. Otherwise, MediaBrowserCompat will post all the commands to the handler
86daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                // and commands wouldn't be run if tests codes waits on the test handler.
87daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                controller.set(new TestMediaBrowser(
88c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim                        mContext, token, new TestBrowserCallback(callback)));
89daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
90daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        });
91daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        return controller.get();
92daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
93daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
94daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    /**
95daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang     * Test if the {@link TestBrowserCallback} wraps the callback proxy without missing any method.
96daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang     */
97daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
98daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testTestBrowserCallback() {
99daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
100daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        Method[] methods = TestBrowserCallback.class.getMethods();
101daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertNotNull(methods);
102daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        for (int i = 0; i < methods.length; i++) {
103daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            // For any methods in the controller callback, TestControllerCallback should have
104daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            // overriden the method and call matching API in the callback proxy.
105daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            assertNotEquals("TestBrowserCallback should override " + methods[i]
106daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                            + " and call callback proxy",
107daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    BrowserCallback.class, methods[i].getDeclaringClass());
108daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
109daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
110daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
111daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
112daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testGetLibraryRoot() throws InterruptedException {
113daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
114daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final Bundle param = new Bundle();
115daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        param.putString(TAG, TAG);
116daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
117daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
118daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
119daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
120daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetLibraryRootDone(MediaBrowser2 browser,
121daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    Bundle rootHints, String rootMediaId, Bundle rootExtra) {
122daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(TestUtils.equals(param, rootHints));
123daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(ROOT_ID, rootMediaId);
124c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim                // Note that TestUtils#equals() cannot be used for this because
125c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim                // MediaBrowserServiceCompat adds extra_client_version to the rootHints.
126c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim                assertTrue(TestUtils.contains(rootExtra, EXTRAS));
127daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
128daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
129daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
130daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
131daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
132daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser =
133daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                (MediaBrowser2) createController(token, true, callback);
134daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getLibraryRoot(param);
135daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
136daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
137daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
138daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
139daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testGetItem() throws InterruptedException {
140daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
141daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String mediaId = MockMediaLibraryService2.MEDIA_ID_GET_ITEM;
142daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
143daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
144daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
145daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
146daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetItemDone(MediaBrowser2 browser, String mediaIdOut, MediaItem2 result) {
147daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(mediaId, mediaIdOut);
148daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertNotNull(result);
149daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(mediaId, result.getMediaId());
150daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
151daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
152daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
153daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
154daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
155daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
156daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getItem(mediaId);
157daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
158daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
159daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
160daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
161daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testGetItemNullResult() throws InterruptedException {
162daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
163daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String mediaId = "random_media_id";
164daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
165daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
166daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
167daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
168daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetItemDone(MediaBrowser2 browser, String mediaIdOut, MediaItem2 result) {
169daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(mediaId, mediaIdOut);
170daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertNull(result);
171daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
172daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
173daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
174daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
175daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
176daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
177daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getItem(mediaId);
178daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
179daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
180daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
181daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
182daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testGetChildren() throws InterruptedException {
183daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
184daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String parentId = MockMediaLibraryService2.PARENT_ID;
185daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final int page = 4;
186daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final int pageSize = 10;
187daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final Bundle extras = new Bundle();
188daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        extras.putString(TAG, TAG);
189daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
190daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
191daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
192daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
193daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut, int pageOut,
194daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
195daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(parentId, parentIdOut);
196daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(page, pageOut);
197daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(pageSize, pageSizeOut);
198daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(TestUtils.equals(extras, extrasOut));
199daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertNotNull(result);
200daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
201daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int fromIndex = (page - 1) * pageSize;
202daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int toIndex = Math.min(page * pageSize, MockMediaLibraryService2.CHILDREN_COUNT);
203daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
204daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                // Compare the given results with originals.
205daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                for (int originalIndex = fromIndex; originalIndex < toIndex; originalIndex++) {
206daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    int relativeIndex = originalIndex - fromIndex;
207daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    Assert.assertEquals(
208daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                            MockMediaLibraryService2.GET_CHILDREN_RESULT.get(originalIndex)
209daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                                    .getMediaId(),
210daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                            result.get(relativeIndex).getMediaId());
211daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                }
212daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
213daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
214daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
215daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
216daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
217daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
218daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getChildren(parentId, page, pageSize, extras);
219daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
220daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
221daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
222daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
223daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testGetChildrenEmptyResult() throws InterruptedException {
224daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
225daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String parentId = MockMediaLibraryService2.PARENT_ID_NO_CHILDREN;
226daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
227daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
228daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
229daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
230daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut,
231daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
232daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertNotNull(result);
233daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(0, result.size());
234daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
235daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
236daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
237daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
238daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
239daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
240daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getChildren(parentId, 1, 1, null);
241daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
242daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
243daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
244daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
245daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testGetChildrenNullResult() throws InterruptedException {
246daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
247daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String parentId = MockMediaLibraryService2.PARENT_ID_ERROR;
248daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
249daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
250daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
251daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
252daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut,
253daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
254daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertNull(result);
255daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
256daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
257daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
258daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
259daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
260daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
261daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getChildren(parentId, 1, 1, null);
262daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
263daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
264daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
265daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
266daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testSearch() throws InterruptedException {
267daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
268daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String query = MockMediaLibraryService2.SEARCH_QUERY;
269daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final int page = 4;
270daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final int pageSize = 10;
271daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final Bundle extras = new Bundle();
272daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        extras.putString(TAG, TAG);
273daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
274daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latchForSearch = new CountDownLatch(1);
275daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latchForGetSearchResult = new CountDownLatch(1);
276daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
277daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
278daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onSearchResultChanged(MediaBrowser2 browser,
279daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    String queryOut, int itemCount, Bundle extrasOut) {
280daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(query, queryOut);
281daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(TestUtils.equals(extras, extrasOut));
282daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(MockMediaLibraryService2.SEARCH_RESULT_COUNT, itemCount);
283daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latchForSearch.countDown();
284daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
285daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
286daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
287daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onGetSearchResultDone(MediaBrowser2 browser, String queryOut,
288daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
289daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(query, queryOut);
290daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(page, pageOut);
291daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(pageSize, pageSizeOut);
292daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(TestUtils.equals(extras, extrasOut));
293daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertNotNull(result);
294daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
295daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int fromIndex = (page - 1) * pageSize;
296daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int toIndex = Math.min(
297daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                        page * pageSize, MockMediaLibraryService2.SEARCH_RESULT_COUNT);
298daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
299daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                // Compare the given results with originals.
300daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                for (int originalIndex = fromIndex; originalIndex < toIndex; originalIndex++) {
301daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    int relativeIndex = originalIndex - fromIndex;
302daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    Assert.assertEquals(
303daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                            MockMediaLibraryService2.SEARCH_RESULT.get(originalIndex).getMediaId(),
304daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                            result.get(relativeIndex).getMediaId());
305daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                }
306daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latchForGetSearchResult.countDown();
307daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
308daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
309daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
310daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        // Request the search.
311daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
312daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
313daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.search(query, extras);
314daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latchForSearch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
315daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
316daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        // Get the search result.
317daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.getSearchResult(query, page, pageSize, extras);
318daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latchForGetSearchResult.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
319daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
320daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
321daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
32203c696e779afb0f54668a8f76b0944ab3f1c9a29Hyundo Moon    @LargeTest
323daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testSearchTakesTime() throws InterruptedException {
324daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
325daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String query = MockMediaLibraryService2.SEARCH_QUERY_TAKES_TIME;
326daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final Bundle extras = new Bundle();
327daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        extras.putString(TAG, TAG);
328daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
329daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
330daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
331daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
332daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onSearchResultChanged(
333daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    MediaBrowser2 browser, String queryOut, int itemCount, Bundle extrasOut) {
334daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(query, queryOut);
335daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(TestUtils.equals(extras, extrasOut));
336daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(MockMediaLibraryService2.SEARCH_RESULT_COUNT, itemCount);
337daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
338daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
339daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
340daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
341daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
342daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
343daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.search(query, extras);
344daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(
345daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                MockMediaLibraryService2.SEARCH_TIME_IN_MS + WAIT_TIME_MS, TimeUnit.MILLISECONDS));
346daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
347daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
348daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
349daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testSearchEmptyResult() throws InterruptedException {
350daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
351daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String query = MockMediaLibraryService2.SEARCH_QUERY_EMPTY_RESULT;
352daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final Bundle extras = new Bundle();
353daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        extras.putString(TAG, TAG);
354daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
355daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
356daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final BrowserCallback callback = new BrowserCallback() {
357daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
358daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onSearchResultChanged(
359daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    MediaBrowser2 browser, String queryOut, int itemCount, Bundle extrasOut) {
360daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(query, queryOut);
361daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(TestUtils.equals(extras, extrasOut));
362daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertEquals(0, itemCount);
363daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                latch.countDown();
364daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
365daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
366daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
367daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
368daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
369daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.search(query, extras);
370daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
371daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
372daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
373daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
374daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testSubscribe() throws InterruptedException {
375daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
376daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String testParentId = "testSubscribeId";
377daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final Bundle testExtras = new Bundle();
378daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        testExtras.putString(testParentId, testParentId);
379daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
380daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
381daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final MediaLibrarySessionCallback callback = new MediaLibrarySessionCallback() {
382daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
383daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onSubscribe(@NonNull MediaLibraryService2.MediaLibrarySession session,
384daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    @NonNull MediaSession2.ControllerInfo info, @NonNull String parentId,
385daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    @Nullable Bundle extras) {
386daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                if (Process.myUid() == info.getUid()) {
387daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    assertEquals(testParentId, parentId);
388daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    assertTrue(TestUtils.equals(testExtras, extras));
389daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    latch.countDown();
390daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                }
391daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
392daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
393daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        TestServiceRegistry.getInstance().setSessionCallback(callback);
394daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
395daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token);
396daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.subscribe(testParentId, testExtras);
397daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
398daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
399daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
400daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Ignore
401daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
402daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public void testUnsubscribe() throws InterruptedException {
403daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
404daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final String testParentId = "testUnsubscribeId";
405daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final CountDownLatch latch = new CountDownLatch(1);
406daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final MediaLibrarySessionCallback callback = new MediaLibrarySessionCallback() {
407daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            @Override
408daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            public void onUnsubscribe(@NonNull MediaLibrarySession session,
409daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    @NonNull ControllerInfo info, @NonNull String parentId) {
410daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                if (Process.myUid() == info.getUid()) {
411daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    assertEquals(testParentId, parentId);
412daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    latch.countDown();
413daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                }
414daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
415daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
416daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        TestServiceRegistry.getInstance().setSessionCallback(callback);
417daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
418daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        MediaBrowser2 browser = (MediaBrowser2) createController(token);
419daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        browser.unsubscribe(testParentId);
420daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
421daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
422daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
423daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    @Test
42446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon    public void testBrowserCallback_onChildrenChangedIsNotCalledWhenNotSubscribed()
42546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            throws InterruptedException {
426e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        // This test uses MediaLibrarySession.notifyChildrenChanged().
427daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        prepareLooper();
42846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final String subscribedMediaId = "subscribedMediaId";
42946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final String anotherMediaId = "anotherMediaId";
430daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final int testChildrenCount = 101;
43146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final CountDownLatch latch = new CountDownLatch(1);
43246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
43346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
43446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            @Override
43546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            public void onSubscribe(@NonNull MediaLibrarySession session,
43646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    @NonNull ControllerInfo controller, @NonNull String parentId,
43746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    @Nullable Bundle extras) {
43846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                if (Process.myUid() == controller.getUid()) {
43946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    // Shouldn't trigger onChildrenChanged() for the browser,
44046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    // because the browser didn't subscribe this media id.
44146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    session.notifyChildrenChanged(anotherMediaId, testChildrenCount, null);
44246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                }
44346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            }
44446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
44546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            @Override
44646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
44746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    ControllerInfo controller, String parentId, int page, int pageSize,
44846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    Bundle extras) {
44946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                return TestUtils.createPlaylist(testChildrenCount);
45046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            }
451daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        };
45246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
45346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            @Override
45446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
45546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    int itemCount, Bundle extras) {
45646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                // Unexpected call.
45746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                fail();
45846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            }
45946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        };
46046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
461daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
462daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
463daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        final MediaBrowser2 browser = (MediaBrowser2) createController(
464daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                token, true, controllerCallbackProxy);
46546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        browser.subscribe(subscribedMediaId, null);
46646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
46746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        // onChildrenChanged() should not be called.
468daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
46946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon    }
47046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
47146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon    @Test
47246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon    public void testBrowserCallback_onChildrenChangedIsCalledWhenSubscribed()
47346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            throws InterruptedException {
474e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        // This test uses MediaLibrarySession.notifyChildrenChanged().
47546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        prepareLooper();
47646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final String expectedParentId = "expectedParentId";
47746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final int testChildrenCount = 101;
47846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final Bundle testExtras = TestUtils.createTestBundle();
47946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
48046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final CountDownLatch latch = new CountDownLatch(1);
48146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
48246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            @Override
48346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            public void onSubscribe(@NonNull MediaLibrarySession session,
48446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    @NonNull ControllerInfo controller, @NonNull String parentId,
48546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    @Nullable Bundle extras) {
48646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                if (Process.myUid() == controller.getUid()) {
48746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    // Should trigger onChildrenChanged() for the browser.
48846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    session.notifyChildrenChanged(expectedParentId, testChildrenCount, testExtras);
48946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                }
49046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            }
49146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
49246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            @Override
49346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
49446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    ControllerInfo controller, String parentId, int page, int pageSize,
49546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    Bundle extras) {
496e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                return TestUtils.createPlaylist(testChildrenCount);
497e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            }
498e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        };
499e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
500e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            @Override
501e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
502e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    int itemCount, Bundle extras) {
503e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                assertEquals(expectedParentId, parentId);
504e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                assertEquals(testChildrenCount, itemCount);
505e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                assertTrue(TestUtils.equals(testExtras, extras));
506e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                latch.countDown();
507e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            }
508e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        };
509e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
510e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
511e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
512e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final MediaBrowser2 browser = (MediaBrowser2) createController(
513e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                token, true, controllerCallbackProxy);
514e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        browser.subscribe(expectedParentId, null);
515e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
516e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        // onChildrenChanged() should be called.
517e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
518e643575a509d0062168f789de14d10ef84280c1dHyundo Moon    }
519e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
520e643575a509d0062168f789de14d10ef84280c1dHyundo Moon    @Test
521e643575a509d0062168f789de14d10ef84280c1dHyundo Moon    public void testBrowserCallback_onChildrenChangedIsNotCalledWhenNotSubscribed2()
522e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            throws InterruptedException {
523e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        // This test uses MediaLibrarySession.notifyChildrenChanged(ControllerInfo).
524e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        prepareLooper();
525e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final String subscribedMediaId = "subscribedMediaId";
526e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final String anotherMediaId = "anotherMediaId";
527e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final int testChildrenCount = 101;
528e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final CountDownLatch latch = new CountDownLatch(1);
529e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
530e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
531e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            @Override
532e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            public void onSubscribe(@NonNull MediaLibrarySession session,
533e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    @NonNull ControllerInfo controller, @NonNull String parentId,
534e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    @Nullable Bundle extras) {
535e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                if (Process.myUid() == controller.getUid()) {
536e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    // Shouldn't trigger onChildrenChanged() for the browser,
537e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    // because the browser didn't subscribe this media id.
538e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    session.notifyChildrenChanged(
539e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                            controller, anotherMediaId, testChildrenCount, null);
540e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                }
541e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            }
542e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
543e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            @Override
544e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
545e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    ControllerInfo controller, String parentId, int page, int pageSize,
546e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    Bundle extras) {
547e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                return TestUtils.createPlaylist(testChildrenCount);
548e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            }
549e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        };
550e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
551e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            @Override
552e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
553e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    int itemCount, Bundle extras) {
554e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                // Unexpected call.
555e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                fail();
556e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            }
557e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        };
558e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
559e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
560e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
561e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final MediaBrowser2 browser = (MediaBrowser2) createController(
562e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                token, true, controllerCallbackProxy);
563e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        browser.subscribe(subscribedMediaId, null);
564e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
565e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        // onChildrenChanged() should not be called.
566e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
567e643575a509d0062168f789de14d10ef84280c1dHyundo Moon    }
568e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
569e643575a509d0062168f789de14d10ef84280c1dHyundo Moon    @Test
570e643575a509d0062168f789de14d10ef84280c1dHyundo Moon    public void testBrowserCallback_onChildrenChangedIsCalledWhenSubscribed2()
571e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            throws InterruptedException {
572e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        // This test uses MediaLibrarySession.notifyChildrenChanged(ControllerInfo).
573e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        prepareLooper();
574e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final String expectedParentId = "expectedParentId";
575e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final int testChildrenCount = 101;
576e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final Bundle testExtras = TestUtils.createTestBundle();
577e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
578e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final CountDownLatch latch = new CountDownLatch(1);
579e643575a509d0062168f789de14d10ef84280c1dHyundo Moon        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
580e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            @Override
581e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            public void onSubscribe(@NonNull MediaLibrarySession session,
582e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    @NonNull ControllerInfo controller, @NonNull String parentId,
583e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    @Nullable Bundle extras) {
584e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                if (Process.myUid() == controller.getUid()) {
585e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    // Should trigger onChildrenChanged() for the browser.
586e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    session.notifyChildrenChanged(
587e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                            controller, expectedParentId, testChildrenCount, testExtras);
588e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                }
589e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            }
590e643575a509d0062168f789de14d10ef84280c1dHyundo Moon
591e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            @Override
592e643575a509d0062168f789de14d10ef84280c1dHyundo Moon            public List<MediaItem2> onGetChildren(MediaLibrarySession session,
593e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    ControllerInfo controller, String parentId, int page, int pageSize,
594e643575a509d0062168f789de14d10ef84280c1dHyundo Moon                    Bundle extras) {
59546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                return TestUtils.createPlaylist(testChildrenCount);
59646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            }
59746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        };
59846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final BrowserCallback controllerCallbackProxy = new BrowserCallback() {
59946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            @Override
60046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            public void onChildrenChanged(MediaBrowser2 browser, String parentId,
60146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                    int itemCount, Bundle extras) {
60246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                assertEquals(expectedParentId, parentId);
60346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                assertEquals(testChildrenCount, itemCount);
60446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                assertTrue(TestUtils.equals(testExtras, extras));
60546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                latch.countDown();
60646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon            }
60746a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        };
60846a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
60946a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
61046a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
61146a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        final MediaBrowser2 browser = (MediaBrowser2) createController(
61246a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon                token, true, controllerCallbackProxy);
61346a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        browser.subscribe(expectedParentId, null);
61446a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon
61546a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        // onChildrenChanged() should be called.
61646a5d0ff57a61f4e91b568f20b2df8e035de765eHyundo Moon        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
617daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
618daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
619daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public static class TestBrowserCallback extends BrowserCallback
620daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            implements TestControllerCallbackInterface {
621daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        private final ControllerCallback mCallbackProxy;
622daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public final CountDownLatch connectLatch = new CountDownLatch(1);
623daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public final CountDownLatch disconnectLatch = new CountDownLatch(1);
624daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @GuardedBy("this")
625daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        private Runnable mOnCustomCommandRunnable;
626daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
627daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        TestBrowserCallback(ControllerCallback callbackProxy) {
628daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (callbackProxy == null) {
629c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim                callbackProxy = new BrowserCallback() {};
630daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
631daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy = callbackProxy;
632daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
633daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
634daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @CallSuper
635daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
636daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onConnected(MediaController2 controller, SessionCommandGroup2 commands) {
637daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            connectLatch.countDown();
638daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
639daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
640daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @CallSuper
641daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
642daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onDisconnected(MediaController2 controller) {
643daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            disconnectLatch.countDown();
644daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
645daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
646daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
647daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void waitForConnect(boolean expect) throws InterruptedException {
648daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (expect) {
649daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(connectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
650daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            } else {
651daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertFalse(connectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
652daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
653daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
654daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
655daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
656daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void waitForDisconnect(boolean expect) throws InterruptedException {
657daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (expect) {
658daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertTrue(disconnectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
659daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            } else {
660daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                assertFalse(disconnectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
661daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
662daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
663daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
664daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
665daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onPlaybackInfoChanged(MediaController2 controller,
666daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                MediaController2.PlaybackInfo info) {
667daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onPlaybackInfoChanged(controller, info);
668daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
669daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
670daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
671daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
672daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                Bundle args, ResultReceiver receiver) {
673daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onCustomCommand(controller, command, args, receiver);
674daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            synchronized (this) {
675daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                if (mOnCustomCommandRunnable != null) {
676daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                    mOnCustomCommandRunnable.run();
677daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                }
678daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
679daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
680daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
681daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
682daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onCustomLayoutChanged(MediaController2 controller, List<CommandButton> layout) {
683daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onCustomLayoutChanged(controller, layout);
684daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
685daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
686daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
687daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onAllowedCommandsChanged(MediaController2 controller,
688daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                SessionCommandGroup2 commands) {
689daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onAllowedCommandsChanged(controller, commands);
690daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
691daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
692daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
693daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onPlayerStateChanged(MediaController2 controller, int state) {
694daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onPlayerStateChanged(controller, state);
695daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
696daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
697daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
698daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onSeekCompleted(MediaController2 controller, long position) {
699daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onSeekCompleted(controller, position);
700daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
701daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
702daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
703daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onPlaybackSpeedChanged(MediaController2 controller, float speed) {
704daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onPlaybackSpeedChanged(controller, speed);
705daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
706daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
707daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
708daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
709daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int state) {
710daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onBufferingStateChanged(controller, item, state);
711daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
712daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
713daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
714daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onError(MediaController2 controller, int errorCode, Bundle extras) {
715daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onError(controller, errorCode, extras);
716daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
717daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
718daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
719daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onCurrentMediaItemChanged(MediaController2 controller, MediaItem2 item) {
720daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onCurrentMediaItemChanged(controller, item);
721daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
722daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
723daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
724daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onPlaylistChanged(MediaController2 controller,
725daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                List<MediaItem2> list, MediaMetadata2 metadata) {
726daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onPlaylistChanged(controller, list, metadata);
727daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
728daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
729daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
730daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onPlaylistMetadataChanged(MediaController2 controller,
731daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                MediaMetadata2 metadata) {
732daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onPlaylistMetadataChanged(controller, metadata);
733daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
734daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
735daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
736daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
737daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onShuffleModeChanged(controller, shuffleMode);
738daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
739daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
740daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
741daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
742daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            mCallbackProxy.onRepeatModeChanged(controller, repeatMode);
743daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
744daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
745daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
746daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onGetLibraryRootDone(MediaBrowser2 browser, Bundle rootHints,
747daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                String rootMediaId, Bundle rootExtra) {
748daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            super.onGetLibraryRootDone(browser, rootHints, rootMediaId, rootExtra);
749daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (mCallbackProxy instanceof BrowserCallback) {
750daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                ((BrowserCallback) mCallbackProxy)
751daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                        .onGetLibraryRootDone(browser, rootHints, rootMediaId, rootExtra);
752daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
753daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
754daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
755daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
756daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onGetItemDone(MediaBrowser2 browser, String mediaId, MediaItem2 result) {
757daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            super.onGetItemDone(browser, mediaId, result);
758daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (mCallbackProxy instanceof BrowserCallback) {
759daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                ((BrowserCallback) mCallbackProxy).onGetItemDone(browser, mediaId, result);
760daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
761daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
762daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
763daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
764daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onGetChildrenDone(MediaBrowser2 browser, String parentId, int page,
765daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int pageSize, List<MediaItem2> result, Bundle extras) {
766daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            super.onGetChildrenDone(browser, parentId, page, pageSize, result, extras);
767daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (mCallbackProxy instanceof BrowserCallback) {
768daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                ((BrowserCallback) mCallbackProxy)
769daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                        .onGetChildrenDone(browser, parentId, page, pageSize, result, extras);
770daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
771daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
772daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
773daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
774daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onSearchResultChanged(MediaBrowser2 browser, String query, int itemCount,
775daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                Bundle extras) {
776daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            super.onSearchResultChanged(browser, query, itemCount, extras);
777daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (mCallbackProxy instanceof BrowserCallback) {
778daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                ((BrowserCallback) mCallbackProxy)
779daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                        .onSearchResultChanged(browser, query, itemCount, extras);
780daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
781daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
782daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
783daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
784daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onGetSearchResultDone(MediaBrowser2 browser, String query, int page,
785daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                int pageSize, List<MediaItem2> result, Bundle extras) {
786daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            super.onGetSearchResultDone(browser, query, page, pageSize, result, extras);
787daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (mCallbackProxy instanceof BrowserCallback) {
788daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                ((BrowserCallback) mCallbackProxy)
789daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                        .onGetSearchResultDone(browser, query, page, pageSize, result, extras);
790daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
791daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
792daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
793daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
794daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void onChildrenChanged(MediaBrowser2 browser, String parentId, int itemCount,
795daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                Bundle extras) {
796daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            super.onChildrenChanged(browser, parentId, itemCount, extras);
797daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            if (mCallbackProxy instanceof BrowserCallback) {
798daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                ((BrowserCallback) mCallbackProxy)
799daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                        .onChildrenChanged(browser, parentId, itemCount, extras);
800daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
801daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
802daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
803daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
804daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public void setRunnableForOnCustomCommand(Runnable runnable) {
805daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            synchronized (this) {
806daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang                mOnCustomCommandRunnable = runnable;
807daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            }
808daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
809daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
810daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
811daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    public class TestMediaBrowser extends MediaBrowser2 implements TestControllerInterface {
812daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        private final BrowserCallback mCallback;
813daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
814daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public TestMediaBrowser(@NonNull Context context, @NonNull SessionToken2 token,
815c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim                @NonNull BrowserCallback callback) {
816c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim            super(context, token, sHandlerExecutor, callback);
817c000096702ed479f7aa922176851fe98cfa6a154Jaewan Kim            mCallback = callback;
818daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
819daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang
820daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        @Override
821daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        public BrowserCallback getCallback() {
822daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang            return mCallback;
823daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang        }
824daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang    }
825daf546359fe5d718ee3e736bf09feeba69ed9db5Insun Kang}
826