diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-05-01 18:20:08 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-05-01 18:20:13 +0000 |
commit | fd09753145ae5af960e177e21857b224ea331048 (patch) | |
tree | 03d3e30904c704966a40c2db7003352020e899a5 | |
parent | 6b33ebe4bdd90b7887772ca3148b8f91854afba0 (diff) | |
parent | e6d009a5ad44cc6868f13ad7dd681349b3ecc980 (diff) | |
download | TvProvider-fd09753145ae5af960e177e21857b224ea331048.tar.gz |
Merge "Add parameter for accessing channels from 3rd-party TV apps." into oc-dev
-rw-r--r-- | src/com/android/providers/tv/TvProvider.java | 6 | ||||
-rw-r--r-- | tests/src/com/android/providers/tv/MockTvProviderContext.java | 16 | ||||
-rw-r--r-- | tests/src/com/android/providers/tv/ParametersTest.java | 137 |
3 files changed, 153 insertions, 6 deletions
diff --git a/src/com/android/providers/tv/TvProvider.java b/src/com/android/providers/tv/TvProvider.java index 725641a..ceb864c 100644 --- a/src/com/android/providers/tv/TvProvider.java +++ b/src/com/android/providers/tv/TvProvider.java @@ -1616,6 +1616,7 @@ public class TvProvider extends ContentProvider { // Control access to EPG data (excluding watched programs) when the caller doesn't have all // access. + String prefix = match == MATCH_CHANNEL ? CHANNELS_TABLE + "." : ""; if (!callerHasAccessAllEpgDataPermission() && match != MATCH_WATCHED_PROGRAM && match != MATCH_WATCHED_PROGRAM_ID) { if (!TextUtils.isEmpty(selection)) { @@ -1623,7 +1624,6 @@ public class TvProvider extends ContentProvider { } // Limit the operation only to the data that the calling package owns except for when // the caller tries to read TV listings and has the appropriate permission. - String prefix = match == MATCH_CHANNEL ? CHANNELS_TABLE + "." : ""; if (operation.equals(OP_QUERY) && callerHasReadTvListingsPermission()) { params.setWhere(prefix + BaseTvColumns.COLUMN_PACKAGE_NAME + "=? OR " + Channels.COLUMN_SEARCHABLE + "=?", getCallingPackage_(), "1"); @@ -1632,6 +1632,10 @@ public class TvProvider extends ContentProvider { getCallingPackage_()); } } + String packageName = uri.getQueryParameter(TvContract.PARAM_PACKAGE); + if (packageName != null) { + params.appendWhere(prefix + BaseTvColumns.COLUMN_PACKAGE_NAME + "=?", packageName); + } switch (match) { case MATCH_CHANNEL: diff --git a/tests/src/com/android/providers/tv/MockTvProviderContext.java b/tests/src/com/android/providers/tv/MockTvProviderContext.java index 177cf35..47520de 100644 --- a/tests/src/com/android/providers/tv/MockTvProviderContext.java +++ b/tests/src/com/android/providers/tv/MockTvProviderContext.java @@ -29,6 +29,9 @@ import android.test.RenamingDelegatingContext; import android.test.mock.MockContext; import android.test.mock.MockPackageManager; +import java.util.Set; +import java.util.HashSet; + class MockTvProviderContext extends IsolatedContext { private final Context mBase; private final MockPackageManager mMockPackageManager = new MockPackageManager() { @@ -38,6 +41,8 @@ class MockTvProviderContext extends IsolatedContext { } }; + private final Set<String> rejectedPermissions = new HashSet<>(); + MockTvProviderContext(ContentResolver resolver, Context base) { super(resolver, new RenamingDelegatingContext(new MockContext(), base, "test.")); mBase = base; @@ -65,11 +70,20 @@ class MockTvProviderContext extends IsolatedContext { @Override public int checkCallingOrSelfPermission(String permission) { - return PackageManager.PERMISSION_GRANTED; + return rejectedPermissions.contains(permission) ? PackageManager.PERMISSION_DENIED + : PackageManager.PERMISSION_GRANTED; } @Override public SharedPreferences getSharedPreferences(String name, int mode) { return mBase.getSharedPreferences(name, mode); } + + public void grantOrRejectPermission(String permission, boolean granted) { + if (granted) { + rejectedPermissions.remove(permission); + } else { + rejectedPermissions.add(permission); + } + } } diff --git a/tests/src/com/android/providers/tv/ParametersTest.java b/tests/src/com/android/providers/tv/ParametersTest.java index 84702fb..fd2b33f 100644 --- a/tests/src/com/android/providers/tv/ParametersTest.java +++ b/tests/src/com/android/providers/tv/ParametersTest.java @@ -30,9 +30,13 @@ 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 { @@ -49,7 +53,8 @@ public class ParametersTest extends AndroidTestCase { mProvider = new TvProviderForTesting(); mResolver.addProvider(TvContract.AUTHORITY, mProvider); - setContext(new MockTvProviderContext(mResolver, getContext())); + mContext = new MockTvProviderContext(mResolver, getContext()); + setContext(mContext); final ProviderInfo info = new ProviderInfo(); info.authority = TvContract.AUTHORITY; @@ -64,7 +69,7 @@ public class ParametersTest extends AndroidTestCase { super.tearDown(); } - private ContentValues createDummyChannelValues(boolean preview) { + 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"); @@ -72,6 +77,7 @@ public class ParametersTest extends AndroidTestCase { 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; } @@ -79,6 +85,10 @@ public class ParametersTest extends AndroidTestCase { 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); @@ -86,21 +96,140 @@ public class ParametersTest extends AndroidTestCase { } } + 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(true); + 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(false); + 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); + } } |