/* * Copyright (C) 2017 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 com.android.providers.tv; import android.content.ContentValues; import android.content.pm.ProviderInfo; import android.database.Cursor; import android.media.tv.TvContract; import android.media.tv.TvContract.Channels; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.test.AndroidTestCase; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; public class ParametersTest extends AndroidTestCase { private static final String FAKE_INPUT_ID = "ParametersTest"; private static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS"; private static final String PERMISSION_ACCESS_ALL_EPG_DATA = "com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA"; private MockContentResolver mResolver; private TvProviderForTesting mProvider; private MockTvProviderContext mContext; @Override protected void setUp() throws Exception { super.setUp(); mResolver = new MockContentResolver(); mResolver.addProvider(Settings.AUTHORITY, new MockContentProvider() { @Override public Bundle call(String method, String request, Bundle args) { return new Bundle(); } }); mProvider = new TvProviderForTesting(); mResolver.addProvider(TvContract.AUTHORITY, mProvider); mContext = new MockTvProviderContext(mResolver, getContext()); setContext(mContext); final ProviderInfo info = new ProviderInfo(); info.authority = TvContract.AUTHORITY; mProvider.attachInfoForTesting(getContext(), info); Utils.clearTvProvider(mResolver); } @Override protected void tearDown() throws Exception { Utils.clearTvProvider(mResolver); mProvider.shutdown(); super.tearDown(); } private ContentValues createDummyChannelValues(int searchable, boolean preview) { ContentValues values = new ContentValues(); values.put(Channels.COLUMN_INPUT_ID, FAKE_INPUT_ID); 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); values.put(Channels.COLUMN_SEARCHABLE, searchable); return values; } private void verifyChannelCountWithPreview(int expectedCount, boolean preview) { Uri channelUri = Channels.CONTENT_URI.buildUpon() .appendQueryParameter(TvContract.PARAM_PREVIEW, String.valueOf(preview)).build(); verifyChannelCount(channelUri, expectedCount); } private void verifyChannelCount(Uri channelUri, int expectedCount) { try (Cursor cursor = mResolver.query( channelUri, new String[] {Channels.COLUMN_TYPE}, null, null, null)) { assertNotNull(cursor); assertEquals("Query:{Uri=" + channelUri + "}", expectedCount, cursor.getCount()); } } private void insertChannelWithPackageName(ContentValues values, String packageName) { mProvider.callingPackage = packageName; mResolver.insert(Channels.CONTENT_URI, values); mProvider.callingPackage = null; } private void verifyChannelQuery(Uri channelsUri, int expectedCount, boolean expectedException) { try { verifyChannelCount(channelsUri, expectedCount); if (expectedException) { fail("Query:{Uri=" + channelsUri + "} should throw exception"); } } catch (SecurityException e) { if (!expectedException) { fail("Query failed due to:" + e); } } } private void verifyChannelUpdate(Uri channelsUri, ContentValues values, int expectedCount, boolean expectedException) { try { int count = mResolver.update(channelsUri, values, null, null); if (expectedException) { fail("Update:{Uri=" + channelsUri + "} should throw exception"); } assertEquals(expectedCount, count); } catch (SecurityException e) { if (!expectedException) { fail("Update failed due to:" + e); } } } private void verifyChannelDelete(Uri channelsUri, int expectedCount, boolean expectedException) { try { int count = mResolver.delete(channelsUri, null, null); if (expectedException) { fail("Delete:{Uri=" + channelsUri + "} should throw exception"); } assertEquals(expectedCount, count); } catch (SecurityException e) { if (!expectedException) { fail("Delete failed due to:" + e); } } } public void testTypePreviewQueryChannel() { // Check if there is not any preview and non-preview channels. verifyChannelCountWithPreview(0, true); verifyChannelCountWithPreview(0, false); // Insert one preview channel and then check if the count of preview channels is 0 and the // count of non-preview channels is 0. ContentValues previewChannelContentValue = createDummyChannelValues(1, true); mResolver.insert(Channels.CONTENT_URI, previewChannelContentValue); verifyChannelCountWithPreview(1, true); verifyChannelCountWithPreview(0, false); // Insert one non-preview channel and then check if the count of preview channels or // non-preview channels are both 1. ContentValues nonPreviewChannelContentValue = createDummyChannelValues(1, false); mResolver.insert(Channels.CONTENT_URI, nonPreviewChannelContentValue); verifyChannelCountWithPreview(1, true); verifyChannelCountWithPreview(1, false); } public void testPackageNameOperateChannels() { String packageName = getContext().getPackageName(); String otherPackageName = packageName + ".other"; Uri ownPackageChannelsUri = Channels.CONTENT_URI.buildUpon() .appendQueryParameter(TvContract.PARAM_PACKAGE, packageName).build(); Uri otherPackageChannelsUri = Channels.CONTENT_URI.buildUpon() .appendQueryParameter(TvContract.PARAM_PACKAGE, otherPackageName).build(); // Tests with PERMISSION_ACCESS_ALL_EPG_DATA. ContentValues values = createDummyChannelValues(1, false); insertChannelWithPackageName(values, packageName); verifyChannelQuery(ownPackageChannelsUri, 1, false); ContentValues otherValues1 = createDummyChannelValues(1, false); ContentValues otherValues2 = createDummyChannelValues(0, false); insertChannelWithPackageName(otherValues1, otherPackageName); verifyChannelQuery(otherPackageChannelsUri, 1, false); insertChannelWithPackageName(otherValues2, otherPackageName); verifyChannelQuery(otherPackageChannelsUri, 2, false); values.remove(Channels.COLUMN_TYPE); values.put(Channels.COLUMN_DISPLAY_NUMBER, "2"); verifyChannelUpdate(ownPackageChannelsUri, values, 1, false); verifyChannelDelete(ownPackageChannelsUri, 1, false); otherValues1.remove(Channels.COLUMN_TYPE); otherValues1.put(Channels.COLUMN_DISPLAY_NUMBER, "2"); verifyChannelUpdate(otherPackageChannelsUri, otherValues1, 2, false); verifyChannelDelete(otherPackageChannelsUri, 2, false); // Tests with PERMISSION_READ_TV_LISTINGS, without PERMISSION_ACCESS_ALL_EPG_DATA. mContext.grantOrRejectPermission(PERMISSION_ACCESS_ALL_EPG_DATA, false); values = createDummyChannelValues(1, false); insertChannelWithPackageName(values, packageName); verifyChannelQuery(ownPackageChannelsUri, 1, false); otherValues1 = createDummyChannelValues(1, false); otherValues2 = createDummyChannelValues(1, false); ContentValues otherValues3 = createDummyChannelValues(0, false); insertChannelWithPackageName(otherValues1, otherPackageName); verifyChannelQuery(otherPackageChannelsUri, 1, false); insertChannelWithPackageName(otherValues2, otherPackageName); verifyChannelQuery(otherPackageChannelsUri, 2, false); insertChannelWithPackageName(otherValues3, otherPackageName); verifyChannelQuery(otherPackageChannelsUri, 2, false); values.remove(Channels.COLUMN_TYPE); values.put(Channels.COLUMN_DISPLAY_NUMBER, "2"); verifyChannelUpdate(ownPackageChannelsUri, values, 1, false); verifyChannelDelete(ownPackageChannelsUri, 1, false); otherValues1.remove(Channels.COLUMN_TYPE); otherValues1.remove(Channels.COLUMN_PACKAGE_NAME); otherValues1.put(Channels.COLUMN_DISPLAY_NUMBER, "2"); verifyChannelUpdate(otherPackageChannelsUri, otherValues1, 0, false); verifyChannelDelete(otherPackageChannelsUri, 0, false); // Tests without PERMISSION_ACCESS_ALL_EPG_DATA and PERMISSION_READ_TV_LISTINGS. mContext.grantOrRejectPermission(PERMISSION_READ_TV_LISTINGS, false); values = createDummyChannelValues(1, false); insertChannelWithPackageName(values, packageName); verifyChannelQuery(ownPackageChannelsUri, 1, false); otherValues1 = createDummyChannelValues(1, false); insertChannelWithPackageName(otherValues1, otherPackageName); verifyChannelQuery(otherPackageChannelsUri, 0, false); values.remove(Channels.COLUMN_TYPE); values.put(Channels.COLUMN_DISPLAY_NUMBER, "2"); verifyChannelUpdate(ownPackageChannelsUri, values, 1, false); verifyChannelDelete(ownPackageChannelsUri, 1, false); otherValues1.remove(Channels.COLUMN_TYPE); otherValues1.remove(Channels.COLUMN_PACKAGE_NAME); otherValues1.put(Channels.COLUMN_DISPLAY_NUMBER, "2"); verifyChannelUpdate(otherPackageChannelsUri, otherValues1, 0, false); verifyChannelDelete(otherPackageChannelsUri, 0, false); } }