MediaController2Test.java revision e18fafc56c49f683278d91e16a7246c7b1e01bad
1fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang/*
2fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Copyright 2018 The Android Open Source Project
3fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *
4fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Licensed under the Apache License, Version 2.0 (the "License");
5fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * you may not use this file except in compliance with the License.
6fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * You may obtain a copy of the License at
7fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *
8fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *      http://www.apache.org/licenses/LICENSE-2.0
9fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *
10fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Unless required by applicable law or agreed to in writing, software
11fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * distributed under the License is distributed on an "AS IS" BASIS,
12fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * See the License for the specific language governing permissions and
14fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * limitations under the License.
15fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang */
16fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
17fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangpackage androidx.media;
18fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
19e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moonimport static org.junit.Assert.assertEquals;
20fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertFalse;
21fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertNotEquals;
22fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertNotNull;
23fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertNull;
24fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertTrue;
25fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.fail;
26fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
27fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.app.PendingIntent;
28fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.content.Intent;
29fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.media.AudioManager;
30fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.net.Uri;
31fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Build;
32fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Bundle;
33fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Handler;
34fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.HandlerThread;
35fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Process;
36fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.ResultReceiver;
37fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.filters.FlakyTest;
38fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.filters.SdkSuppress;
39fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.filters.SmallTest;
40fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.runner.AndroidJUnit4;
41fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
42fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.annotation.NonNull;
43fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.MediaController2.ControllerCallback;
44fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.MediaSession2.ControllerInfo;
45fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.MediaSession2.SessionCallback;
46fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.TestServiceRegistry.SessionServiceCallback;
47fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.TestUtils.SyncHandler;
48fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
49fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.After;
50fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.Before;
51fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.Ignore;
52fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.Test;
53fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.runner.RunWith;
54fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
55fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.lang.reflect.Method;
56fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.List;
57fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.concurrent.CountDownLatch;
58fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.concurrent.TimeUnit;
59fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.concurrent.atomic.AtomicReference;
60fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
61fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang/**
62fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Tests {@link MediaController2}.
63fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang */
64fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang// TODO(jaewan): Implement host-side test so controller and session can run in different processes.
65fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang// TODO(jaewan): Fix flaky failure -- see MediaController2Impl.getController()
66fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang// TODO(jaeawn): Revisit create/close session in the sHandler. It's no longer necessary.
67fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
68fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@RunWith(AndroidJUnit4.class)
69fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@SmallTest
70fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@FlakyTest
71fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangpublic class MediaController2Test extends MediaSession2TestBase {
72fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private static final String TAG = "MediaController2Test";
73fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
74fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    PendingIntent mIntent;
75fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MediaSession2 mSession;
76fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MediaController2 mController;
77fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MockPlayer mPlayer;
78fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MockPlaylistAgent mMockAgent;
79fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
80fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Before
81fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Override
82fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void setUp() throws Exception {
83fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        super.setUp();
84fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Intent sessionActivity = new Intent(mContext, MockActivity.class);
85fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Create this test specific MediaSession2 to use our own Handler.
86fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
87fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
88fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer = new MockPlayer(1);
89fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mMockAgent = new MockPlaylistAgent();
90fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession = new MediaSession2.Builder(mContext)
91fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
92fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(mMockAgent)
93fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
94fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @Override
95fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    public SessionCommandGroup2 onConnect(MediaSession2 session,
96fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            ControllerInfo controller) {
97fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        if (Process.myUid() == controller.getUid()) {
98fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            return super.onConnect(session, controller);
99fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        }
100fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        return null;
101fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
102fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
103fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @Override
104fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    public void onPlaylistMetadataChanged(MediaSession2 session,
105fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            MediaPlaylistAgent playlistAgent,
106fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            MediaMetadata2 metadata) {
107fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        super.onPlaylistMetadataChanged(session, playlistAgent, metadata);
108fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
109fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                })
110fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionActivity(mIntent)
111fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId(TAG).build();
112fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController = createController(mSession.getToken());
113fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().setHandler(sHandler);
114fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
115fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
116fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @After
117fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Override
118fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void cleanUp() throws Exception {
119fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        super.cleanUp();
120fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        if (mSession != null) {
121fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mSession.close();
122fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
123fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().cleanUp();
124fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
125fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
126fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
127fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * Test if the {@link MediaSession2TestBase.TestControllerCallback} wraps the callback proxy
128fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * without missing any method.
129fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
130fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
131fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testTestControllerCallback() {
132fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
133fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        Method[] methods = TestControllerCallback.class.getMethods();
134fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(methods);
135fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        for (int i = 0; i < methods.length; i++) {
136fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            // For any methods in the controller callback, TestControllerCallback should have
137fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            // overriden the method and call matching API in the callback proxy.
138fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertNotEquals("TestControllerCallback should override " + methods[i]
139fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            + " and call callback proxy",
140fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    ControllerCallback.class, methods[i].getDeclaringClass());
141fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
142fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
143fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
144fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
145fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlay() {
146fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
147fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.play();
148fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
149fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
150fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
151fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
152fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
153fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPlayCalled);
154fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
155fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
156fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
157fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPause() {
158fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
159fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.pause();
160fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
161fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
162fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
163fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
164fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
165fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPauseCalled);
166fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
167fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
168fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
169fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testReset() {
170fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
171fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.reset();
172fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
173fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
174fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
175fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
176fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
177fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mResetCalled);
178fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
179fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
180fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
181fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepare() {
182fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
183fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.prepare();
184fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
185fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
186fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
187fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
188fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
189fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPrepareCalled);
190fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
191fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
192fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
193fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSeekTo() {
194fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
195fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final long seekPosition = 12125L;
196fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.seekTo(seekPosition);
197fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
198fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
199fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
200fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
201fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
202fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mSeekToCalled);
203fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(seekPosition, mPlayer.mSeekPosition);
204fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
205fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
206fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
207fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGettersAfterConnected() throws InterruptedException {
208fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
209fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
210fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final long position = 150000;
211fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final long bufferedPosition = 900000;
212fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final float speed = 0.5f;
213fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
214fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mLastPlayerState = state;
215fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mCurrentPosition = position;
216fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mBufferedPosition = bufferedPosition;
217fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mPlaybackSpeed = speed;
218fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
2191e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim        long time1 = System.currentTimeMillis();
220fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
2211e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim        long time2 = System.currentTimeMillis();
222fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(state, controller.getPlayerState());
223fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(bufferedPosition, controller.getBufferedPosition());
224e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        assertEquals(speed, controller.getPlaybackSpeed(), 0.0f);
2251e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim        long positionLowerBound = (long) (position + speed * (System.currentTimeMillis() - time2));
2261e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim        long currentPosition = controller.getCurrentPosition();
2271e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim        long positionUpperBound = (long) (position + speed * (System.currentTimeMillis() - time1));
2281e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim        assertTrue("curPos=" + currentPosition + ", lowerBound=" + positionLowerBound
2291e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim                        + ", upperBound=" + positionUpperBound,
2301e7820def08357c7a191557bccc34e435c9cf6d4Jaewan Kim                positionLowerBound <= currentPosition && currentPosition <= positionUpperBound);
231fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
232fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
233fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
234fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetSessionActivity() {
235fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
236fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        PendingIntent sessionActivity = mController.getSessionActivity();
237fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
238fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
239fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
240fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
241fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
242fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetPlaylist() throws InterruptedException {
243fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
244fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final List<MediaItem2> list = TestUtils.createPlaylist(2);
245fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.setPlaylist(list, null /* Metadata */);
246fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
247fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
248fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSetPlaylistCalled);
249fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNull(mMockAgent.mMetadata);
250fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
251fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(mMockAgent.mPlaylist);
252fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(list.size(), mMockAgent.mPlaylist.size());
253fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        for (int i = 0; i < list.size(); i++) {
254fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            // MediaController2.setPlaylist does not ensure the equality of the items.
255fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(list.get(i).getMediaId(), mMockAgent.mPlaylist.get(i).getMediaId());
256fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
257fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
258fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
259fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
260fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * This also tests {@link ControllerCallback#onPlaylistChanged(
261fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * MediaController2, List, MediaMetadata2)}.
262fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
263fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
264fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetPlaylist() throws InterruptedException {
265fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
266fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final List<MediaItem2> testList = TestUtils.createPlaylist(2);
267fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final AtomicReference<List<MediaItem2>> listFromCallback = new AtomicReference<>();
268fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
269fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
270fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
271fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlaylistChanged(MediaController2 controller,
272fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    List<MediaItem2> playlist, MediaMetadata2 metadata) {
273fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNotNull(playlist);
274fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testList.size(), playlist.size());
275fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                for (int i = 0; i < playlist.size(); i++) {
276fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    assertEquals(testList.get(i).getMediaId(), playlist.get(i).getMediaId());
277fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
278fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                listFromCallback.set(playlist);
279fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
280fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
281fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
282fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
283fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
284fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public List<MediaItem2> getPlaylist() {
285fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testList;
286fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
287fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
288fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
289fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
290fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testControllerCallback_onPlaylistChanged")
291fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
292fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(agent)
293fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .build()) {
294fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(
295fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    session.getToken(), true, callback);
296fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            agent.notifyPlaylistChanged();
297fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
298fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(listFromCallback.get(), controller.getPlaylist());
299fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
300fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
301fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
302fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
303fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testUpdatePlaylistMetadata() throws InterruptedException {
304fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
305fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
306fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.updatePlaylistMetadata(testMetadata);
307fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
308fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
309fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
310fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(mMockAgent.mMetadata);
311fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testMetadata.getMediaId(), mMockAgent.mMetadata.getMediaId());
312fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
313fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
314fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
315fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetPlaylistMetadata() throws InterruptedException {
316fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
317fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
318fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final AtomicReference<MediaMetadata2> metadataFromCallback = new AtomicReference<>();
319fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
320fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
321fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
322fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlaylistMetadataChanged(MediaController2 controller,
323fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    MediaMetadata2 metadata) {
324fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNotNull(testMetadata);
325fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testMetadata.getMediaId(), metadata.getMediaId());
326fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                metadataFromCallback.set(metadata);
327fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
328fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
329fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
330fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
331fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
332fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public MediaMetadata2 getPlaylistMetadata() {
333fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testMetadata;
334fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
335fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
336fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
337fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
338fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testGetPlaylistMetadata")
339fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
340fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(agent)
341fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .build()) {
342fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken(), true, callback);
343fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            agent.notifyPlaylistMetadataChanged();
344fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
345fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(metadataFromCallback.get().getMediaId(),
346fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    controller.getPlaylistMetadata().getMediaId());
347fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
348fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
349fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
350e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon    @Test
351e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon    public void testSetPlaybackSpeed() throws Exception {
352e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        prepareLooper();
353e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        final float speed = 1.5f;
354e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        mController.setPlaybackSpeed(speed);
355e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
356e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        assertEquals(speed, mPlayer.mPlaybackSpeed, 0.0f);
357e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon    }
358e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon
359fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
360fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * Test whether {@link MediaSession2#setPlaylist(List, MediaMetadata2)} is notified
361fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * through the
362fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * {@link ControllerCallback#onPlaylistMetadataChanged(MediaController2, MediaMetadata2)}
363fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * if the controller doesn't have {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST} but
364fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST_METADATA}.
365fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
366fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
367fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_onPlaylistMetadataChanged() throws InterruptedException {
368fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
369fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaItem2 item = TestUtils.createMediaItemWithMetadata();
370fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final List<MediaItem2> list = TestUtils.createPlaylist(2);
371fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
372fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
373fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
374fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlaylistMetadataChanged(MediaController2 controller,
375fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    MediaMetadata2 metadata) {
376fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNotNull(metadata);
377fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(item.getMediaId(), metadata.getMediaId());
378fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
379fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
380fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
381fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback sessionCallback = new SessionCallback() {
382fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
383fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public SessionCommandGroup2 onConnect(MediaSession2 session,
384fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    ControllerInfo controller) {
385fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                if (Process.myUid() == controller.getUid()) {
386fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    SessionCommandGroup2 commands = new SessionCommandGroup2();
387fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    commands.addCommand(new SessionCommand2(
388fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                              SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST_METADATA));
389fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    return commands;
390fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
391fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return super.onConnect(session, controller);
392fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
393fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
394fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
395fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
396fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public MediaMetadata2 getPlaylistMetadata() {
397fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return item.getMetadata();
398fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
399fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
400fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
401fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public List<MediaItem2> getPlaylist() {
402fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return list;
403fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
404fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
405fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
406fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
407fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testControllerCallback_onPlaylistMetadataChanged")
408fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, sessionCallback)
409fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(agent)
410fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .build()) {
411fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken(), true, callback);
412fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            agent.notifyPlaylistMetadataChanged();
413fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
414fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
415fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
416fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
417fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
418fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testAddPlaylistItem() throws InterruptedException {
419fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
420fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testIndex = 12;
421fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
422fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.addPlaylistItem(testIndex, testMediaItem);
423fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
424fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
425fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mAddPlaylistItemCalled);
426fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testIndex, mMockAgent.mIndex);
427fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // MediaController2.addPlaylistItem does not ensure the equality of the items.
428fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
429fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
430fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
431fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
432fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testRemovePlaylistItem() throws InterruptedException {
433fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
434fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mMockAgent.mPlaylist = TestUtils.createPlaylist(2);
435fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
436fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Recreate controller for sending removePlaylistItem.
437fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // It's easier to ensure that MediaController2.getPlaylist() returns the playlist from the
438fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // agent.
439fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
440fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaItem2 targetItem = controller.getPlaylist().get(0);
441fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.removePlaylistItem(targetItem);
442fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
443fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
444fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mRemovePlaylistItemCalled);
445fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(targetItem, mMockAgent.mItem);
446fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
447fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
448fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
449fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testReplacePlaylistItem() throws InterruptedException {
450fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
451fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testIndex = 12;
452fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
453fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.replacePlaylistItem(testIndex, testMediaItem);
454fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
455fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
456fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mReplacePlaylistItemCalled);
457fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // MediaController2.replacePlaylistItem does not ensure the equality of the items.
458fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
459fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
460fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
461fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
462fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSkipToPreviousItem() throws InterruptedException {
463fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
464fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.skipToPreviousItem();
465fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
466fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSkipToPreviousItemCalled);
467fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
468fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
469fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
470fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSkipToNextItem() throws InterruptedException {
471fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
472fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.skipToNextItem();
473fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
474fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSkipToNextItemCalled);
475fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
476fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
477fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
478fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSkipToPlaylistItem() throws InterruptedException {
479fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
480fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
481fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaItem2 targetItem = TestUtils.createMediaItemWithMetadata();
482fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.skipToPlaylistItem(targetItem);
483fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
484fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
485fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
486fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(targetItem, mMockAgent.mItem);
487fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
488fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
489fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
490fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * This also tests {@link ControllerCallback#onShuffleModeChanged(MediaController2, int)}.
491fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
492fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
493fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetShuffleMode() throws InterruptedException {
494fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
495fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
496fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
497fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
498fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public int getShuffleMode() {
499fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testShuffleMode;
500fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
501fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
502fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
503fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
504fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
505fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
506fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testShuffleMode, shuffleMode);
507fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
508fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
509fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
510fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(mPlayer, agent, null);
511fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken(), true, callback);
512fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        agent.notifyShuffleModeChanged();
513fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
514fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testShuffleMode, controller.getShuffleMode());
515fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
516fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
517fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
518fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetShuffleMode() throws InterruptedException {
519fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
520fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
521fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.setShuffleMode(testShuffleMode);
522fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
523fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
524fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSetShuffleModeCalled);
525fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
526fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
527fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
528fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
529fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * This also tests {@link ControllerCallback#onRepeatModeChanged(MediaController2, int)}.
530fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
531fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
532fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetRepeatMode() throws InterruptedException {
533fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
534fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
535fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
536fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
537fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public int getRepeatMode() {
538fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testRepeatMode;
539fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
540fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
541fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
542fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
543fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
544fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
545fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testRepeatMode, repeatMode);
546fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
547fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
548fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
549fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(mPlayer, agent, null);
550fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken(), true, callback);
551fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        agent.notifyRepeatModeChanged();
552fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
553fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testRepeatMode, controller.getRepeatMode());
554fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
555fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
556fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
557fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetRepeatMode() throws InterruptedException {
558fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
559fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
560fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.setRepeatMode(testRepeatMode);
561fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
562fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
563fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSetRepeatModeCalled);
564fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
565fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
566fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
567fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
568fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetVolumeTo() throws Exception {
569fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO(jaewan): Also test with local volume.
570fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
571fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int maxVolume = 100;
572fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int currentVolume = 23;
573fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
574fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestVolumeProvider volumeProvider =
575fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
576fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
577fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
578fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaController2 controller = createController(mSession.getToken(), true, null);
579fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
580fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int targetVolume = 50;
581fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.setVolumeTo(targetVolume, 0 /* flags */);
582fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
583fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mSetVolumeToCalled);
584fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(targetVolume, volumeProvider.mVolume);
585fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
586fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
587fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
588fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testAdjustVolume() throws Exception {
589fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO(jaewan): Also test with local volume.
590fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
591fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int maxVolume = 100;
592fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int currentVolume = 23;
593fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
594fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestVolumeProvider volumeProvider =
595fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
596fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
597fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
598fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaController2 controller = createController(mSession.getToken(), true, null);
599fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
600fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int direction = AudioManager.ADJUST_RAISE;
601fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.adjustVolume(direction, 0 /* flags */);
602fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
603fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mAdjustVolumeCalled);
604fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(direction, volumeProvider.mDirection);
605fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
606fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
607fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
608fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetPackageName() {
609fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
610fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
611fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
612fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
613fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
614fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSendCustomCommand() throws InterruptedException {
615fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
616fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO(jaewan): Need to revisit with the permission.
617fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCommand2 testCommand =
618fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
619fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle testArgs = new Bundle();
620fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testArgs.putString("args", "testSendCustomCommand");
621fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
622fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
623fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
624fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
625fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onCustomCommand(MediaSession2 session, ControllerInfo controller,
626fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    SessionCommand2 customCommand, Bundle args, ResultReceiver cb) {
627fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
628fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testCommand, customCommand);
629fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(testArgs, args));
630fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNull(cb);
631fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
632fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
633fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
634fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.close();
635fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
636fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
637fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaController2 controller = createController(mSession.getToken());
638fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.sendCustomCommand(testCommand, testArgs, null);
639fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
640fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
641fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
642fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
643fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_onConnected() throws InterruptedException {
644fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
645fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // createController() uses controller callback to wait until the controller becomes
646fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // available.
647fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
648fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(controller);
649fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
650fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
651fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
652fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_sessionRejects() throws InterruptedException {
653fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
654fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaSession2.SessionCallback sessionCallback = new SessionCallback() {
655fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
656fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public SessionCommandGroup2 onConnect(MediaSession2 session,
657fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    ControllerInfo controller) {
658fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return null;
659fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
660fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
661fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sHandler.postAndSync(new Runnable() {
662fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
663fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
664fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession.close();
665fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
666fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        .setSessionCallback(sHandlerExecutor, sessionCallback).build();
667fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
668fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
669fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller =
670fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                createController(mSession.getToken(), false, null);
671fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(controller);
672fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForConnect(controller, false);
673fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(controller, true);
674fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
675fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
676fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
677fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_releaseSession() throws InterruptedException {
678fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
679fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.close();
680fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
681fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
682fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
683fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
684fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_close() throws InterruptedException {
685fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
686fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
687fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
688fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
689fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
690fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
691fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testFastForward() throws InterruptedException {
692fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
693fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
694fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
695fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
696fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onFastForward(MediaSession2 session, ControllerInfo controller) {
697fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
698fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
699fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
700fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
701fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
702fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
703fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
704fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testFastForward").build()) {
705fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
706fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.fastForward();
707fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
708fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
709fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
710fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
711fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
712fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testRewind() throws InterruptedException {
713fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
714fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
715fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
716fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
717fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onRewind(MediaSession2 session, ControllerInfo controller) {
718fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
719fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
720fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
721fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
722fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
723fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
724fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
725fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testRewind").build()) {
726fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
727fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.rewind();
728fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
729fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
730fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
731fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
732fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
733fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlayFromSearch() throws InterruptedException {
734fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
735fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "random query";
736fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
737fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
738fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
739fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
740fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
741fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
742fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String query, Bundle extras) {
743fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                super.onPlayFromSearch(session, controller, query, extras);
744fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
745fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, query);
746fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
747fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
748fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
749fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
750fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
751fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
752fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
753fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPlayFromSearch").build()) {
754fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
755fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.playFromSearch(request, bundle);
756fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
757fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
758fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
759fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
760fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
761fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlayFromUri() throws InterruptedException {
762fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
763fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Uri request = Uri.parse("foo://boo");
764fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
765fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
766fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
767fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
768fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
769fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlayFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
770fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    Bundle extras) {
771fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
772fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, uri);
773fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
774fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
775fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
776fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
777fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
778fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
779fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
780fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPlayFromUri").build()) {
781fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
782fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.playFromUri(request, bundle);
783fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
784fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
785fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
786fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
787fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
788fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlayFromMediaId() throws InterruptedException {
789fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
790fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "media_id";
791fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
792fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
793fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
794fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
795fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
796fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
797fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String mediaId, Bundle extras) {
798fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
799fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, mediaId);
800fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
801fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
802fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
803fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
804fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
805fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
806fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
807fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPlayFromMediaId").build()) {
808fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
809fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.playFromMediaId(request, bundle);
810fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
811fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
812fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
813fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
814fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
815fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepareFromSearch() throws InterruptedException {
816fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
817fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "random query";
818fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
819fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
820fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
821fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
822fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
823fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
824fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String query, Bundle extras) {
825fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
826fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, query);
827fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
828fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
829fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
830fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
831fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
832fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
833fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
834fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPrepareFromSearch").build()) {
835fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
836fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.prepareFromSearch(request, bundle);
837fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
838fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
839fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
840fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
841fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
842fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepareFromUri() throws InterruptedException {
843fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
844fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Uri request = Uri.parse("foo://boo");
845fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
846fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
847fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
848fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
849fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
850fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
851fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    Bundle extras) {
852fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
853fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, uri);
854fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
855fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
856fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
857fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
858fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
859fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
860fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
861fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPrepareFromUri").build()) {
862fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
863fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.prepareFromUri(request, bundle);
864fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
865fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
866fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
867fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
868fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
869fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepareFromMediaId() throws InterruptedException {
870fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
871fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "media_id";
872fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
873fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
874fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
875fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
876fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
877fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
878fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String mediaId, Bundle extras) {
879fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
880fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, mediaId);
881fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
882fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
883fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
884fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
885fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
886fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
887fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
888fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPrepareFromMediaId").build()) {
889fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
890fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.prepareFromMediaId(request, bundle);
891fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
892fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
893fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
894fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
895fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
896fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetRating() throws InterruptedException {
897fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
898fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int ratingType = Rating2.RATING_5_STARS;
899fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final float ratingValue = 3.5f;
900fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Rating2 rating = Rating2.newStarRating(ratingType, ratingValue);
901fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String mediaId = "media_id";
902fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
903fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
904fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
905fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
906fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onSetRating(MediaSession2 session, ControllerInfo controller,
907fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String mediaIdOut, Rating2 ratingOut) {
908fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
909fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mediaId, mediaIdOut);
910fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(rating, ratingOut);
911fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
912fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
913fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
914fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
915fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
916fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
917fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
918fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testSetRating").build()) {
919fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
920fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.setRating(mediaId, rating);
921fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
922fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
923fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
924fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
925fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
926fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testIsConnected() throws InterruptedException {
927fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
928fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mController.isConnected());
929fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sHandler.postAndSync(new Runnable() {
930fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
931fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
932fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession.close();
933fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
934fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
935fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
936fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertFalse(mController.isConnected());
937fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
938fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
939fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
940fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * Test potential deadlock for calls between controller and session.
941fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
942fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
943fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testDeadlock() throws InterruptedException {
944fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
945fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sHandler.postAndSync(new Runnable() {
946fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
947fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
948fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession.close();
949fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession = null;
950fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
951fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
952fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
953fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Two more threads are needed not to block test thread nor test wide thread (sHandler).
954fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final HandlerThread sessionThread = new HandlerThread("testDeadlock_session");
955fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final HandlerThread testThread = new HandlerThread("testDeadlock_test");
956fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sessionThread.start();
957fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testThread.start();
958fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SyncHandler sessionHandler = new SyncHandler(sessionThread.getLooper());
959fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Handler testHandler = new Handler(testThread.getLooper());
960fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
961fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
962fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            final MockPlayer player = new MockPlayer(0);
963fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            sessionHandler.postAndSync(new Runnable() {
964fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                @Override
965fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                public void run() {
966fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    mSession = new MediaSession2.Builder(mContext)
967fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            .setPlayer(mPlayer)
968fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
969fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            .setId("testDeadlock").build();
970fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
971fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            });
972fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            final MediaController2 controller = createController(mSession.getToken());
973fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            testHandler.post(new Runnable() {
974fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                @Override
975fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                public void run() {
976fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    final int state = MediaPlayerBase.PLAYER_STATE_ERROR;
977fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    for (int i = 0; i < 100; i++) {
978fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // triggers call from session to controller.
979fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
980fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // triggers call from controller to session.
981fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.play();
982fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
983fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // Repeat above
984fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
985fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.pause();
986fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
987fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.reset();
988fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
989fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.skipToNextItem();
990fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
991fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.skipToPreviousItem();
992fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
993fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    // This may hang if deadlock happens.
994fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    latch.countDown();
995fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
996fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            });
997fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
998fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } finally {
999fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            if (mSession != null) {
1000fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                sessionHandler.postAndSync(new Runnable() {
1001fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @Override
1002fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    public void run() {
1003fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // Clean up here because sessionHandler will be removed afterwards.
1004fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        mSession.close();
1005fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        mSession = null;
1006fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
1007fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                });
1008fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1009fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            if (sessionThread != null) {
1010fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                sessionThread.quitSafely();
1011fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1012fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            if (testThread != null) {
1013fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                testThread.quitSafely();
1014fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1015fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1016fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1017fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1018fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1019fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetServiceToken() {
1020fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1021fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        SessionToken2 token = TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID);
1022fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(token);
1023fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(mContext.getPackageName(), token.getPackageName());
1024fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(MockMediaSessionService2.ID, token.getId());
1025fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
1026fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1027fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1028fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1029fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testConnectToService_sessionService() throws InterruptedException {
1030fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1031fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testConnectToService(MockMediaSessionService2.ID);
1032fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1033fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1034fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Ignore
1035fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1036fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testConnectToService_libraryService() throws InterruptedException {
1037fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1038fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testConnectToService(MockMediaLibraryService2.ID);
1039fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1040fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1041fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testConnectToService(String id) throws InterruptedException {
1042fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1043fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1044fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback sessionCallback = new SessionCallback() {
1045fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1046fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
1047fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @NonNull ControllerInfo controller) {
1048fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                if (Process.myUid() == controller.getUid()) {
1049fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    if (mSession != null) {
1050fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        mSession.close();
1051fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
1052fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    mSession = session;
1053fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    mPlayer = (MockPlayer) session.getPlayer();
1054fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    assertEquals(mContext.getPackageName(), controller.getPackageName());
1055fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    assertFalse(controller.isTrusted());
1056fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    latch.countDown();
1057fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
1058fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return super.onConnect(session, controller);
1059fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1060fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1061fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
1062fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1063fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController = createController(TestUtils.getServiceToken(mContext, id));
1064fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1065fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1066fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Test command from controller to session service
1067fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO: Re enable when transport control works
1068fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        /*
1069fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.play();
1070fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1071fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPlayCalled);
1072fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        */
1073fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1074fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Test command from session service to controller
1075fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO(jaewan): Add equivalent tests again
1076fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        /*
1077fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1078fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.registerPlayerEventCallback((state) -> {
1079fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertNotNull(state);
1080fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(PlaybackState.STATE_REWINDING, state.getState());
1081fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            latch.countDown();
1082fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }, sHandler);
1083fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.notifyPlaybackState(
1084fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                TestUtils.createPlaybackState(PlaybackState.STATE_REWINDING));
1085fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1086fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        */
1087fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1088fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1089fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1090fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerAfterSessionIsGone_session() throws InterruptedException {
1091fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1092fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(mSession.getToken().getId());
1093fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1094fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1095fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // TODO(jaewan): Re-enable this test
1096fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Ignore
1097fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1098fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerAfterSessionIsClosed_sessionService() throws InterruptedException {
1099fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1100fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        /*
1101fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        connectToService(TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID));
1102fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(MockMediaSessionService2.ID);
1103fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        */
1104fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1105fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1106fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1107fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    public void testSubscribeRouteInfo() throws InterruptedException {
1108fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        prepareLooper();
1109fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final TestSessionCallback callback = new TestSessionCallback() {
1110fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            @Override
1111fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            public void onSubscribeRoutesInfo(@NonNull MediaSession2 session,
1112fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                    @NonNull ControllerInfo controller) {
1113fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertEquals(mContext.getPackageName(), controller.getPackageName());
1114fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                mLatch.countDown();
1115fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            }
1116fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1117fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            @Override
1118fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            public void onUnsubscribeRoutesInfo(@NonNull MediaSession2 session,
1119fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                    @NonNull ControllerInfo controller) {
1120fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertEquals(mContext.getPackageName(), controller.getPackageName());
1121fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                mLatch.countDown();
1122fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            }
1123fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        };
1124fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession.close();
1125fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
1126fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
1127fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final MediaController2 controller = createController(mSession.getToken());
1128fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1129fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        callback.resetLatchCount(1);
1130fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        controller.subscribeRoutesInfo();
1131fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1132fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1133fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        callback.resetLatchCount(1);
1134fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        controller.unsubscribeRoutesInfo();
1135fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1136fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    }
1137fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1138fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    @Test
1139fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    public void testSelectRouteInfo() throws InterruptedException {
1140fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        prepareLooper();
1141fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final Bundle testRoute = new Bundle();
1142fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        testRoute.putString("id", "testRoute");
1143fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final TestSessionCallback callback = new TestSessionCallback() {
1144fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            @Override
1145fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            public void onSelectRoute(@NonNull MediaSession2 session,
1146fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                    @NonNull ControllerInfo controller, @NonNull Bundle route) {
1147fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertEquals(mContext.getPackageName(), controller.getPackageName());
1148fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertTrue(TestUtils.equals(route, testRoute));
1149fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                mLatch.countDown();
1150fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            }
1151fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        };
1152fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession.close();
1153fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
1154fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
1155fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final MediaController2 controller = createController(mSession.getToken());
1156fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1157fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        callback.resetLatchCount(1);
1158fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        controller.selectRoute(testRoute);
1159fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1160fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    }
1161fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1162fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    @Test
1163fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_beforeConnected() throws InterruptedException {
1164fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1165fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller =
1166fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                createController(mSession.getToken(), false, null);
1167fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.close();
1168fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1169fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1170fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1171fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_twice() {
1172fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1173fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1174fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1175fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1176fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1177fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1178fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_session() throws InterruptedException {
1179fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1180fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String id = mSession.getToken().getId();
1181fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1182fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // close is done immediately for session.
1183fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1184fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1185fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Test whether the controller is notified about later close of the session or
1186fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // re-creation.
1187fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(id);
1188fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1189fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1190fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Ignore
1191fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1192fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_sessionService() throws InterruptedException {
1193fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1194fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testCloseFromService(MockMediaSessionService2.ID);
1195fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1196fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1197fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Ignore
1198fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1199fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_libraryService() throws InterruptedException {
1200fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1201fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testCloseFromService(MockMediaLibraryService2.ID);
1202fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1203fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1204fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private void testCloseFromService(String id) throws InterruptedException {
1205fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1206fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().setSessionServiceCallback(new SessionServiceCallback() {
1207fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1208fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onCreated() {
1209fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                // Do nothing.
1210fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1211fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1212fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1213fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onDestroyed() {
1214fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1215fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1216fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
1217fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController = createController(TestUtils.getServiceToken(mContext, id));
1218fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1219fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Wait until close triggers onDestroy() of the session service.
1220fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1221fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNull(TestServiceRegistry.getInstance().getServiceInstance());
1222fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1223fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1224fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Test whether the controller is notified about later close of the session or
1225fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // re-creation.
1226fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(id);
1227fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1228fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1229fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private void testControllerAfterSessionIsClosed(final String id) throws InterruptedException {
1230fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // This cause session service to be died.
1231fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.close();
1232fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
1233fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1234fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1235fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Ensure that the controller cannot use newly create session with the same ID.
1236fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Recreated session has different session stub, so previously created controller
1237fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // shouldn't be available.
1238fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession = new MediaSession2.Builder(mContext)
1239fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1240fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
1241fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId(id).build();
1242fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1243fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1244fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1245fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // Test that mSession and mController doesn't interact.
1246fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // Note that this method can be called after the mSession is died, so mSession may not have
1247fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // valid player.
1248fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private void testNoInteraction() throws InterruptedException {
1249fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO: check that calls from the controller to session shouldn't be delivered.
1250fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1251fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Calls from the session to controller shouldn't be delivered.
1252fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1253fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        setRunnableForOnCustomCommand(mController, new Runnable() {
1254fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1255fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
1256fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1257fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1258fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
1259fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        SessionCommand2 customCommand = new SessionCommand2("testNoInteraction", null);
1260fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.sendCustomCommand(customCommand, null);
1261fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1262fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        setRunnableForOnCustomCommand(mController, null);
1263fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1264fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1265fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // TODO(jaewan): Add  test for service connect rejection, when we differentiate session
1266fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    //               active/inactive and connection accept/refuse
1267fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1268fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    class TestVolumeProvider extends VolumeProviderCompat {
1269fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch mLatch = new CountDownLatch(1);
1270fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        boolean mSetVolumeToCalled;
1271fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        boolean mAdjustVolumeCalled;
1272fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        int mVolume;
1273fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        int mDirection;
1274fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1275fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestVolumeProvider(int controlType, int maxVolume, int currentVolume) {
1276fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            super(controlType, maxVolume, currentVolume);
1277fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1278fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1279fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        @Override
1280fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        public void onSetVolumeTo(int volume) {
1281fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mSetVolumeToCalled = true;
1282fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mVolume = volume;
1283fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mLatch.countDown();
1284fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1285fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1286fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        @Override
1287fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        public void onAdjustVolume(int direction) {
1288fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mAdjustVolumeCalled = true;
1289fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mDirection = direction;
1290fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mLatch.countDown();
1291fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1292fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1293fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1294fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    class TestSessionCallback extends SessionCallback {
1295fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        CountDownLatch mLatch;
1296fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1297fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        void resetLatchCount(int count) {
1298fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            mLatch = new CountDownLatch(count);
1299fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        }
1300fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    }
1301fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang}
1302