summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2017-05-01 18:20:08 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-05-01 18:20:13 +0000
commitfd09753145ae5af960e177e21857b224ea331048 (patch)
tree03d3e30904c704966a40c2db7003352020e899a5
parent6b33ebe4bdd90b7887772ca3148b8f91854afba0 (diff)
parente6d009a5ad44cc6868f13ad7dd681349b3ecc980 (diff)
downloadTvProvider-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.java6
-rw-r--r--tests/src/com/android/providers/tv/MockTvProviderContext.java16
-rw-r--r--tests/src/com/android/providers/tv/ParametersTest.java137
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);
+ }
}