Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media.tv.cts;
     18 
     19 import android.content.ComponentName;
     20 import android.content.ContentResolver;
     21 import android.content.ContentUris;
     22 import android.content.ContentValues;
     23 import android.content.res.AssetFileDescriptor;
     24 import android.database.Cursor;
     25 import android.graphics.Bitmap;
     26 import android.graphics.BitmapFactory;
     27 import android.media.tv.TvContentRating;
     28 import android.media.tv.TvContract;
     29 import android.net.Uri;
     30 import android.test.AndroidTestCase;
     31 
     32 import com.android.cts.tv.R;
     33 
     34 import java.io.InputStream;
     35 import java.io.OutputStream;
     36 
     37 /**
     38  * Test for {@link android.media.tv.TvContract}.
     39  */
     40 public class TvContractTest extends AndroidTestCase {
     41     private static final String[] CHANNELS_PROJECTION = {
     42         TvContract.Channels._ID,
     43         TvContract.Channels.COLUMN_INPUT_ID,
     44         TvContract.Channels.COLUMN_TYPE,
     45         TvContract.Channels.COLUMN_SERVICE_TYPE,
     46         TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID,
     47         TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID,
     48         TvContract.Channels.COLUMN_SERVICE_ID,
     49         TvContract.Channels.COLUMN_DISPLAY_NUMBER,
     50         TvContract.Channels.COLUMN_DISPLAY_NAME,
     51         TvContract.Channels.COLUMN_NETWORK_AFFILIATION,
     52         TvContract.Channels.COLUMN_DESCRIPTION,
     53         TvContract.Channels.COLUMN_VIDEO_FORMAT,
     54         TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA,
     55         TvContract.Channels.COLUMN_VERSION_NUMBER,
     56     };
     57 
     58     private static final String[] PROGRAMS_PROJECTION = {
     59         TvContract.Programs._ID,
     60         TvContract.Programs.COLUMN_CHANNEL_ID,
     61         TvContract.Programs.COLUMN_TITLE,
     62         TvContract.Programs.COLUMN_SEASON_NUMBER,
     63         TvContract.Programs.COLUMN_EPISODE_NUMBER,
     64         TvContract.Programs.COLUMN_EPISODE_TITLE,
     65         TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
     66         TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS,
     67         TvContract.Programs.COLUMN_BROADCAST_GENRE,
     68         TvContract.Programs.COLUMN_CANONICAL_GENRE,
     69         TvContract.Programs.COLUMN_SHORT_DESCRIPTION,
     70         TvContract.Programs.COLUMN_LONG_DESCRIPTION,
     71         TvContract.Programs.COLUMN_VIDEO_WIDTH,
     72         TvContract.Programs.COLUMN_VIDEO_HEIGHT,
     73         TvContract.Programs.COLUMN_AUDIO_LANGUAGE,
     74         TvContract.Programs.COLUMN_CONTENT_RATING,
     75         TvContract.Programs.COLUMN_POSTER_ART_URI,
     76         TvContract.Programs.COLUMN_THUMBNAIL_URI,
     77         TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA,
     78         TvContract.Programs.COLUMN_VERSION_NUMBER,
     79     };
     80 
     81     private static long OPERATION_TIME = 1000l;
     82 
     83     private String mInputId;
     84     private ContentResolver mContentResolver;
     85     private Uri mChannelsUri;
     86 
     87     @Override
     88     protected void setUp() throws Exception {
     89         super.setUp();
     90         if (!Utils.hasTvInputFramework(getContext())) {
     91             return;
     92         }
     93         mInputId = TvContract.buildInputId(
     94                 new ComponentName(getContext(), StubTunerTvInputService.class));
     95         mContentResolver = getContext().getContentResolver();
     96         mChannelsUri = TvContract.buildChannelsUriForInput(mInputId);
     97     }
     98 
     99     @Override
    100     protected void tearDown() throws Exception {
    101         if (!Utils.hasTvInputFramework(getContext())) {
    102             super.tearDown();
    103             return;
    104         }
    105         // Clean up, just in case we failed to delete the entry when a test failed.
    106         // The cotentUris are specific to this package, so this will delete only the
    107         // entries inserted by this package.
    108         String[] projection = { TvContract.Channels._ID };
    109         try (Cursor cursor = mContentResolver.query(mChannelsUri, projection, null, null, null)) {
    110             while (cursor != null && cursor.moveToNext()) {
    111                 long channelId = cursor.getLong(0);
    112                 mContentResolver.delete(
    113                         TvContract.buildProgramsUriForChannel(channelId), null, null);
    114             }
    115         }
    116         mContentResolver.delete(mChannelsUri, null, null);
    117         super.tearDown();
    118     }
    119 
    120     private static ContentValues createDummyChannelValues(String inputId) {
    121         ContentValues values = new ContentValues();
    122         values.put(TvContract.Channels.COLUMN_INPUT_ID, inputId);
    123         values.put(TvContract.Channels.COLUMN_TYPE, TvContract.Channels.TYPE_OTHER);
    124         values.put(TvContract.Channels.COLUMN_SERVICE_TYPE,
    125                 TvContract.Channels.SERVICE_TYPE_AUDIO_VIDEO);
    126         values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "1");
    127         values.put(TvContract.Channels.COLUMN_VIDEO_FORMAT, TvContract.Channels.VIDEO_FORMAT_480P);
    128 
    129         return values;
    130     }
    131 
    132     private static ContentValues createDummyProgramValues(long channelId) {
    133         ContentValues values = new ContentValues();
    134         values.put(TvContract.Programs.COLUMN_CHANNEL_ID, channelId);
    135         values.put(TvContract.Programs.COLUMN_EPISODE_TITLE, "Title");
    136         values.put(TvContract.Programs.COLUMN_CANONICAL_GENRE, TvContract.Programs.Genres.encode(
    137                 TvContract.Programs.Genres.MOVIES, TvContract.Programs.Genres.DRAMA));
    138         TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
    139                 "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
    140         values.put(TvContract.Programs.COLUMN_CONTENT_RATING, rating.flattenToString());
    141 
    142         return values;
    143     }
    144 
    145     private static void verifyStringColumn(Cursor cursor, ContentValues expectedValues,
    146             String columnName) {
    147         if (expectedValues.containsKey(columnName)) {
    148             assertEquals(expectedValues.getAsString(columnName),
    149                     cursor.getString(cursor.getColumnIndex(columnName)));
    150         }
    151     }
    152 
    153     private static void verifyIntegerColumn(Cursor cursor, ContentValues expectedValues,
    154             String columnName) {
    155         if (expectedValues.containsKey(columnName)) {
    156             assertEquals(expectedValues.getAsInteger(columnName).intValue(),
    157                     cursor.getInt(cursor.getColumnIndex(columnName)));
    158         }
    159     }
    160 
    161     private static void verifyLongColumn(Cursor cursor, ContentValues expectedValues,
    162             String columnName) {
    163         if (expectedValues.containsKey(columnName)) {
    164             assertEquals(expectedValues.getAsLong(columnName).longValue(),
    165                     cursor.getLong(cursor.getColumnIndex(columnName)));
    166         }
    167     }
    168 
    169     private static void verifyBlobColumn(Cursor cursor, ContentValues expectedValues,
    170             String columnName) {
    171         if (expectedValues.containsKey(columnName)) {
    172             byte[] expected = expectedValues.getAsByteArray(columnName);
    173             byte[] actual = cursor.getBlob(cursor.getColumnIndex(columnName));
    174             assertEquals(expected.length, actual.length);
    175             for (int i = 0; i < expected.length; ++i) {
    176                 assertEquals(expected[i], actual[i]);
    177             }
    178         }
    179     }
    180 
    181     private void verifyChannel(Uri channelUri, ContentValues expectedValues, long channelId) {
    182         try (Cursor cursor = mContentResolver.query(
    183                 channelUri, CHANNELS_PROJECTION, null, null, null)) {
    184             assertNotNull(cursor);
    185             assertEquals(cursor.getCount(), 1);
    186             assertTrue(cursor.moveToNext());
    187             assertEquals(channelId, cursor.getLong(cursor.getColumnIndex(TvContract.Channels._ID)));
    188             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_INPUT_ID);
    189             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_TYPE);
    190             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_SERVICE_TYPE);
    191             verifyIntegerColumn(cursor, expectedValues,
    192                     TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID);
    193             verifyIntegerColumn(cursor, expectedValues,
    194                     TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID);
    195             verifyIntegerColumn(cursor, expectedValues,
    196                     TvContract.Channels.COLUMN_SERVICE_ID);
    197             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_DISPLAY_NUMBER);
    198             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_DISPLAY_NAME);
    199             verifyStringColumn(cursor, expectedValues,
    200                     TvContract.Channels.COLUMN_NETWORK_AFFILIATION);
    201             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_DESCRIPTION);
    202             verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_VIDEO_FORMAT);
    203             verifyBlobColumn(cursor, expectedValues,
    204                     TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA);
    205             verifyIntegerColumn(cursor, expectedValues, TvContract.Channels.COLUMN_VERSION_NUMBER);
    206         }
    207     }
    208 
    209     public void testChannelsTable() throws Exception {
    210         if (!Utils.hasTvInputFramework(getContext())) {
    211             return;
    212         }
    213         // Test: insert
    214         ContentValues values = createDummyChannelValues(mInputId);
    215 
    216         Uri rowUri = mContentResolver.insert(mChannelsUri, values);
    217         long channelId = ContentUris.parseId(rowUri);
    218         Uri channelUri = TvContract.buildChannelUri(channelId);
    219         verifyChannel(channelUri, values, channelId);
    220 
    221         // Test: update
    222         values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "1-1");
    223         values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "One dash one");
    224         values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());
    225 
    226         mContentResolver.update(channelUri, values, null, null);
    227         verifyChannel(channelUri, values, channelId);
    228 
    229         // Test: delete
    230         mContentResolver.delete(mChannelsUri, null, null);
    231         try (Cursor cursor = mContentResolver.query(
    232                 mChannelsUri, CHANNELS_PROJECTION, null, null, null)) {
    233             assertEquals(0, cursor.getCount());
    234         }
    235     }
    236 
    237     private void verifyProgram(Uri programUri, ContentValues expectedValues, long programId) {
    238         try (Cursor cursor = mContentResolver.query(
    239                 programUri, PROGRAMS_PROJECTION, null, null, null)) {
    240             assertNotNull(cursor);
    241             assertEquals(cursor.getCount(), 1);
    242             assertTrue(cursor.moveToNext());
    243             assertEquals(programId, cursor.getLong(cursor.getColumnIndex(TvContract.Programs._ID)));
    244             verifyLongColumn(cursor, expectedValues, TvContract.Programs.COLUMN_CHANNEL_ID);
    245             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_TITLE);
    246             verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_SEASON_NUMBER);
    247             verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_EPISODE_NUMBER);
    248             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_EPISODE_TITLE);
    249             verifyLongColumn(cursor, expectedValues,
    250                     TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS);
    251             verifyLongColumn(cursor, expectedValues,
    252                     TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS);
    253             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_BROADCAST_GENRE);
    254             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_CANONICAL_GENRE);
    255             verifyStringColumn(cursor, expectedValues,
    256                     TvContract.Programs.COLUMN_SHORT_DESCRIPTION);
    257             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_LONG_DESCRIPTION);
    258             verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_VIDEO_WIDTH);
    259             verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_VIDEO_HEIGHT);
    260             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_AUDIO_LANGUAGE);
    261             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_CONTENT_RATING);
    262             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_POSTER_ART_URI);
    263             verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_THUMBNAIL_URI);
    264             verifyBlobColumn(cursor, expectedValues,
    265                     TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA);
    266             verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_VERSION_NUMBER);
    267         }
    268     }
    269 
    270     private void verifyLogoIsReadable(Uri logoUri) throws Exception {
    271         try (AssetFileDescriptor fd = mContentResolver.openAssetFileDescriptor(logoUri, "r")) {
    272             try (InputStream is = fd.createInputStream()) {
    273                 // Assure that the stream is decodable as a Bitmap.
    274                 BitmapFactory.decodeStream(is);
    275             }
    276         }
    277     }
    278 
    279     public void testChannelLogo() throws Exception {
    280         if (!Utils.hasTvInputFramework(getContext())) {
    281             return;
    282         }
    283         // Set-up: add a channel.
    284         ContentValues values = createDummyChannelValues(mInputId);
    285         Uri channelUri = mContentResolver.insert(mChannelsUri, values);
    286         Uri logoUri = TvContract.buildChannelLogoUri(channelUri);
    287         Bitmap logo = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.robot);
    288 
    289         // Write
    290         try (AssetFileDescriptor fd = mContentResolver.openAssetFileDescriptor(logoUri, "w")) {
    291             try (OutputStream os = fd.createOutputStream()) {
    292                 logo.compress(Bitmap.CompressFormat.PNG, 100, os);
    293             }
    294         }
    295 
    296         // Give some time for TvProvider to process the logo.
    297         Thread.sleep(OPERATION_TIME);
    298 
    299         // Read and verify
    300         verifyLogoIsReadable(logoUri);
    301 
    302         // Read and verify using alternative logo URI.
    303         verifyLogoIsReadable(TvContract.buildChannelLogoUri(ContentUris.parseId(channelUri)));
    304     }
    305 
    306     public void verifyProgramsTable(Uri programsUri, long channelId) {
    307         if (!Utils.hasTvInputFramework(getContext())) {
    308             return;
    309         }
    310         // Test: insert
    311         ContentValues values = createDummyProgramValues(channelId);
    312 
    313         Uri rowUri = mContentResolver.insert(programsUri, values);
    314         long programId = ContentUris.parseId(rowUri);
    315         Uri programUri = TvContract.buildProgramUri(programId);
    316         verifyProgram(programUri, values, programId);
    317 
    318         // Test: update
    319         values.put(TvContract.Programs.COLUMN_EPISODE_TITLE, "Sample title");
    320         values.put(TvContract.Programs.COLUMN_SHORT_DESCRIPTION, "Short description");
    321         values.put(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());
    322 
    323         mContentResolver.update(programUri, values, null, null);
    324         verifyProgram(programUri, values, programId);
    325 
    326         // Test: delete
    327         mContentResolver.delete(programsUri, null, null);
    328         try (Cursor cursor = mContentResolver.query(
    329                 programsUri, PROGRAMS_PROJECTION, null, null, null)) {
    330             assertEquals(0, cursor.getCount());
    331         }
    332     }
    333 
    334     public void testProgramsTable() throws Exception {
    335         if (!Utils.hasTvInputFramework(getContext())) {
    336             return;
    337         }
    338         // Set-up: add a channel.
    339         ContentValues values = createDummyChannelValues(mInputId);
    340         Uri channelUri = mContentResolver.insert(mChannelsUri, values);
    341         long channelId = ContentUris.parseId(channelUri);
    342 
    343         verifyProgramsTable(TvContract.buildProgramsUriForChannel(channelId), channelId);
    344         verifyProgramsTable(TvContract.buildProgramsUriForChannel(channelUri), channelId);
    345     }
    346 
    347     private void verifyOverlap(long startMillis, long endMillis, int expectedCount,
    348             long channelId, Uri channelUri) {
    349         try (Cursor cursor = mContentResolver.query(TvContract.buildProgramsUriForChannel(
    350                 channelId, startMillis, endMillis), PROGRAMS_PROJECTION, null, null, null)) {
    351             assertEquals(expectedCount, cursor.getCount());
    352         }
    353         try (Cursor cursor = mContentResolver.query(TvContract.buildProgramsUriForChannel(
    354                 channelUri, startMillis, endMillis), PROGRAMS_PROJECTION, null, null, null)) {
    355             assertEquals(expectedCount, cursor.getCount());
    356         }
    357     }
    358 
    359     public void testProgramsScheduleOverlap() throws Exception {
    360         if (!Utils.hasTvInputFramework(getContext())) {
    361             return;
    362         }
    363         final long programStartMillis = 1403712000000l;  // Jun 25 2014 16:00 UTC
    364         final long programEndMillis = 1403719200000l;  // Jun 25 2014 18:00 UTC
    365         final long hour = 3600000l;
    366 
    367         // Set-up: add a channel and program.
    368         ContentValues values = createDummyChannelValues(mInputId);
    369         Uri channelUri = mContentResolver.insert(mChannelsUri, values);
    370         long channelId = ContentUris.parseId(channelUri);
    371         Uri programsUri = TvContract.buildProgramsUriForChannel(channelId);
    372         values = createDummyProgramValues(channelId);
    373         values.put(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, programStartMillis);
    374         values.put(TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, programEndMillis);
    375         mContentResolver.insert(programsUri, values);
    376 
    377         // Overlap 1: starts early, ends early.
    378         verifyOverlap(programStartMillis - hour, programEndMillis - hour, 1, channelId, channelUri);
    379 
    380         // Overlap 2: starts early, ends late.
    381         verifyOverlap(programStartMillis - hour, programEndMillis + hour, 1, channelId, channelUri);
    382 
    383         // Overlap 3: starts early, ends late.
    384         verifyOverlap(programStartMillis + hour / 2, programEndMillis - hour / 2, 1,
    385                 channelId, channelUri);
    386 
    387         // Overlap 4: starts late, ends late.
    388         verifyOverlap(programStartMillis + hour, programEndMillis + hour, 1, channelId, channelUri);
    389 
    390         // Non-overlap 1: ends too early.
    391         verifyOverlap(programStartMillis - hour, programStartMillis - hour / 2, 0,
    392                 channelId, channelUri);
    393 
    394         // Non-overlap 2: starts too late
    395         verifyOverlap(programEndMillis + hour, programEndMillis + hour * 2, 0,
    396                 channelId, channelUri);
    397     }
    398 
    399     private void verifyQueryWithSortOrder(Uri uri, final String[] projection,
    400             String sortOrder) throws Exception {
    401         try {
    402             getContext().getContentResolver().query(uri, projection, null, null, sortOrder);
    403             fail("Setting sortOrder should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
    404         } catch (SecurityException e) {
    405             // Expected exception
    406         }
    407     }
    408 
    409     private void verifyQueryWithSelection(Uri uri, final String[] projection,
    410             String selection) throws Exception {
    411         try {
    412             getContext().getContentResolver().query(uri, projection, selection, null, null);
    413             fail("Setting selection should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
    414         } catch (SecurityException e) {
    415             // Expected exception
    416         }
    417     }
    418 
    419     private void verifyUpdateWithSelection(Uri uri, String selection) throws Exception {
    420         try {
    421             ContentValues values = new ContentValues();
    422             getContext().getContentResolver().update(uri, values, selection, null);
    423             fail("Setting selection should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
    424         } catch (SecurityException e) {
    425             // Expected exception
    426         }
    427     }
    428 
    429     private void verifyDeleteWithSelection(Uri uri, String selection) throws Exception {
    430         try {
    431             getContext().getContentResolver().delete(uri, selection, null);
    432             fail("Setting selection should fail without ACCESS_ALL_EPG_DATA permission for " + uri);
    433         } catch (SecurityException e) {
    434             // Expected exception
    435         }
    436     }
    437 
    438     public void testAllEpgPermissionBlocksSortOrderOnQuery_Channels() throws Exception {
    439         if (!Utils.hasTvInputFramework(getContext())) {
    440             return;
    441         }
    442         final String[] projection = { TvContract.Channels._ID };
    443         verifyQueryWithSortOrder(TvContract.Channels.CONTENT_URI, projection,
    444                 TvContract.Channels._ID + " ASC");
    445     }
    446 
    447     public void testAllEpgPermissionBlocksSelectionOnQuery_Channels() throws Exception {
    448         if (!Utils.hasTvInputFramework(getContext())) {
    449             return;
    450         }
    451         final String[] projection = { TvContract.Channels._ID };
    452         verifyQueryWithSelection(TvContract.Channels.CONTENT_URI, projection,
    453                 TvContract.Channels._ID + ">0");
    454     }
    455 
    456     public void testAllEpgPermissionBlocksSelectionOnUpdate_Channels() throws Exception {
    457         if (!Utils.hasTvInputFramework(getContext())) {
    458             return;
    459         }
    460         verifyUpdateWithSelection(TvContract.Channels.CONTENT_URI,
    461                 TvContract.Channels._ID + ">0");
    462     }
    463 
    464     public void testAllEpgPermissionBlocksSelectionOnDelete_Channels() throws Exception {
    465         if (!Utils.hasTvInputFramework(getContext())) {
    466             return;
    467         }
    468         verifyDeleteWithSelection(TvContract.Channels.CONTENT_URI,
    469                 TvContract.Channels._ID + ">0");
    470     }
    471 
    472     public void testAllEpgPermissionBlocksSortOrderOnQuery_Programs() throws Exception {
    473         if (!Utils.hasTvInputFramework(getContext())) {
    474             return;
    475         }
    476         final String[] projection = { TvContract.Programs._ID };
    477         verifyQueryWithSortOrder(TvContract.Programs.CONTENT_URI, projection,
    478                 TvContract.Programs._ID + " ASC");
    479     }
    480 
    481     public void testAllEpgPermissionBlocksSelectionOnQuery_Programs() throws Exception {
    482         if (!Utils.hasTvInputFramework(getContext())) {
    483             return;
    484         }
    485         final String[] projection = { TvContract.Channels._ID };
    486         verifyQueryWithSelection(TvContract.Programs.CONTENT_URI, projection,
    487                 TvContract.Programs._ID + ">0");
    488     }
    489 
    490     public void testAllEpgPermissionBlocksSelectionOnUpdate_Programs() throws Exception {
    491         if (!Utils.hasTvInputFramework(getContext())) {
    492             return;
    493         }
    494         verifyUpdateWithSelection(TvContract.Programs.CONTENT_URI,
    495                 TvContract.Programs._ID + ">0");
    496     }
    497 
    498     public void testAllEpgPermissionBlocksSelectionOnDelete_Programs() throws Exception {
    499         if (!Utils.hasTvInputFramework(getContext())) {
    500             return;
    501         }
    502         verifyDeleteWithSelection(TvContract.Programs.CONTENT_URI,
    503                 TvContract.Programs._ID + ">0");
    504     }
    505 
    506     public void testDefaultValues() throws Exception {
    507         if (!Utils.hasTvInputFramework(getContext())) {
    508             return;
    509         }
    510         ContentValues values = new ContentValues();
    511         values.put(TvContract.Channels.COLUMN_INPUT_ID, mInputId);
    512         Uri channelUri = mContentResolver.insert(mChannelsUri, values);
    513         assertNotNull(channelUri);
    514         long channelId = ContentUris.parseId(channelUri);
    515         try (Cursor cursor = mContentResolver.query(
    516                 channelUri, CHANNELS_PROJECTION, null, null, null)) {
    517             cursor.moveToNext();
    518             assertEquals(TvContract.Channels.TYPE_OTHER,
    519                     cursor.getString(cursor.getColumnIndex(TvContract.Channels.COLUMN_TYPE)));
    520             assertEquals(TvContract.Channels.SERVICE_TYPE_AUDIO_VIDEO,
    521                     cursor.getString(cursor.getColumnIndex(
    522                             TvContract.Channels.COLUMN_SERVICE_TYPE)));
    523         }
    524         values.clear();
    525     }
    526 }
    527