/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.tv.cts;

import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.tv.TvContentRating;
import android.media.tv.TvContract;
import android.media.tv.TvContract.Channels;
import android.media.tv.TvContract.PreviewPrograms;
import android.media.tv.TvContract.Programs;
import android.media.tv.TvContract.Programs.Genres;
import android.media.tv.TvContract.RecordedPrograms;
import android.media.tv.TvContract.WatchNextPrograms;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.tv.cts.R;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;

/**
 * Test for {@link android.media.tv.TvContract}.
 */
public class TvContractTest extends AndroidTestCase {
    private static final String[] CHANNELS_PROJECTION = {
        Channels._ID,
        Channels.COLUMN_INPUT_ID,
        Channels.COLUMN_TYPE,
        Channels.COLUMN_SERVICE_TYPE,
        Channels.COLUMN_ORIGINAL_NETWORK_ID,
        Channels.COLUMN_TRANSPORT_STREAM_ID,
        Channels.COLUMN_SERVICE_ID,
        Channels.COLUMN_DISPLAY_NUMBER,
        Channels.COLUMN_DISPLAY_NAME,
        Channels.COLUMN_NETWORK_AFFILIATION,
        Channels.COLUMN_DESCRIPTION,
        Channels.COLUMN_VIDEO_FORMAT,
        Channels.COLUMN_INTERNAL_PROVIDER_DATA,
        Channels.COLUMN_VERSION_NUMBER,
        Channels.COLUMN_INTERNAL_PROVIDER_ID,
    };

    private static final String[] PROGRAMS_PROJECTION = {
        Programs._ID,
        Programs.COLUMN_CHANNEL_ID,
        Programs.COLUMN_TITLE,
        Programs.COLUMN_SEASON_DISPLAY_NUMBER,
        Programs.COLUMN_SEASON_TITLE,
        Programs.COLUMN_EPISODE_DISPLAY_NUMBER,
        Programs.COLUMN_EPISODE_TITLE,
        Programs.COLUMN_START_TIME_UTC_MILLIS,
        Programs.COLUMN_END_TIME_UTC_MILLIS,
        Programs.COLUMN_BROADCAST_GENRE,
        Programs.COLUMN_CANONICAL_GENRE,
        Programs.COLUMN_SHORT_DESCRIPTION,
        Programs.COLUMN_LONG_DESCRIPTION,
        Programs.COLUMN_VIDEO_WIDTH,
        Programs.COLUMN_VIDEO_HEIGHT,
        Programs.COLUMN_AUDIO_LANGUAGE,
        Programs.COLUMN_CONTENT_RATING,
        Programs.COLUMN_POSTER_ART_URI,
        Programs.COLUMN_THUMBNAIL_URI,
        Programs.COLUMN_INTERNAL_PROVIDER_DATA,
        Programs.COLUMN_VERSION_NUMBER,
    };

    private static long OPERATION_TIME = 1000l;

    private static final String ENCODED_GENRE_STRING = Genres.ANIMAL_WILDLIFE + "," + Genres.COMEDY
            + "," + Genres.DRAMA + "," + Genres.EDUCATION + "," + Genres.FAMILY_KIDS + ","
            + Genres.GAMING + "," + Genres.MOVIES + "," + Genres.NEWS + "," + Genres.SHOPPING + ","
            + Genres.SPORTS + "," + Genres.TRAVEL;

    // Delimiter for genre.
    private static final String DELIMITER = ",";
    private static final String EMPTY_GENRE = "";
    private static final String COMMA = ",";
    private static final String COMMA_ENCODED = "\",";
    private static final String QUOTE = "\"";
    private static final String QUOTE_ENCODED = "\"\"";
    private static final String WHITE_SPACES = " \r \n \t \f ";

    private static final String PARAM_CANONICAL_GENRE = "canonical_genre";
    private static final String[] NON_EXISTING_COLUMN_NAMES =
            {"non_existing_column", "another non-existing column --"};

    private String mInputId;
    private ContentResolver mContentResolver;
    private Uri mChannelsUri;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        mInputId = TvContract.buildInputId(
                new ComponentName(getContext(), StubTunerTvInputService.class));
        mContentResolver = getContext().getContentResolver();
        mChannelsUri = TvContract.buildChannelsUriForInput(mInputId);
    }

    @Override
    protected void tearDown() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            super.tearDown();
            return;
        }
        mContentResolver.delete(Channels.CONTENT_URI, null, null);
        mContentResolver.delete(RecordedPrograms.CONTENT_URI, null, null);
        mContentResolver.delete(WatchNextPrograms.CONTENT_URI, null, null);
        super.tearDown();
    }

    private static ContentValues createDummyChannelValues(String inputId, boolean preview) {
        ContentValues values = new ContentValues();
        values.put(Channels.COLUMN_INPUT_ID, inputId);
        values.put(Channels.COLUMN_INTERNAL_PROVIDER_ID, "ID-4321");
        values.put(Channels.COLUMN_TYPE, preview ? Channels.TYPE_PREVIEW : Channels.TYPE_OTHER);
        values.put(Channels.COLUMN_SERVICE_TYPE, Channels.SERVICE_TYPE_AUDIO_VIDEO);
        values.put(Channels.COLUMN_DISPLAY_NUMBER, "1");
        values.put(Channels.COLUMN_VIDEO_FORMAT, Channels.VIDEO_FORMAT_480P);

        return values;
    }

    private static ContentValues createDummyProgramValues(long channelId) {
        ContentValues values = new ContentValues();
        values.put(Programs.COLUMN_CHANNEL_ID, channelId);
        values.put(Programs.COLUMN_EPISODE_DISPLAY_NUMBER , "1A");
        values.put(Programs.COLUMN_EPISODE_TITLE, "episode_title");
        values.put(Programs.COLUMN_SEASON_DISPLAY_NUMBER , "2B");
        values.put(Programs.COLUMN_SEASON_TITLE, "season_title");
        values.put(Programs.COLUMN_CANONICAL_GENRE, Programs.Genres.encode(
                Programs.Genres.MOVIES, Programs.Genres.DRAMA));
        TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
                "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
        values.put(Programs.COLUMN_CONTENT_RATING, rating.flattenToString());
        values.put(Programs.COLUMN_REVIEW_RATING_STYLE,
                RecordedPrograms.REVIEW_RATING_STYLE_STARS);
        values.put(Programs.COLUMN_REVIEW_RATING, "4.5");

        return values;
    }

    private static ContentValues createDummyPreviewProgramValues(long channelId) {
        ContentValues values = createDummyBasePreviewProgramValues();
        values.put(PreviewPrograms.COLUMN_CHANNEL_ID, channelId);
        values.put(PreviewPrograms.COLUMN_WEIGHT, 100);
        return values;
    }

    private static ContentValues createDummyWatchNextProgramValues() {
        ContentValues values = createDummyBasePreviewProgramValues();
        values.put(WatchNextPrograms.COLUMN_WATCH_NEXT_TYPE,
                WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE);
        values.put(WatchNextPrograms.COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS,
                System.currentTimeMillis());
        return values;
    }

    private static ContentValues createDummyBasePreviewProgramValues() {
        ContentValues values = new ContentValues();
        values.put(PreviewPrograms.COLUMN_INTERNAL_PROVIDER_ID, "ID-4321");
        values.put(PreviewPrograms.COLUMN_PREVIEW_VIDEO_URI, "http://test.com/preview.mp4");
        values.put(PreviewPrograms.COLUMN_LAST_PLAYBACK_POSITION_MILLIS, 5000);
        values.put(PreviewPrograms.COLUMN_DURATION_MILLIS, 60000);
        values.put(PreviewPrograms.COLUMN_INTENT_URI, "intent_for_video");
        values.put(PreviewPrograms.COLUMN_TITLE, "program_title");
        values.put(PreviewPrograms.COLUMN_SHORT_DESCRIPTION, "short_description");
        values.put(PreviewPrograms.COLUMN_EPISODE_DISPLAY_NUMBER , "1A");
        values.put(PreviewPrograms.COLUMN_EPISODE_TITLE, "episode_title");
        values.put(PreviewPrograms.COLUMN_SEASON_DISPLAY_NUMBER , "2B");
        values.put(PreviewPrograms.COLUMN_SEASON_TITLE, "season_title");
        values.put(PreviewPrograms.COLUMN_CANONICAL_GENRE, Programs.Genres.encode(
                Programs.Genres.SPORTS, Programs.Genres.DRAMA));
        TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
                "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
        values.put(PreviewPrograms.COLUMN_CONTENT_RATING, rating.flattenToString());
        values.put(PreviewPrograms.COLUMN_TYPE, PreviewPrograms.TYPE_MOVIE);
        values.put(PreviewPrograms.COLUMN_POSTER_ART_URI, "http://foo.com/artwork.png");
        values.put(PreviewPrograms.COLUMN_POSTER_ART_ASPECT_RATIO,
                PreviewPrograms.ASPECT_RATIO_2_3);
        values.put(PreviewPrograms.COLUMN_THUMBNAIL_URI, "http://foo.com/thumbnail.jpg");
        values.put(PreviewPrograms.COLUMN_THUMBNAIL_ASPECT_RATIO,
                PreviewPrograms.ASPECT_RATIO_16_9);
        values.put(PreviewPrograms.COLUMN_LOGO_URI, "http://foo.com/logo.jpg");
        values.put(PreviewPrograms.COLUMN_AVAILABILITY, PreviewPrograms.AVAILABILITY_AVAILABLE);
        values.put(PreviewPrograms.COLUMN_STARTING_PRICE, "10.99 USD");
        values.put(PreviewPrograms.COLUMN_OFFER_PRICE, "3.99 USD");
        values.put(PreviewPrograms.COLUMN_RELEASE_DATE, "1985");
        values.put(PreviewPrograms.COLUMN_ITEM_COUNT, 1);
        values.put(PreviewPrograms.COLUMN_LIVE, 0);
        values.put(PreviewPrograms.COLUMN_INTERACTION_TYPE, PreviewPrograms.INTERACTION_TYPE_LIKES);
        values.put(PreviewPrograms.COLUMN_INTERACTION_COUNT, 4000);
        values.put(PreviewPrograms.COLUMN_AUTHOR, "author_name1");
        values.put(PreviewPrograms.COLUMN_REVIEW_RATING_STYLE,
                PreviewPrograms.REVIEW_RATING_STYLE_STARS);
        values.put(PreviewPrograms.COLUMN_REVIEW_RATING, "4.5");
        values.put(WatchNextPrograms.COLUMN_CONTENT_ID, "CID-125-6335");

        return values;
    }


    private static ContentValues createDummyRecordedProgramValues(String inputId, long channelId) {
        ContentValues values = new ContentValues();
        values.put(RecordedPrograms.COLUMN_INPUT_ID, inputId);
        values.put(RecordedPrograms.COLUMN_CHANNEL_ID, channelId);
        values.put(RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER , "3B");
        values.put(RecordedPrograms.COLUMN_SEASON_TITLE, "season_title");
        values.put(RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER , "2A");
        values.put(RecordedPrograms.COLUMN_EPISODE_TITLE, "episode_title");
        values.put(RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS, 1000);
        values.put(RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, 2000);
        values.put(RecordedPrograms.COLUMN_CANONICAL_GENRE,
                Programs.Genres.encode(Programs.Genres.MOVIES, Programs.Genres.DRAMA));
        values.put(RecordedPrograms.COLUMN_SHORT_DESCRIPTION, "short_description");
        values.put(RecordedPrograms.COLUMN_LONG_DESCRIPTION, "long_description");
        values.put(RecordedPrograms.COLUMN_VIDEO_WIDTH, 1920);
        values.put(RecordedPrograms.COLUMN_VIDEO_HEIGHT, 1080);
        values.put(RecordedPrograms.COLUMN_AUDIO_LANGUAGE, "en");
        TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
                "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
        values.put(RecordedPrograms.COLUMN_CONTENT_RATING, rating.flattenToString());
        values.put(RecordedPrograms.COLUMN_POSTER_ART_URI, "http://foo.com/artwork.png");
        values.put(RecordedPrograms.COLUMN_THUMBNAIL_URI, "http://foo.com/thumbnail.jpg");
        values.put(RecordedPrograms.COLUMN_SEARCHABLE, 1);
        values.put(RecordedPrograms.COLUMN_RECORDING_DATA_URI, "file:///sdcard/foo/");
        values.put(RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, 1024 * 1024);
        values.put(RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS, 60 * 60 * 1000);
        values.put(RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS, 1454480880L);
        values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
                "internal_provider_data".getBytes());
        values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1, 4);
        values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2, 3);
        values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3, 2);
        values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4, 1);
        values.put(RecordedPrograms.COLUMN_REVIEW_RATING_STYLE,
                RecordedPrograms.REVIEW_RATING_STYLE_STARS);
        values.put(RecordedPrograms.COLUMN_REVIEW_RATING, "4.5");

        return values;
    }

    private static void verifyStringColumn(Cursor cursor, ContentValues expectedValues,
            String columnName) {
        if (expectedValues.containsKey(columnName)) {
            assertEquals(expectedValues.getAsString(columnName),
                    cursor.getString(cursor.getColumnIndex(columnName)));
        }
    }

    private static void verifyIntegerColumn(Cursor cursor, ContentValues expectedValues,
            String columnName) {
        if (expectedValues.containsKey(columnName)) {
            assertEquals(expectedValues.getAsInteger(columnName).intValue(),
                    cursor.getInt(cursor.getColumnIndex(columnName)));
        }
    }

    private static void verifyLongColumn(Cursor cursor, ContentValues expectedValues,
            String columnName) {
        if (expectedValues.containsKey(columnName)) {
            assertEquals(expectedValues.getAsLong(columnName).longValue(),
                    cursor.getLong(cursor.getColumnIndex(columnName)));
        }
    }

    private static void verifyBlobColumn(Cursor cursor, ContentValues expectedValues,
            String columnName) {
        if (expectedValues.containsKey(columnName)) {
            byte[] expected = expectedValues.getAsByteArray(columnName);
            byte[] actual = cursor.getBlob(cursor.getColumnIndex(columnName));
            assertEquals(expected.length, actual.length);
            for (int i = 0; i < expected.length; ++i) {
                assertEquals(expected[i], actual[i]);
            }
        }
    }

    private void verifyChannel(Uri channelUri, ContentValues expectedValues, long channelId) {
        verifyChannel(channelUri, expectedValues, channelId, true);
    }

    private void verifyChannel(Uri channelUri, ContentValues expectedValues, long channelId,
            boolean verifyInputId) {
        try (Cursor cursor = mContentResolver.query(
                channelUri, CHANNELS_PROJECTION, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());
            assertEquals(channelId, cursor.getLong(cursor.getColumnIndex(Channels._ID)));
            if (verifyInputId) {
                verifyStringColumn(cursor, expectedValues, Channels.COLUMN_INPUT_ID);
            }
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_TYPE);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_SERVICE_TYPE);
            verifyIntegerColumn(cursor, expectedValues, Channels.COLUMN_ORIGINAL_NETWORK_ID);
            verifyIntegerColumn(cursor, expectedValues, Channels.COLUMN_TRANSPORT_STREAM_ID);
            verifyIntegerColumn(cursor, expectedValues, Channels.COLUMN_SERVICE_ID);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_DISPLAY_NAME);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_NETWORK_AFFILIATION);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_DESCRIPTION);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_VIDEO_FORMAT);
            verifyStringColumn(cursor, expectedValues, Channels.COLUMN_INTERNAL_PROVIDER_ID);
            verifyBlobColumn(cursor, expectedValues, Channels.COLUMN_INTERNAL_PROVIDER_DATA);
            verifyIntegerColumn(cursor, expectedValues, Channels.COLUMN_VERSION_NUMBER);
        }
    }

    private void verifyNonExistingColumn(Uri channelUri, long channelId) {
        String[] projection = {
                Channels._ID,
                NON_EXISTING_COLUMN_NAMES[0],
                NON_EXISTING_COLUMN_NAMES[1]
        };
        try (Cursor cursor = mContentResolver.query(channelUri, projection, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());
            assertEquals(channelId, cursor.getLong(0));
            assertEquals(NON_EXISTING_COLUMN_NAMES[0], cursor.getColumnName(1));
            assertNull(cursor.getString(1));
            assertEquals(0, cursor.getInt(1));
            assertEquals(NON_EXISTING_COLUMN_NAMES[1], cursor.getColumnName(2));
            assertNull(cursor.getString(2));
            assertEquals(0, cursor.getInt(2));
        }
    }

    public void testChannelsTable() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Test: insert
        ContentValues values = createDummyChannelValues(mInputId, false);

        Uri rowUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(rowUri);
        Uri channelUri = TvContract.buildChannelUri(channelId);
        verifyChannel(channelUri, values, channelId);

        // Test: update
        values.put(Channels.COLUMN_DISPLAY_NUMBER, "1-1");
        values.put(Channels.COLUMN_DISPLAY_NAME, "One dash one");
        values.put(Channels.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());

        mContentResolver.update(channelUri, values, null, null);
        verifyChannel(channelUri, values, channelId);

        // Test: delete
        mContentResolver.delete(mChannelsUri, null, null);
        try (Cursor cursor = mContentResolver.query(
                mChannelsUri, CHANNELS_PROJECTION, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void testChannelsTableForModifyChannelType() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        ContentValues values = createDummyChannelValues(mInputId, true);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);

        // Test: try to modify channel type should fail
        values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
        values.put(Channels.COLUMN_DISPLAY_NAME, "One dash one");
        int result = mContentResolver.update(channelUri, values, null, null);
        assertEquals(0, result);

        // Test: update with same channel type should succeed
        values.put(Channels.COLUMN_TYPE, Channels.TYPE_PREVIEW);
        result = mContentResolver.update(channelUri, values, null, null);
        assertEquals(1, result);
        verifyChannel(channelUri, values, channelId);

        // Test: update channel type for all channels should fail
        result = mContentResolver.update(Channels.CONTENT_URI, values, null, null);
        assertEquals(0, result);
    }

    public void testChannelsTableForInputId() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Non-preview channels should not be inserted without input ID
        ContentValues values = createDummyChannelValues(mInputId, false);
        values.remove(Channels.COLUMN_INPUT_ID);
        Uri rowUri = mContentResolver.insert(Channels.CONTENT_URI, values);
        assertNull(rowUri);

        // Non-preview channels should not be inserted with null input ID
        values.putNull(Channels.COLUMN_INPUT_ID);
        rowUri = mContentResolver.insert(Channels.CONTENT_URI, values);
        assertNull(rowUri);

        // Preview channels can be inserted with null input ID
        values.put(Channels.COLUMN_TYPE, Channels.TYPE_PREVIEW);
        rowUri = mContentResolver.insert(Channels.CONTENT_URI, values);
        long channelId = ContentUris.parseId(rowUri);
        Uri channelUri = TvContract.buildChannelUri(channelId);
        verifyChannel(channelUri, values, channelId, false);

        // Preview channels can be inserted without input ID
        values.remove(Channels.COLUMN_INPUT_ID);
        rowUri = mContentResolver.insert(Channels.CONTENT_URI, values);
        channelId = ContentUris.parseId(rowUri);
        channelUri = TvContract.buildChannelUri(channelId);
        verifyChannel(channelUri, values, channelId, false);
    }

    public void testChannelsTableForModifyIdAndPackageName() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        ContentValues baseValues = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(mChannelsUri, baseValues);
        long channelId = ContentUris.parseId(channelUri);

        ContentValues values = new ContentValues(baseValues);
        values.put(Channels._ID, channelId);
        int result = mContentResolver.update(channelUri, values, null, null);
        assertEquals(1, result);
        values.put(Channels._ID, channelId + 1);
        try {
            mContentResolver.update(channelUri, values, null, null);
            fail("Channels._ID should not be changed.");
        } catch (Exception e) {
            // Expected.
        }

        values = new ContentValues(baseValues);
        values.put(Channels.COLUMN_PACKAGE_NAME, getContext().getPackageName());
        result = mContentResolver.update(channelUri, values, null, null);
        assertEquals(1, result);
        values.put(Channels.COLUMN_PACKAGE_NAME, "");
        try {
            mContentResolver.update(channelUri, values, null, null);
            fail("Channels.COLUMN_PACKAGE_NAME should not be changed.");
        } catch (Exception e) {
            // Expected.
        }
    }

    public void testChannelsTableForIllegalAccess() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        ContentValues baseValues = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(mChannelsUri, baseValues);

        // Test: insert
        ContentValues values = new ContentValues(baseValues);
        values.put(Channels.COLUMN_BROWSABLE, 1);
        try {
            mContentResolver.insert(mChannelsUri, values);
            fail("Channels.COLUMN_BROWSABLE should be read-only.");
        } catch (Exception e) {
            // Expected.
        }
        values = new ContentValues(baseValues);
        values.put(Channels.COLUMN_LOCKED, 1);
        try {
            mContentResolver.insert(mChannelsUri, values);
            fail("Channels.COLUMN_LOCKED should be read-only.");
        } catch (Exception e) {
            // Expected.
        }

        // Test: update
        values = new ContentValues(baseValues);
        values.put(Channels.COLUMN_BROWSABLE, 1);
        try {
            mContentResolver.update(channelUri, values, null, null);
            fail("Channels.COLUMN_BROWSABLE should be read-only.");
        } catch (Exception e) {
            // Expected.
        }
        values = new ContentValues(baseValues);
        values.put(Channels.COLUMN_LOCKED, 1);
        try {
            mContentResolver.update(channelUri, values, null, null);
            fail("Channels.COLUMN_LOCKED should be read-only.");
        } catch (Exception e) {
            // Expected.
        }

        // Test: query
        try (Cursor cursor = mContentResolver.query(
                channelUri,
                new String[]{ Channels.COLUMN_BROWSABLE }, null, null, null)) {
            // Channels.COLUMN_BROWSABLE should be readable from application.
            assertEquals(1, cursor.getCount());
        }
        try (Cursor cursor = mContentResolver.query(
                channelUri,
                new String[]{ Channels.COLUMN_LOCKED }, null, null, null)) {
            // Channels.COLUMN_LOCKED should be readable from application.
            assertEquals(1, cursor.getCount());
        }

        mContentResolver.delete(mChannelsUri, null, null);
        try (Cursor cursor = mContentResolver.query(
                mChannelsUri, CHANNELS_PROJECTION, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void testChannelsTableForNonExistingColumns() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        ContentValues values = createDummyChannelValues(mInputId, false);
        values.put(NON_EXISTING_COLUMN_NAMES[0], "dummy value 0");
        values.put(NON_EXISTING_COLUMN_NAMES[1], "dummy value 1");
        Uri rowUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(rowUri);
        Uri channelUri = TvContract.buildChannelUri(channelId);
        verifyChannel(channelUri, values, channelId);
        verifyNonExistingColumn(channelUri, channelId);

        // Test: update
        mContentResolver.update(channelUri, values, null, null);
        verifyChannel(channelUri, values, channelId);
        verifyNonExistingColumn(channelUri, channelId);

        // Test: delete
        mContentResolver.delete(mChannelsUri, null, null);
        try (Cursor cursor = mContentResolver.query(
                mChannelsUri, CHANNELS_PROJECTION, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    private void verifyProgram(Uri programUri, ContentValues expectedValues, long programId) {
        try (Cursor cursor = mContentResolver.query(
                programUri, null, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());
            assertEquals(programId, cursor.getLong(cursor.getColumnIndex(Programs._ID)));
            verifyLongColumn(cursor, expectedValues, Programs.COLUMN_CHANNEL_ID);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_TITLE);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_SEASON_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_SEASON_TITLE);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_EPISODE_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_EPISODE_TITLE);
            verifyLongColumn(cursor, expectedValues, Programs.COLUMN_START_TIME_UTC_MILLIS);
            verifyLongColumn(cursor, expectedValues, Programs.COLUMN_END_TIME_UTC_MILLIS);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_BROADCAST_GENRE);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_CANONICAL_GENRE);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_SHORT_DESCRIPTION);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_LONG_DESCRIPTION);
            verifyIntegerColumn(cursor, expectedValues, Programs.COLUMN_VIDEO_WIDTH);
            verifyIntegerColumn(cursor, expectedValues, Programs.COLUMN_VIDEO_HEIGHT);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_AUDIO_LANGUAGE);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_CONTENT_RATING);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_POSTER_ART_URI);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_THUMBNAIL_URI);
            verifyBlobColumn(cursor, expectedValues, Programs.COLUMN_INTERNAL_PROVIDER_DATA);
            verifyIntegerColumn(cursor, expectedValues, Programs.COLUMN_VERSION_NUMBER);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_REVIEW_RATING_STYLE);
            verifyStringColumn(cursor, expectedValues, Programs.COLUMN_REVIEW_RATING);
        }
    }

    private void verifyPreviewProgram(Uri programUri, ContentValues expectedValues,
            long programId) {
        try (Cursor cursor = mContentResolver.query(
                programUri, null, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());
            assertEquals(programId, cursor.getLong(cursor.getColumnIndex(PreviewPrograms._ID)));
            verifyLongColumn(cursor, expectedValues, PreviewPrograms.COLUMN_CHANNEL_ID);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_TITLE);
            verifyStringColumn(cursor, expectedValues,
                    PreviewPrograms.COLUMN_SEASON_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_SEASON_TITLE);
            verifyStringColumn(cursor, expectedValues,
                    PreviewPrograms.COLUMN_EPISODE_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_EPISODE_TITLE);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_CANONICAL_GENRE);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_SHORT_DESCRIPTION);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_LONG_DESCRIPTION);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_VIDEO_WIDTH);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_VIDEO_HEIGHT);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_AUDIO_LANGUAGE);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_CONTENT_RATING);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_POSTER_ART_URI);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_THUMBNAIL_URI);
            verifyBlobColumn(cursor, expectedValues, PreviewPrograms.COLUMN_INTERNAL_PROVIDER_DATA);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_VERSION_NUMBER);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_INTERNAL_PROVIDER_ID);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_PREVIEW_VIDEO_URI);
            verifyIntegerColumn(cursor, expectedValues,
                    PreviewPrograms.COLUMN_LAST_PLAYBACK_POSITION_MILLIS);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_DURATION_MILLIS);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_INTENT_URI);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_WEIGHT);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_TYPE);
            verifyIntegerColumn(cursor, expectedValues,
                    PreviewPrograms.COLUMN_POSTER_ART_ASPECT_RATIO);
            verifyIntegerColumn(cursor, expectedValues,
                    PreviewPrograms.COLUMN_THUMBNAIL_ASPECT_RATIO);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_LOGO_URI);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_AVAILABILITY);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_STARTING_PRICE);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_OFFER_PRICE);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_RELEASE_DATE);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_ITEM_COUNT);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_LIVE);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_INTERACTION_TYPE);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_INTERACTION_COUNT);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_AUTHOR);
            verifyIntegerColumn(cursor, expectedValues, PreviewPrograms.COLUMN_REVIEW_RATING_STYLE);
            verifyStringColumn(cursor, expectedValues, PreviewPrograms.COLUMN_REVIEW_RATING);
        }
    }

    private void verifyWatchNextProgram(Uri programUri, ContentValues expectedValues,
            long programId) {
        verifyPreviewProgram(programUri, expectedValues, programId);
        try (Cursor cursor = mContentResolver.query(programUri, null, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());

            verifyIntegerColumn(cursor, expectedValues, WatchNextPrograms.COLUMN_WATCH_NEXT_TYPE);
            verifyLongColumn(cursor, expectedValues,
                    WatchNextPrograms.COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS);
        }
    }

    private void verifyDeprecatedColumsInProgram(Uri programUri, ContentValues expectedValues) {
        final String[] DEPRECATED_COLUMNS_PROJECTION = {
            Programs.COLUMN_SEASON_NUMBER,
            Programs.COLUMN_EPISODE_NUMBER,
        };
        try (Cursor cursor = mContentResolver.query(
                programUri, DEPRECATED_COLUMNS_PROJECTION, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());
            verifyIntegerColumn(cursor, expectedValues, Programs.COLUMN_SEASON_NUMBER);
            verifyIntegerColumn(cursor, expectedValues, Programs.COLUMN_EPISODE_NUMBER);
        }
    }

    private void verifyLogoIsReadable(Uri logoUri) throws Exception {
        try (AssetFileDescriptor fd = mContentResolver.openAssetFileDescriptor(logoUri, "r")) {
            try (InputStream is = fd.createInputStream()) {
                // Assure that the stream is decodable as a Bitmap.
                BitmapFactory.decodeStream(is);
            }
        }
    }

    public void testChannelLogo() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Set-up: add a channel.
        ContentValues values = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        Uri logoUri = TvContract.buildChannelLogoUri(channelUri);
        Bitmap logo = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.robot);

        // Write
        try (AssetFileDescriptor fd = mContentResolver.openAssetFileDescriptor(logoUri, "w")) {
            try (OutputStream os = fd.createOutputStream()) {
                logo.compress(Bitmap.CompressFormat.PNG, 100, os);
            }
        }

        // Give some time for TvProvider to process the logo.
        Thread.sleep(OPERATION_TIME);

        // Read and verify
        verifyLogoIsReadable(logoUri);

        // Read and verify using alternative logo URI.
        verifyLogoIsReadable(TvContract.buildChannelLogoUri(ContentUris.parseId(channelUri)));
    }

    public void verifyProgramsTable(Uri programsUri, long channelId) {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Test: insert
        ContentValues values = createDummyProgramValues(channelId);

        Uri rowUri = mContentResolver.insert(programsUri, values);
        long programId = ContentUris.parseId(rowUri);
        Uri programUri = TvContract.buildProgramUri(programId);
        verifyProgram(programUri, values, programId);

        // Test: update
        values.put(Programs.COLUMN_TITLE, "new_program_title");
        values.put(Programs.COLUMN_SHORT_DESCRIPTION, "");
        values.put(Programs.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());

        mContentResolver.update(programUri, values, null, null);
        verifyProgram(programUri, values, programId);

        // Test: delete
        mContentResolver.delete(programsUri, null, null);
        try (Cursor cursor = mContentResolver.query(programsUri, null, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void verifyPreviewProgramsTable(Uri previewProgramsUri, long channelId) {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Test: insert
        ContentValues values = createDummyPreviewProgramValues(channelId);

        Uri rowUri = mContentResolver.insert(previewProgramsUri, values);
        long programId = ContentUris.parseId(rowUri);
        Uri programUri = TvContract.buildPreviewProgramUri(programId);
        verifyPreviewProgram(programUri, values, programId);

        values.remove(PreviewPrograms.COLUMN_TYPE);
        try {
            mContentResolver.insert(previewProgramsUri, values);
            fail("Type should be a required column.");
        } catch (IllegalArgumentException e) {
            // Expected.
        }

        // Test: update
        values.put(PreviewPrograms.COLUMN_EPISODE_TITLE, "Sample title");
        values.put(PreviewPrograms.COLUMN_SHORT_DESCRIPTION, "Short description");
        values.put(PreviewPrograms.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());

        mContentResolver.update(programUri, values, null, null);
        verifyPreviewProgram(programUri, values, programId);

        // Test: delete
        mContentResolver.delete(previewProgramsUri, null, null);
        try (Cursor cursor = mContentResolver.query(previewProgramsUri, null, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void verifyWatchNextProgramsTable(Uri watchNextProgramsUri) {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Test: insert
        ContentValues values = createDummyWatchNextProgramValues();

        Uri rowUri = mContentResolver.insert(watchNextProgramsUri, values);
        long programId = ContentUris.parseId(rowUri);
        Uri programUri = TvContract.buildWatchNextProgramUri(programId);
        verifyWatchNextProgram(programUri, values, programId);

        values.remove(WatchNextPrograms.COLUMN_TYPE);
        try {
            mContentResolver.insert(watchNextProgramsUri, values);
            fail("Type should be a required column.");
        } catch (IllegalArgumentException e) {
            // Expected.
        }

        // Test: update
        values.put(WatchNextPrograms.COLUMN_EPISODE_TITLE, "Sample title");
        values.put(WatchNextPrograms.COLUMN_SHORT_DESCRIPTION, "Short description");
        values.put(WatchNextPrograms.COLUMN_CONTENT_ID, "CID-4328-2548");

        mContentResolver.update(programUri, values, null, null);
        verifyWatchNextProgram(programUri, values, programId);

        // Test: delete
        mContentResolver.delete(watchNextProgramsUri, null, null);
        try (Cursor cursor = mContentResolver.query(watchNextProgramsUri, null, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void verifyProgramsTableWithDeprecatedColumns(Uri programsUri, long channelId) {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Test: insert
        ContentValues expected = createDummyProgramValues(channelId);
        expected.put(Programs.COLUMN_SEASON_DISPLAY_NUMBER, "3");
        expected.put(Programs.COLUMN_EPISODE_DISPLAY_NUMBER, "9");

        ContentValues input = new ContentValues(expected);
        input.remove(Programs.COLUMN_SEASON_DISPLAY_NUMBER);
        input.remove(Programs.COLUMN_EPISODE_DISPLAY_NUMBER);
        input.put(Programs.COLUMN_SEASON_NUMBER, 3);
        input.put(Programs.COLUMN_EPISODE_NUMBER, 9);

        Uri rowUri = mContentResolver.insert(programsUri, input);
        long programId = ContentUris.parseId(rowUri);
        Uri programUri = TvContract.buildProgramUri(programId);
        verifyProgram(programUri, expected, programId);
        verifyDeprecatedColumsInProgram(programUri, input);

        // Test: update
        expected.put(Programs.COLUMN_SEASON_DISPLAY_NUMBER, "4");
        expected.put(Programs.COLUMN_EPISODE_DISPLAY_NUMBER, "10");
        input.put(Programs.COLUMN_SEASON_NUMBER, 4);
        input.put(Programs.COLUMN_EPISODE_NUMBER, 10);

        mContentResolver.update(programUri, input, null, null);
        verifyProgram(programUri, expected, programId);
        verifyDeprecatedColumsInProgram(programUri, input);

        // Test: delete
        mContentResolver.delete(programsUri, null, null);
        try (Cursor cursor = mContentResolver.query(
                programsUri, PROGRAMS_PROJECTION, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void testProgramsTable() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Set-up: add a channel.
        ContentValues values = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);

        verifyProgramsTable(TvContract.buildProgramsUriForChannel(channelId), channelId);
        verifyProgramsTable(TvContract.buildProgramsUriForChannel(channelUri), channelId);
        verifyProgramsTableWithDeprecatedColumns(TvContract.buildProgramsUriForChannel(channelId),
                channelId);
        verifyProgramsTableWithDeprecatedColumns(TvContract.buildProgramsUriForChannel(channelUri),
                channelId);
    }

    public void testPreviewProgramsTable() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Set-up: add a preview type channel.
        ContentValues values = createDummyChannelValues(mInputId, true);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);

        verifyPreviewProgramsTable(PreviewPrograms.CONTENT_URI, channelId);
    }

    public void testWatchNextProgramsTable() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        verifyWatchNextProgramsTable(WatchNextPrograms.CONTENT_URI);
    }

    public void testPreviewProgramsTableForIllegalAccess() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Set-up: add a channel and preview program.
        ContentValues values = createDummyChannelValues(mInputId, true);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);
        Uri previewProgramsUri = TvContract.buildPreviewProgramsUriForChannel(channelId);
        values = createDummyPreviewProgramValues(channelId);
        Uri previewProgramUri = mContentResolver.insert(previewProgramsUri, values);

        values.put(PreviewPrograms.COLUMN_BROWSABLE, 1);
        try {
            mContentResolver.insert(previewProgramUri, values);
            fail("PreviewPrograms.COLUMN_BROWSABLE should not be accessible.");
        } catch (Exception e) {
            // Expected.
        }

        mContentResolver.delete(previewProgramUri, null, null);
        try (Cursor cursor = mContentResolver.query(
                previewProgramUri, PROGRAMS_PROJECTION, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void testPreviewProgramsTableForModifyChannelId() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Set-up: add a channel and preview program.
        ContentValues values = createDummyChannelValues(mInputId, true);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);
        Uri previewProgramsUri = TvContract.buildPreviewProgramsUriForChannel(channelId);
        values = createDummyPreviewProgramValues(channelId);
        Uri previewProgramUri = mContentResolver.insert(previewProgramsUri, values);

        // Channel ID cannot be changed
        values.put(PreviewPrograms.COLUMN_ITEM_COUNT, 1);
        values.put(PreviewPrograms.COLUMN_CHANNEL_ID, channelId + 1);
        int result = mContentResolver.update(previewProgramUri, values, null, null);
        assertEquals(0, result);

        // Same Channel ID should not fail updating
        values.put(PreviewPrograms.COLUMN_CHANNEL_ID, channelId);
        result = mContentResolver.update(previewProgramUri, values, null, null);
        assertEquals(1, result);

        // Update without Channel ID should not fail
        values.put(PreviewPrograms.COLUMN_ITEM_COUNT, 2);
        values.remove(PreviewPrograms.COLUMN_CHANNEL_ID);
        result = mContentResolver.update(previewProgramUri, values, null, null);
        assertEquals(1, result);

        // Update channel ID with CONTENT_URI should fail
        values.put(PreviewPrograms.COLUMN_CHANNEL_ID, channelId);
        result = mContentResolver.update(PreviewPrograms.CONTENT_URI, values, null, null);
        assertEquals(0, result);

        mContentResolver.delete(previewProgramUri, null, null);
        try (Cursor cursor = mContentResolver.query(
                previewProgramUri, PROGRAMS_PROJECTION, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    private void verifyOverlap(long startMillis, long endMillis, int expectedCount,
            long channelId, Uri channelUri) {
        try (Cursor cursor = mContentResolver.query(TvContract.buildProgramsUriForChannel(
                channelId, startMillis, endMillis), PROGRAMS_PROJECTION, null, null, null)) {
            assertEquals(expectedCount, cursor.getCount());
        }
        try (Cursor cursor = mContentResolver.query(TvContract.buildProgramsUriForChannel(
                channelUri, startMillis, endMillis), PROGRAMS_PROJECTION, null, null, null)) {
            assertEquals(expectedCount, cursor.getCount());
        }
    }

    public void testProgramsScheduleOverlap() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        final long programStartMillis = 1403712000000l;  // Jun 25 2014 16:00 UTC
        final long programEndMillis = 1403719200000l;  // Jun 25 2014 18:00 UTC
        final long hour = 3600000l;

        // Set-up: add a channel and program.
        ContentValues values = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);
        Uri programsUri = TvContract.buildProgramsUriForChannel(channelId);
        values = createDummyProgramValues(channelId);
        values.put(Programs.COLUMN_START_TIME_UTC_MILLIS, programStartMillis);
        values.put(Programs.COLUMN_END_TIME_UTC_MILLIS, programEndMillis);
        mContentResolver.insert(programsUri, values);

        // Overlap 1: starts early, ends early.
        verifyOverlap(programStartMillis - hour, programEndMillis - hour, 1, channelId, channelUri);

        // Overlap 2: starts early, ends late.
        verifyOverlap(programStartMillis - hour, programEndMillis + hour, 1, channelId, channelUri);

        // Overlap 3: starts early, ends late.
        verifyOverlap(programStartMillis + hour / 2, programEndMillis - hour / 2, 1,
                channelId, channelUri);

        // Overlap 4: starts late, ends late.
        verifyOverlap(programStartMillis + hour, programEndMillis + hour, 1, channelId, channelUri);

        // Non-overlap 1: ends too early.
        verifyOverlap(programStartMillis - hour, programStartMillis - hour / 2, 0,
                channelId, channelUri);

        // Non-overlap 2: starts too late
        verifyOverlap(programEndMillis + hour, programEndMillis + hour * 2, 0,
                channelId, channelUri);
    }

    private void verifyRecordedProgram(Uri recordedProgramUri, ContentValues expectedValues,
                long recordedProgramId) {
        try (Cursor cursor = mContentResolver.query(recordedProgramUri, null, null, null, null)) {
            assertNotNull(cursor);
            assertEquals(cursor.getCount(), 1);
            assertTrue(cursor.moveToNext());
            assertEquals(recordedProgramId, cursor.getLong(cursor.getColumnIndex(
                    RecordedPrograms._ID)));
            verifyLongColumn(cursor, expectedValues, RecordedPrograms.COLUMN_CHANNEL_ID);
            verifyStringColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_SEASON_TITLE);
            verifyStringColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_EPISODE_TITLE);
            verifyLongColumn(cursor, expectedValues, RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS);
            verifyLongColumn(cursor, expectedValues, RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_BROADCAST_GENRE);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_CANONICAL_GENRE);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_SHORT_DESCRIPTION);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_LONG_DESCRIPTION);
            verifyIntegerColumn(cursor, expectedValues, RecordedPrograms.COLUMN_VIDEO_WIDTH);
            verifyIntegerColumn(cursor, expectedValues, RecordedPrograms.COLUMN_VIDEO_HEIGHT);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_AUDIO_LANGUAGE);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_CONTENT_RATING);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_POSTER_ART_URI);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_THUMBNAIL_URI);
            verifyIntegerColumn(cursor, expectedValues, RecordedPrograms.COLUMN_SEARCHABLE);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_RECORDING_DATA_URI);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_RECORDING_DATA_BYTES);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS);
            verifyBlobColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3);
            verifyIntegerColumn(cursor, expectedValues,
                    RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4);
            verifyIntegerColumn(cursor, expectedValues, RecordedPrograms.COLUMN_VERSION_NUMBER);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_REVIEW_RATING_STYLE);
            verifyStringColumn(cursor, expectedValues, RecordedPrograms.COLUMN_REVIEW_RATING);
        }
    }

    private void verifyRecordedProgramsTable(Uri recordedProgramsUri, long channelId) {
        // Test: insert
        ContentValues values = createDummyRecordedProgramValues(mInputId, channelId);

        Uri rowUri = mContentResolver.insert(recordedProgramsUri, values);
        long recordedProgramId = ContentUris.parseId(rowUri);
        Uri recordedProgramUri = TvContract.buildRecordedProgramUri(recordedProgramId);
        verifyRecordedProgram(recordedProgramUri, values, recordedProgramId);

        // Test: update
        values.put(RecordedPrograms.COLUMN_EPISODE_TITLE, "episode_title1");
        values.put(RecordedPrograms.COLUMN_SHORT_DESCRIPTION, "short_description1");
        values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA,
                "internal_provider_data1".getBytes());

        mContentResolver.update(recordedProgramUri, values, null, null);
        verifyRecordedProgram(recordedProgramUri, values, recordedProgramId);

        // Test: delete
        mContentResolver.delete(recordedProgramUri, null, null);
        try (Cursor cursor = mContentResolver.query(recordedProgramsUri, null, null, null, null)) {
            assertEquals(0, cursor.getCount());
        }
    }

    public void testRecordedProgramsTable() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // Set-up: add a channel.
        ContentValues values = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        long channelId = ContentUris.parseId(channelUri);

        verifyRecordedProgramsTable(RecordedPrograms.CONTENT_URI, channelId);
    }

    private void verifyQueryWithSortOrder(Uri uri, final String[] projection,
            String sortOrder) throws Exception {
        try {
            getContext().getContentResolver().query(uri, projection, null, null, sortOrder);
        } catch (SecurityException e) {
            fail("Setting sort order shoud be allowed for " + uri);
        }
    }

    private void verifyQueryWithSelection(Uri uri, final String[] projection,
            String selection) throws Exception {
        try {
            getContext().getContentResolver().query(uri, projection, selection, null, null);
            fail("Setting selection should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
        } catch (SecurityException e) {
            // Expected exception
        }
    }

    private void verifyUpdateWithSelection(Uri uri, String selection) throws Exception {
        try {
            ContentValues values = new ContentValues();
            getContext().getContentResolver().update(uri, values, selection, null);
            fail("Setting selection should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
        } catch (SecurityException e) {
            // Expected exception
        }
    }

    private void verifyDeleteWithSelection(Uri uri, String selection) throws Exception {
        try {
            getContext().getContentResolver().delete(uri, selection, null);
            fail("Setting selection should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
        } catch (SecurityException e) {
            // Expected exception
        }
    }

    public void testAllEpgPermissionBlocksSortOrderOnQuery_Channels() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        final String[] projection = { Channels._ID };
        verifyQueryWithSortOrder(Channels.CONTENT_URI, projection, Channels._ID + " ASC");
    }

    public void testAllEpgPermissionBlocksSelectionOnQuery_Channels() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        final String[] projection = { Channels._ID };
        verifyQueryWithSelection(Channels.CONTENT_URI, projection, Channels._ID + ">0");
    }

    public void testAllEpgPermissionBlocksSelectionOnUpdate_Channels() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        verifyUpdateWithSelection(Channels.CONTENT_URI, Channels._ID + ">0");
    }

    public void testAllEpgPermissionBlocksSelectionOnDelete_Channels() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        verifyDeleteWithSelection(Channels.CONTENT_URI, Channels._ID + ">0");
    }

    public void testAllEpgPermissionBlocksSortOrderOnQuery_Programs() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        final String[] projection = { Programs._ID };
        verifyQueryWithSortOrder(Programs.CONTENT_URI, projection, Programs._ID + " ASC");
    }

    public void testAllEpgPermissionBlocksSelectionOnQuery_Programs() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        final String[] projection = { Channels._ID };
        verifyQueryWithSelection(Programs.CONTENT_URI, projection, Programs._ID + ">0");
    }

    public void testAllEpgPermissionBlocksSelectionOnUpdate_Programs() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        verifyUpdateWithSelection(Programs.CONTENT_URI, Programs._ID + ">0");
    }

    public void testAllEpgPermissionBlocksSelectionOnDelete_Programs() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        verifyDeleteWithSelection(Programs.CONTENT_URI, Programs._ID + ">0");
    }

    public void testDefaultValues() throws Exception {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        ContentValues values = new ContentValues();
        values.put(Channels.COLUMN_INPUT_ID, mInputId);
        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
        assertNotNull(channelUri);
        try (Cursor cursor = mContentResolver.query(
                channelUri, CHANNELS_PROJECTION, null, null, null)) {
            cursor.moveToNext();
            assertEquals(Channels.TYPE_OTHER,
                    cursor.getString(cursor.getColumnIndex(Channels.COLUMN_TYPE)));
            assertEquals(Channels.SERVICE_TYPE_AUDIO_VIDEO,
                    cursor.getString(cursor.getColumnIndex(Channels.COLUMN_SERVICE_TYPE)));
        }
        values.clear();
    }

    public void testChannelsGetVideoResolution() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        assertEquals(Channels.VIDEO_RESOLUTION_SD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_480I));
        assertEquals(Channels.VIDEO_RESOLUTION_ED, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_480P));
        assertEquals(Channels.VIDEO_RESOLUTION_SD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_576I));
        assertEquals(Channels.VIDEO_RESOLUTION_ED, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_576P));
        assertEquals(Channels.VIDEO_RESOLUTION_HD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_720P));
        assertEquals(Channels.VIDEO_RESOLUTION_HD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_1080I));
        assertEquals(Channels.VIDEO_RESOLUTION_FHD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_1080P));
        assertEquals(Channels.VIDEO_RESOLUTION_UHD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_2160P));
        assertEquals(Channels.VIDEO_RESOLUTION_UHD, Channels.getVideoResolution(
                Channels.VIDEO_FORMAT_4320P));
        assertEquals(null, Channels.getVideoResolution("Unknown format"));
    }

    public void testProgramsGenresDecode() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        List genres = Arrays.asList(Genres.decode(ENCODED_GENRE_STRING));
        assertEquals(11, genres.size());
        assertTrue(genres.contains(Genres.ANIMAL_WILDLIFE));
        assertTrue(genres.contains(Genres.COMEDY));
        assertTrue(genres.contains(Genres.DRAMA));
        assertTrue(genres.contains(Genres.EDUCATION));
        assertTrue(genres.contains(Genres.FAMILY_KIDS));
        assertTrue(genres.contains(Genres.GAMING));
        assertTrue(genres.contains(Genres.MOVIES));
        assertTrue(genres.contains(Genres.NEWS));
        assertTrue(genres.contains(Genres.SHOPPING));
        assertTrue(genres.contains(Genres.SPORTS));
        assertTrue(genres.contains(Genres.TRAVEL));
        assertFalse(genres.contains(","));
    }

    public void testProgramsGenresEncode() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        assertEquals(ENCODED_GENRE_STRING, Genres.encode(Genres.ANIMAL_WILDLIFE,
                Genres.COMEDY, Genres.DRAMA, Genres.EDUCATION, Genres.FAMILY_KIDS, Genres.GAMING,
                Genres.MOVIES, Genres.NEWS, Genres.SHOPPING, Genres.SPORTS, Genres.TRAVEL));
    }

    public void testProgramsGenresEncodeDecode_empty() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        String[] genres = new String[] {EMPTY_GENRE};
        String expectedEncoded = EMPTY_GENRE;
        checkGenreEncodeDecode(genres, expectedEncoded, 0);

        genres = new String[] {EMPTY_GENRE, EMPTY_GENRE, EMPTY_GENRE};
        expectedEncoded = DELIMITER + DELIMITER;
        checkGenreEncodeDecode(genres, expectedEncoded, 0);
    }

    public void testProgramsGenresEncodeDecode_simpleDelimiter() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        String[] genres = new String[] {EMPTY_GENRE,
                COMMA,
                QUOTE,
                COMMA + QUOTE,
                QUOTE + COMMA,
                COMMA + COMMA,
                QUOTE + QUOTE,
                COMMA + QUOTE + COMMA,
                QUOTE + COMMA + QUOTE};
        String expectedEncoded =
                DELIMITER + COMMA_ENCODED
                + DELIMITER + QUOTE_ENCODED
                + DELIMITER + COMMA_ENCODED + QUOTE_ENCODED
                + DELIMITER + QUOTE_ENCODED + COMMA_ENCODED
                + DELIMITER + COMMA_ENCODED + COMMA_ENCODED
                + DELIMITER + QUOTE_ENCODED + QUOTE_ENCODED
                + DELIMITER + COMMA_ENCODED + QUOTE_ENCODED + COMMA_ENCODED
                + DELIMITER + QUOTE_ENCODED + COMMA_ENCODED + QUOTE_ENCODED;
        checkGenreEncodeDecode(genres, expectedEncoded, genres.length - 1);
    }

    public void testProgramsGenresEncodeDecode_delimiterWithWhiteSpace() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        String[] genres = new String[] {EMPTY_GENRE,
                COMMA + WHITE_SPACES,
                QUOTE + WHITE_SPACES,
                WHITE_SPACES + COMMA,
                WHITE_SPACES + QUOTE,
                WHITE_SPACES + COMMA + WHITE_SPACES,
                WHITE_SPACES + QUOTE + WHITE_SPACES};
        String expectedEncoded =
                DELIMITER + COMMA_ENCODED + WHITE_SPACES
                + DELIMITER + QUOTE_ENCODED + WHITE_SPACES
                + DELIMITER + WHITE_SPACES + COMMA_ENCODED
                + DELIMITER + WHITE_SPACES + QUOTE_ENCODED
                + DELIMITER + WHITE_SPACES + COMMA_ENCODED + WHITE_SPACES
                + DELIMITER + WHITE_SPACES + QUOTE_ENCODED + WHITE_SPACES;
        checkGenreEncodeDecode(genres, expectedEncoded, genres.length - 1);
    }

    public void testProgramsGenresEncodeDecode_all() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        String[] genres = new String[] {EMPTY_GENRE,
                Genres.COMEDY,
                Genres.COMEDY + COMMA,
                Genres.COMEDY + COMMA + Genres.COMEDY,
                COMMA + Genres.COMEDY + COMMA,
                QUOTE + Genres.COMEDY + QUOTE,
                Genres.COMEDY + COMMA + WHITE_SPACES,
                Genres.COMEDY + COMMA + Genres.COMEDY + WHITE_SPACES,
                COMMA + Genres.COMEDY + COMMA + WHITE_SPACES,
                QUOTE + Genres.COMEDY + QUOTE + WHITE_SPACES
        };
        String expectedEncoded =
                DELIMITER + Genres.COMEDY
                + DELIMITER + Genres.COMEDY + COMMA_ENCODED
                + DELIMITER + Genres.COMEDY + COMMA_ENCODED + Genres.COMEDY
                + DELIMITER + COMMA_ENCODED + Genres.COMEDY + COMMA_ENCODED
                + DELIMITER + QUOTE_ENCODED + Genres.COMEDY + QUOTE_ENCODED
                + DELIMITER + Genres.COMEDY + COMMA_ENCODED + WHITE_SPACES
                + DELIMITER + Genres.COMEDY + COMMA_ENCODED + Genres.COMEDY + WHITE_SPACES
                + DELIMITER + COMMA_ENCODED + Genres.COMEDY + COMMA_ENCODED + WHITE_SPACES
                + DELIMITER + QUOTE_ENCODED + Genres.COMEDY + QUOTE_ENCODED + WHITE_SPACES;
        checkGenreEncodeDecode(genres, expectedEncoded, genres.length - 1);
    }

    private void checkGenreEncodeDecode(String[] genres, String expectedEncoded,
            int expectedDecodedLength) {
        String encoded = Genres.encode(genres);
        assertEquals(expectedEncoded, encoded);
        String[] decoded = Genres.decode(encoded);
        assertEquals(expectedDecodedLength, decoded.length);
        int decodedIndex = 0;
        for (int i = 0; i < genres.length; ++i) {
            String original = genres[i].trim();
            if (!original.isEmpty()) {
                assertEquals(original, decoded[decodedIndex++]);
            }
        }
    }

    private Uri insertProgramWithBroadcastGenre(String[] broadcastGenre) {
        ContentValues values = createDummyChannelValues(mInputId, false);
        Uri channelUri = mContentResolver.insert(Channels.CONTENT_URI, values);
        long channelId = ContentUris.parseId(channelUri);
        long curTime = System.currentTimeMillis();
        values = new ContentValues();
        values.put(Programs.COLUMN_CHANNEL_ID, channelId);
        values.put(Programs.COLUMN_BROADCAST_GENRE, Genres.encode(broadcastGenre));
        values.put(Programs.COLUMN_START_TIME_UTC_MILLIS, curTime - 60000);
        values.put(Programs.COLUMN_END_TIME_UTC_MILLIS, curTime + 60000);
        Uri programUri = mContentResolver.insert(Programs.CONTENT_URI, values);
        assertNotNull(programUri);
        return programUri;
    }

    private void verifyChannelCountWithCanonicalGenre(String canonicalGenre, int expectedCount) {
        Uri channelUri = TvContract.buildChannelsUriForInput(mInputId).buildUpon()
                .appendQueryParameter(PARAM_CANONICAL_GENRE, canonicalGenre).build();
        try (Cursor c = mContentResolver.query(channelUri, new String[] {Channels._ID}, null, null,
                null)) {
            assertNotNull(c);
            assertEquals("Query:{Uri=" + channelUri + "}", expectedCount, c.getCount());
        }
    }

    public void testBroadcastGenreEncodeDecode() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        String[] broadcastGenre = new String[] {"Animation", "Classic, opera"};
        insertProgramWithBroadcastGenre(broadcastGenre);
        try (Cursor c = mContentResolver.query(Programs.CONTENT_URI,
                new String[] {Programs.COLUMN_BROADCAST_GENRE}, null, null, null)) {
            assertNotNull(c);
            assertEquals(1, c.getCount());
            c.moveToNext();
            MoreAsserts.assertEquals(broadcastGenre, Genres.decode(c.getString(0)));
        }
    }

    public void testBroadcastGenreQueryChannel() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        // "Animation" is mapped to Genres.MOVIES
        // "Classic, opera" is mapped to Genres.MUSIC
        insertProgramWithBroadcastGenre(new String[]{"Animation"});
        insertProgramWithBroadcastGenre(new String[] {"Classic, opera"});
        insertProgramWithBroadcastGenre(new String[]{"Animation", "Classic, opera"});
        // There are two channels which belong to MOVIES genre - channel 1 and 3.
        verifyChannelCountWithCanonicalGenre(Genres.MOVIES, 2);
        // There are two channels which belong to MUSIC genre - channel 2 and 3.
        verifyChannelCountWithCanonicalGenre(Genres.MUSIC, 2);
    }

    public void testGenresIsCanonical() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        assertTrue(Genres.isCanonical(Genres.DRAMA));
        assertFalse(Genres.isCanonical("Not a genre"));
    }

    public void testUriUtils() {
        if (!Utils.hasTvInputFramework(getContext())) {
            return;
        }
        final Uri CHANNEL_URI_FOR_TUNER = TvContract.buildChannelUri(0);
        final Uri CHANNEL_URI_FOR_PASSTHROUGH_INPUT =
                TvContract.buildChannelUriForPassthroughInput("inputId");
        final Uri PROGRAM_URI = TvContract.buildProgramUri(0);

        // Test isChannelUri
        assertTrue(TvContract.isChannelUri(CHANNEL_URI_FOR_TUNER));
        assertTrue(TvContract.isChannelUri(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
        assertFalse(TvContract.isChannelUri(PROGRAM_URI));
        assertFalse(TvContract.isChannelUri(null));

        // Test isChannelUriForPassthroughInput
        assertFalse(TvContract.isChannelUriForPassthroughInput(CHANNEL_URI_FOR_TUNER));
        assertTrue(TvContract.isChannelUriForPassthroughInput(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
        assertFalse(TvContract.isChannelUriForPassthroughInput(PROGRAM_URI));
        assertFalse(TvContract.isChannelUriForPassthroughInput(null));

        // Test isChannelUriForTunerInput
        assertTrue(TvContract.isChannelUriForTunerInput(CHANNEL_URI_FOR_TUNER));
        assertFalse(TvContract.isChannelUriForTunerInput(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
        assertFalse(TvContract.isChannelUriForTunerInput(PROGRAM_URI));
        assertFalse(TvContract.isChannelUriForTunerInput(null));

        // Test isProgramUri
        assertFalse(TvContract.isProgramUri(CHANNEL_URI_FOR_TUNER));
        assertFalse(TvContract.isProgramUri(CHANNEL_URI_FOR_PASSTHROUGH_INPUT));
        assertTrue(TvContract.isProgramUri(PROGRAM_URI));
        assertFalse(TvContract.isProgramUri(null));
    }
}
