1816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/*
2816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Copyright (C) 2015 The Android Open Source Project
3816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
4816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
5816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * you may not use this file except in compliance with the License.
6816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * You may obtain a copy of the License at
7816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
8816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
9816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
10816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * Unless required by applicable law or agreed to in writing, software
11816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
12816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * See the License for the specific language governing permissions and
14816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * limitations under the License.
15816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */
16816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
17816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopackage com.android.tv.data;
18816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
19816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.ContentProvider;
20816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.ContentUris;
21816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.ContentValues;
22816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.content.Context;
23816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.database.ContentObserver;
24816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.database.Cursor;
25816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvContract;
26816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.media.tv.TvContract.Channels;
27816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.net.Uri;
28816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.AndroidTestCase;
29816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.MoreAsserts;
307d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport android.test.UiThreadTest;
31816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.mock.MockContentProvider;
32816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.mock.MockContentResolver;
33816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.mock.MockCursor;
34816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.test.suitebuilder.annotation.SmallTest;
35816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.text.TextUtils;
36816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.Log;
37816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport android.util.SparseArray;
38816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
39816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.testing.ChannelInfo;
40816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.testing.Constants;
417d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalkoimport com.android.tv.testing.Utils;
42816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport com.android.tv.util.TvInputManagerHelper;
43816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
44816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport org.mockito.Matchers;
45816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport org.mockito.Mockito;
46816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
47816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.ArrayList;
4807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport java.util.Arrays;
49816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.List;
50816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.concurrent.CountDownLatch;
51816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkoimport java.util.concurrent.TimeUnit;
52816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
53816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko/**
547d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Test for {@link ChannelDataManager}
55816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko *
56816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko * A test method may include tests for multiple methods to minimize the DB access.
577d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko * Note that all the methods of {@link ChannelDataManager} should be called from the UI thread.
58816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko */
59816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko@SmallTest
60816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalkopublic class ChannelDataManagerTest extends AndroidTestCase {
61816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final boolean DEBUG = false;
62816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final String TAG = "ChannelDataManagerTest";
63816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
64816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // Wait time for expected success.
65816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final long WAIT_TIME_OUT_MS = 1000L;
66816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final String DUMMY_INPUT_ID = "dummy";
67816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // TODO: Use Channels.COLUMN_BROWSABLE and Channels.COLUMN_LOCKED instead.
68816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final String COLUMN_BROWSABLE = "browsable";
69816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private static final String COLUMN_LOCKED = "locked";
70816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
71816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private ChannelDataManager mChannelDataManager;
72816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private TestChannelDataManagerListener mListener;
73816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private FakeContentResolver mContentResolver;
74816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private FakeContentProvider mContentProvider;
75816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
76816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
77816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    protected void setUp() throws Exception {
78816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.setUp();
79816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertTrue("More than 2 channels to test", Constants.UNIT_TEST_CHANNEL_COUNT > 2);
80816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
81816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentProvider = new FakeContentProvider(getContext());
82816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentResolver = new FakeContentResolver();
83816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentResolver.addProvider(TvContract.AUTHORITY, mContentProvider);
84816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mListener = new TestChannelDataManagerListener();
857d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        Utils.runOnMainSync(new Runnable() {
867d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            @Override
877d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            public void run() {
887d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko                TvInputManagerHelper mockHelper = Mockito.mock(TvInputManagerHelper.class);
897d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko                Mockito.when(mockHelper.hasTvInputInfo(Matchers.anyString())).thenReturn(true);
907d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko                mChannelDataManager = new ChannelDataManager(getContext(), mockHelper,
91ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                        mContentResolver);
927d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko                mChannelDataManager.addListener(mListener);
937d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            }
947d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        });
95816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
96816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
97816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    @Override
98816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    protected void tearDown() throws Exception {
997d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        Utils.runOnMainSync(new Runnable() {
1007d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            @Override
1017d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            public void run() {
1027d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko                mChannelDataManager.stop();
1037d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            }
1047d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko        });
105816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        super.tearDown();
106816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
107816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
108816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void startAndWaitForComplete() throws Exception {
109816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.start();
110816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        try {
111816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertTrue(mListener.loadFinishedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
112816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        } catch (InterruptedException e) {
113816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            throw e;
114816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
115816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
116816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
117816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private void restart() throws Exception {
118816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.stop();
119816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mListener.reset();
120816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
121816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
122816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
1237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
124816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testIsDbLoadFinished() throws Exception {
125816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
126816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertTrue(mChannelDataManager.isDbLoadFinished());
127816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
128816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
129816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
130816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Test for following methods
131816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#getChannelCount}
132816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#getChannelList}
133816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#getChannel}
134816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1357d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
136816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testGetChannels() throws Exception {
137816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
138816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
139816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#getChannelCount}
140816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(Constants.UNIT_TEST_CHANNEL_COUNT, mChannelDataManager.getChannelCount());
141816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
142816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#getChannelList}
143816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<ChannelInfo> channelInfoList = new ArrayList<>();
144816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (int i = 1; i <= Constants.UNIT_TEST_CHANNEL_COUNT; i++) {
145816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channelInfoList.add(ChannelInfo.create(getContext(), i));
146816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
147816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<Channel> channelList = mChannelDataManager.getChannelList();
148816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (Channel channel : channelList) {
149816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            boolean found = false;
150816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            for (ChannelInfo channelInfo : channelInfoList) {
151816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (TextUtils.equals(channelInfo.name, channel.getDisplayName())
152816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        && TextUtils.equals(channelInfo.name, channel.getDisplayName())) {
153816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    found = true;
154816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    channelInfoList.remove(channelInfo);
155816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    break;
156816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
157816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
158816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertTrue("Cannot find (" + channel + ")", found);
159816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
160816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
161816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#getChannelIndex()}
162816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (Channel channel : channelList) {
163816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertEquals(channel, mChannelDataManager.getChannel(channel.getId()));
164816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
165816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
166816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
167816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
168816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Test for {@link ChannelDataManager#getChannelCount} when no channel is available.
169816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1707d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
171816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testGetChannels_noChannels() throws Exception {
172816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentProvider.clear();
173816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
174816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(0, mChannelDataManager.getChannelCount());
175816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
176816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
177816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
178816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Test for following methods and channel listener with notifying change.
179816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#updateBrowsable}
180816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#applyUpdatedValuesToDb}
181816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
1827d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
183816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testBrowsable() throws Exception {
184816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
185816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
18607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        // Test if all channels are browsable
187816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<Channel> channelList = new ArrayList<>(mChannelDataManager.getChannelList());
188816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<Channel> browsableChannelList = mChannelDataManager.getBrowsableChannelList();
189816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (Channel browsableChannel : browsableChannelList) {
190816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            boolean found = channelList.remove(browsableChannel);
191816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertTrue("Cannot find (" + browsableChannel + ")", found);
192816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
193816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(0, channelList.size());
194816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
195816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Prepare for next tests.
196816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TestChannelDataManagerChannelListener channelListener =
197816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                new TestChannelDataManagerChannelListener();
198816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Channel channel1 = mChannelDataManager.getChannelList().get(0);
199816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.addChannelListener(channel1.getId(), channelListener);
200816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
201816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#updateBrowsable} & notification.
202816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.updateBrowsable(channel1.getId(), false, false);
203816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertTrue(mListener.channelBrowsableChangedCalled);
204816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertFalse(mChannelDataManager.getBrowsableChannelList().contains(channel1));
205816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        MoreAsserts.assertContentsInAnyOrder(channelListener.updatedChannels, channel1);
206816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        channelListener.reset();
207816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
208816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#applyUpdatedValuesToDb}
20948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // Disable the update notification to avoid the unwanted call of "onLoadFinished".
21048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mContentResolver.mNotifyDisabled = true;
211816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.applyUpdatedValuesToDb();
212816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        restart();
213816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        browsableChannelList = mChannelDataManager.getBrowsableChannelList();
214816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(Constants.UNIT_TEST_CHANNEL_COUNT - 1, browsableChannelList.size());
215816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertFalse(browsableChannelList.contains(channel1));
216816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
217816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
218816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
219816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Test for following methods and channel listener without notifying change.
220816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#updateBrowsable}
221816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#applyUpdatedValuesToDb}
222816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
2237d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
224816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testBrowsable_skipNotification() throws Exception {
225816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
226816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
227816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Prepare for next tests.
228816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TestChannelDataManagerChannelListener channelListener =
229816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                new TestChannelDataManagerChannelListener();
230816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Channel channel1 = mChannelDataManager.getChannelList().get(0);
231816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Channel channel2 = mChannelDataManager.getChannelList().get(1);
232816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.addChannelListener(channel1.getId(), channelListener);
233816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.addChannelListener(channel2.getId(), channelListener);
234816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
235816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#updateBrowsable} & skip notification.
236816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.updateBrowsable(channel1.getId(), false, true);
237816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.updateBrowsable(channel2.getId(), false, true);
238816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.updateBrowsable(channel1.getId(), true, true);
239816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertFalse(mListener.channelBrowsableChangedCalled);
240816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<Channel> browsableChannelList = mChannelDataManager.getBrowsableChannelList();
241816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertTrue(browsableChannelList.contains(channel1));
242816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertFalse(browsableChannelList.contains(channel2));
243816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
244816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#applyUpdatedValuesToDb}
24548dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // Disable the update notification to avoid the unwanted call of "onLoadFinished".
24648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mContentResolver.mNotifyDisabled = true;
247816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.applyUpdatedValuesToDb();
248816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        restart();
249816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        browsableChannelList = mChannelDataManager.getBrowsableChannelList();
250816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(Constants.UNIT_TEST_CHANNEL_COUNT - 1, browsableChannelList.size());
251816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertFalse(browsableChannelList.contains(channel2));
252816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
253816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
254816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
255816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Test for following methods and channel listener.
256816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#updateLocked}
257816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     *   - {@link ChannelDataManager#applyUpdatedValuesToDb}
258816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
2597d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
260816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testLocked() throws Exception {
261816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
262816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
263816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test if all channels aren't locked at the first time.
264816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        List<Channel> channelList = mChannelDataManager.getChannelList();
265816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        for (Channel channel : channelList) {
266816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertFalse(channel + " is locked", channel.isLocked());
267816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
268816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
269816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Prepare for next tests.
270816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Channel channel = mChannelDataManager.getChannelList().get(0);
271816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
272816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#updateLocked}
273816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.updateLocked(channel.getId(), true);
274816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertTrue(mChannelDataManager.getChannel(channel.getId()).isLocked());
275816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
276816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test {@link ChannelDataManager#applyUpdatedValuesToDb}.
27748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        // Disable the update notification to avoid the unwanted call of "onLoadFinished".
27848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mContentResolver.mNotifyDisabled = true;
279816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.applyUpdatedValuesToDb();
280816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        restart();
281816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertTrue(mChannelDataManager.getChannel(channel.getId()).isLocked());
282816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
283816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Cleanup
284816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.updateLocked(channel.getId(), false);
285816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
286816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
287816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    /**
288816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     * Test ChannelDataManager when channels in TvContract are updated, removed, or added.
289816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko     */
2907d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko    @UiThreadTest
291816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    public void testChannelListChanged() throws Exception {
292816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        startAndWaitForComplete();
293816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
294816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test channel add.
295816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mListener.reset();
296816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        long testChannelId = Constants.UNIT_TEST_CHANNEL_COUNT + 1;
297816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        ChannelInfo testChannelInfo = ChannelInfo.create(getContext(), (int) testChannelId);
298816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        testChannelId = Constants.UNIT_TEST_CHANNEL_COUNT + 1;
299816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentProvider.simulateInsert(testChannelInfo);
30007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        assertTrue(
30107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                mListener.channelListUpdatedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
302816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(Constants.UNIT_TEST_CHANNEL_COUNT + 1, mChannelDataManager.getChannelCount());
303816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
304816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test channel update
305816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mListener.reset();
306816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        TestChannelDataManagerChannelListener channelListener =
307816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                new TestChannelDataManagerChannelListener();
308816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mChannelDataManager.addChannelListener(testChannelId, channelListener);
309816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        String newName = testChannelInfo.name + "_test";
310816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentProvider.simulateUpdate(testChannelId, newName);
31107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        assertTrue(
31207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                mListener.channelListUpdatedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
31307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        assertTrue(
31407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                channelListener.channelChangedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
315816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(0, channelListener.removedChannels.size());
316816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(1, channelListener.updatedChannels.size());
317816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Channel updatedChannel = channelListener.updatedChannels.get(0);
318816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(testChannelId, updatedChannel.getId());
319816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(testChannelInfo.number, updatedChannel.getDisplayNumber());
320816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(newName, updatedChannel.getDisplayName());
321816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(Constants.UNIT_TEST_CHANNEL_COUNT + 1,
322816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mChannelDataManager.getChannelCount());
323816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
324816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        // Test channel remove.
325816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mListener.reset();
326816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        channelListener.reset();
327816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        mContentProvider.simulateDelete(testChannelId);
32807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        assertTrue(
32907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                mListener.channelListUpdatedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
33007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        assertTrue(
33107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                channelListener.channelChangedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
332816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(1, channelListener.removedChannels.size());
333816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(0, channelListener.updatedChannels.size());
334816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        Channel removedChannel = channelListener.removedChannels.get(0);
335816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(newName, removedChannel.getDisplayName());
336816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(testChannelInfo.number, removedChannel.getDisplayNumber());
337816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        assertEquals(Constants.UNIT_TEST_CHANNEL_COUNT, mChannelDataManager.getChannelCount());
338816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
339816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
340816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private class ChannelInfoWrapper {
341816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public ChannelInfo channelInfo;
342816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public boolean browsable;
343816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public boolean locked;
344816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public ChannelInfoWrapper(ChannelInfo channelInfo) {
345816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            this.channelInfo = channelInfo;
346816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            browsable = true;
347816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            locked = false;
348816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
349816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
350816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
351816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private class FakeContentResolver extends MockContentResolver {
35248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        boolean mNotifyDisabled;
35348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho
354816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
355816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
356816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            super.notifyChange(uri, observer, syncToNetwork);
357816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) {
35848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                Log.d(TAG, "onChanged(uri=" + uri + ", observer=" + observer + ") - Notification "
35948dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                        + (mNotifyDisabled ? "disabled" : "enabled"));
36048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            }
36148dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            if (mNotifyDisabled) {
36248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                return;
363816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
3647d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            // Do not call {@link ContentObserver#onChange} directly to run it on the correct
3657d67089aa1e9aa2123c3cd2f386d7019a1544db1Nick Chalko            // thread.
366816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (observer != null) {
367816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                observer.dispatchChange(false, uri);
368816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } else {
369816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mChannelDataManager.getContentObserver().dispatchChange(false, uri);
370816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
371816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
372816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
373816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
374816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // This implements the minimal methods in content resolver
375816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    // and detailed assumptions are written in each method.
376816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private class FakeContentProvider extends MockContentProvider {
37707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        private final SparseArray<ChannelInfoWrapper> mChannelInfoList = new SparseArray<>();
378816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
379816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public FakeContentProvider(Context context) {
380816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            super(context);
381816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            for (int i = 1; i <= Constants.UNIT_TEST_CHANNEL_COUNT; i++) {
382816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                mChannelInfoList.put(i,
383816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        new ChannelInfoWrapper(ChannelInfo.create(getContext(), i)));
384816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
385816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
386816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
387816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
388816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Implementation of {@link ContentProvider#query}.
389816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * This assumes that {@link ChannelDataManager} queries channels
390816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * with empty {@code selection}. (i.e. channels are always queries for all)
391816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
392816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
393816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public Cursor query(Uri uri, String[] projection, String selection, String[]
394816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                selectionArgs, String sortOrder) {
395816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) {
396816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Log.d(TAG, "dump query");
397816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Log.d(TAG, "  uri=" + uri);
39807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                Log.d(TAG, "  projection=" + Arrays.toString(projection));
39907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko                Log.d(TAG, "  selection=" + selection);
400816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
401816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertChannelUri(uri);
402816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return new FakeCursor(projection);
403816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
404816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
405816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
406816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Implementation of {@link ContentProvider#update}.
407816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * This assumes that {@link ChannelDataManager} update channels
408816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * only for changing browsable and locked.
409816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
410816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
411816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
412816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) Log.d(TAG, "update(uri=" + uri + ", selection=" + selection);
413816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertChannelUri(uri);
414816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            List<Long> channelIds = new ArrayList<>();
415816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            try {
416816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                long channelId = ContentUris.parseId(uri);
417816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                channelIds.add(channelId);
418816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } catch (NumberFormatException e) {
419816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                // Update for multiple channels.
420816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (TextUtils.isEmpty(selection)) {
421816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    for (int i = 0; i < mChannelInfoList.size(); i++) {
422816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        channelIds.add((long) mChannelInfoList.keyAt(i));
423816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
424816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                } else {
425816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    // See {@link Utils#buildSelectionForIds} for the syntax.
426816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    String selectionForId = selection.substring(
427816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                            selection.indexOf("(") + 1, selection.lastIndexOf(")"));
428816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    String[] ids = selectionForId.split(", ");
429816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    if (ids != null) {
430816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        for (String id : ids) {
431816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                            channelIds.add(Long.parseLong(id));
432816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                        }
433816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    }
434816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
435816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
436816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            int updateCount = 0;
437816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            for (long channelId : channelIds) {
438816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                boolean updated = false;
439816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                ChannelInfoWrapper channel = mChannelInfoList.get((int) channelId);
440816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (channel == null) {
441816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return 0;
442816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
443816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (values.containsKey(COLUMN_BROWSABLE)) {
444816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    updated = true;
445816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    channel.browsable = (values.getAsInteger(COLUMN_BROWSABLE) == 1);
446816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
447816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (values.containsKey(COLUMN_LOCKED)) {
448816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    updated = true;
449816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    channel.locked = (values.getAsInteger(COLUMN_LOCKED) == 1);
450816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
451816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                updateCount += updated ? 1 : 0;
452816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
453816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (updateCount > 0) {
454816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (channelIds.size() == 1) {
455816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mContentResolver.notifyChange(uri, null);
456816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                } else {
457816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    mContentResolver.notifyChange(Channels.CONTENT_URI, null);
458816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
459816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            } else {
460816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (DEBUG) {
461816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    Log.d(TAG, "Update to channel(uri=" + uri + ") is ignored for " + values);
462816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
463816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
464816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return updateCount;
465816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
466816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
467816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
468816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Simulates channel data insert.
469816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * This assigns original network ID (the same with channel number) to channel ID.
470816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
471816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void simulateInsert(ChannelInfo testChannelInfo) {
472816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            long channelId = testChannelInfo.originalNetworkId;
473816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mChannelInfoList.put((int) channelId,
474816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    new ChannelInfoWrapper(ChannelInfo.create(getContext(), (int) channelId)));
475816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mContentResolver.notifyChange(TvContract.buildChannelUri(channelId), null);
476816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
477816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
478816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
479816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Simulates channel data delete.
480816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
481816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void simulateDelete(long channelId) {
482816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mChannelInfoList.remove((int) channelId);
483816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mContentResolver.notifyChange(TvContract.buildChannelUri(channelId), null);
484816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
485816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
486816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        /**
487816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         * Simulates channel data update.
488816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko         */
489816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void simulateUpdate(long channelId, String newName) {
490816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            ChannelInfoWrapper channel = mChannelInfoList.get((int) channelId);
491816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            ChannelInfo.Builder builder = new ChannelInfo.Builder(channel.channelInfo);
492816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            builder.setName(newName);
493816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channel.channelInfo = builder.build();
494816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mContentResolver.notifyChange(TvContract.buildChannelUri(channelId), null);
495816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
496816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
497816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        private void assertChannelUri(Uri uri) {
498816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            assertTrue("Uri(" + uri + ") isn't channel uri",
499816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    uri.toString().startsWith(Channels.CONTENT_URI.toString()));
500816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
501816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
502816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void clear() {
503816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mChannelInfoList.clear();
504816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
505816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
506816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public ChannelInfoWrapper get(int position) {
507816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return mChannelInfoList.get(mChannelInfoList.keyAt(position));
508816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
509816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
510816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public int getCount() {
511816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return mChannelInfoList.size();
512816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
513816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
514816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public long keyAt(int position) {
515816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return mChannelInfoList.keyAt(position);
516816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
517816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
518816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
519816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private class FakeCursor extends MockCursor {
52007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        private final String[] ALL_COLUMNS =  {
521816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Channels._ID,
522816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Channels.COLUMN_DISPLAY_NAME,
523816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Channels.COLUMN_DISPLAY_NUMBER,
524816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Channels.COLUMN_INPUT_ID,
525816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Channels.COLUMN_VIDEO_FORMAT,
526816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Channels.COLUMN_ORIGINAL_NETWORK_ID,
527816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                COLUMN_BROWSABLE,
528816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                COLUMN_LOCKED};
52907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        private final String[] mColumns;
530816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        private int mPosition;
531816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
532816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public FakeCursor(String[] columns) {
533816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mColumns = (columns == null) ? ALL_COLUMNS : columns;
534816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            mPosition = -1;
535816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
536816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
537816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
538816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public String getColumnName(int columnIndex) {
539816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return mColumns[columnIndex];
540816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
541816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
542816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
543816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public int getColumnIndex(String columnName) {
544816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            for (int i = 0; i < mColumns.length; i++) {
545816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                if (mColumns[i].equalsIgnoreCase(columnName)) {
546816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return i;
547816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                }
548816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
549816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return -1;
550816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
551816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
552816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
553816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public long getLong(int columnIndex) {
554816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            String columnName = getColumnName(columnIndex);
555816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (columnName) {
556816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case Channels._ID:
557816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return mContentProvider.keyAt(mPosition);
558816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
559816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) {
560816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Log.d(TAG, "Column (" + columnName + ") is ignored in getLong()");
561816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
562816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return 0;
563816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
564816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
565816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
566816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public String getString(int columnIndex) {
567816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            String columnName = getColumnName(columnIndex);
568816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            ChannelInfoWrapper channel = mContentProvider.get(mPosition);
569816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (columnName) {
570816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case Channels.COLUMN_DISPLAY_NAME:
571816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return channel.channelInfo.name;
572816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case Channels.COLUMN_DISPLAY_NUMBER:
573816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return channel.channelInfo.number;
574816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case Channels.COLUMN_INPUT_ID:
575816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return DUMMY_INPUT_ID;
576816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case Channels.COLUMN_VIDEO_FORMAT:
577816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return channel.channelInfo.getVideoFormat();
578816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
579816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) {
580816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Log.d(TAG, "Column (" + columnName + ") is ignored in getString()");
581816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
582816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return null;
583816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
584816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
585816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
586816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public int getInt(int columnIndex) {
587816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            String columnName = getColumnName(columnIndex);
588816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            ChannelInfoWrapper channel = mContentProvider.get(mPosition);
589816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            switch (columnName) {
590816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case Channels.COLUMN_ORIGINAL_NETWORK_ID:
591816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return channel.channelInfo.originalNetworkId;
592816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case COLUMN_BROWSABLE:
593816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return channel.browsable ? 1 : 0;
594816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                case COLUMN_LOCKED:
595816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                    return channel.locked ? 1 : 0;
596816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
597816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            if (DEBUG) {
598816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko                Log.d(TAG, "Column (" + columnName + ") is ignored in getInt()");
599816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            }
600816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return 0;
601816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
602816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
603816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
604816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public int getCount() {
605816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return mContentProvider.getCount();
606816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
607816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
608816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
609816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public boolean moveToNext() {
610816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            return ++mPosition < mContentProvider.getCount();
611816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
612816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
613816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
614816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void close() {
615816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            // No-op.
616816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
617816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
618816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
619816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private class TestChannelDataManagerListener implements ChannelDataManager.Listener {
620816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public CountDownLatch loadFinishedLatch = new CountDownLatch(1);
62107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        public CountDownLatch channelListUpdatedLatch = new CountDownLatch(1);
622816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public boolean channelBrowsableChangedCalled;
623816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
624816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
625816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void onLoadFinished() {
626816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            loadFinishedLatch.countDown();
627816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
628816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
629816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
630816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void onChannelListUpdated() {
63107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko            channelListUpdatedLatch.countDown();
632816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
633816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
634816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
635816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void onChannelBrowsableChanged() {
636816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channelBrowsableChangedCalled = true;
637816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
638816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
639816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void reset() {
640816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            loadFinishedLatch = new CountDownLatch(1);
64107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko            channelListUpdatedLatch = new CountDownLatch(1);
642816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channelBrowsableChangedCalled = false;
643816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
644816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
645816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
646816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    private class TestChannelDataManagerChannelListener
647816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            implements ChannelDataManager.ChannelListener {
648816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public CountDownLatch channelChangedLatch = new CountDownLatch(1);
64907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        public final List<Channel> removedChannels = new ArrayList<>();
65007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        public final List<Channel> updatedChannels = new ArrayList<>();
651816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
652816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
653816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void onChannelRemoved(Channel channel) {
654816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            removedChannels.add(channel);
655816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channelChangedLatch.countDown();
656816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
657816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
658816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        @Override
659816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void onChannelUpdated(Channel channel) {
660816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            updatedChannels.add(channel);
661816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channelChangedLatch.countDown();
662816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
663816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko
664816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        public void reset() {
665816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            channelChangedLatch = new CountDownLatch(1);
666816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            removedChannels.clear();
667816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko            updatedChannels.clear();
668816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko        }
669816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko    }
670816a4be1a0f34f6a48877c8afd3dbbca19eac435Nick Chalko}
671