1 /*
2  * Copyright (C) 2017 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 com.android.providers.tv;
18 
19 import android.content.ContentValues;
20 import android.content.pm.ProviderInfo;
21 import android.database.Cursor;
22 import android.media.tv.TvContract;
23 import android.media.tv.TvContract.Channels;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.provider.Settings;
27 import android.test.AndroidTestCase;
28 import android.test.mock.MockContentProvider;
29 import android.test.mock.MockContentResolver;
30 
31 public class ParametersTest extends AndroidTestCase {
32     private static final String FAKE_INPUT_ID = "ParametersTest";
33     private static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS";
34     private static final String PERMISSION_ACCESS_ALL_EPG_DATA =
35             "com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA";
36 
37     private MockContentResolver mResolver;
38     private TvProviderForTesting mProvider;
39     private MockTvProviderContext mContext;
40 
41     @Override
setUp()42     protected void setUp() throws Exception {
43         super.setUp();
44 
45         mResolver = new MockContentResolver();
46         mResolver.addProvider(Settings.AUTHORITY, new MockContentProvider() {
47             @Override
48             public Bundle call(String method, String request, Bundle args) {
49                 return new Bundle();
50             }
51         });
52 
53         mProvider = new TvProviderForTesting();
54         mResolver.addProvider(TvContract.AUTHORITY, mProvider);
55 
56         mContext = new MockTvProviderContext(mResolver, getContext());
57         setContext(mContext);
58 
59         final ProviderInfo info = new ProviderInfo();
60         info.authority = TvContract.AUTHORITY;
61         mProvider.attachInfoForTesting(getContext(), info);
62         Utils.clearTvProvider(mResolver);
63     }
64 
65     @Override
tearDown()66     protected void tearDown() throws Exception {
67         Utils.clearTvProvider(mResolver);
68         mProvider.shutdown();
69         super.tearDown();
70     }
71 
createDummyChannelValues(int searchable, boolean preview)72     private ContentValues createDummyChannelValues(int searchable, boolean preview) {
73         ContentValues values = new ContentValues();
74         values.put(Channels.COLUMN_INPUT_ID, FAKE_INPUT_ID);
75         values.put(Channels.COLUMN_INTERNAL_PROVIDER_ID, "ID-4321");
76         values.put(Channels.COLUMN_TYPE, preview ? Channels.TYPE_PREVIEW : Channels.TYPE_OTHER);
77         values.put(Channels.COLUMN_SERVICE_TYPE, Channels.SERVICE_TYPE_AUDIO_VIDEO);
78         values.put(Channels.COLUMN_DISPLAY_NUMBER, "1");
79         values.put(Channels.COLUMN_VIDEO_FORMAT, Channels.VIDEO_FORMAT_480P);
80         values.put(Channels.COLUMN_SEARCHABLE, searchable);
81 
82         return values;
83     }
84 
verifyChannelCountWithPreview(int expectedCount, boolean preview)85     private void verifyChannelCountWithPreview(int expectedCount, boolean preview) {
86         Uri channelUri = Channels.CONTENT_URI.buildUpon()
87                 .appendQueryParameter(TvContract.PARAM_PREVIEW, String.valueOf(preview)).build();
88         verifyChannelCount(channelUri, expectedCount);
89     }
90 
verifyChannelCount(Uri channelUri, int expectedCount)91     private void verifyChannelCount(Uri channelUri, int expectedCount) {
92         try (Cursor cursor = mResolver.query(
93                 channelUri, new String[] {Channels.COLUMN_TYPE}, null, null, null)) {
94             assertNotNull(cursor);
95             assertEquals("Query:{Uri=" + channelUri + "}", expectedCount, cursor.getCount());
96         }
97     }
98 
insertChannelWithPackageName(ContentValues values, String packageName)99     private void insertChannelWithPackageName(ContentValues values, String packageName) {
100         mProvider.callingPackage = packageName;
101         mResolver.insert(Channels.CONTENT_URI, values);
102         mProvider.callingPackage = null;
103     }
104 
verifyChannelQuery(Uri channelsUri, int expectedCount, boolean expectedException)105     private void verifyChannelQuery(Uri channelsUri, int expectedCount, boolean expectedException) {
106         try {
107             verifyChannelCount(channelsUri, expectedCount);
108             if (expectedException) {
109                 fail("Query:{Uri=" + channelsUri + "} should throw exception");
110             }
111         } catch (SecurityException e) {
112             if (!expectedException) {
113                 fail("Query failed due to:" + e);
114             }
115         }
116     }
117 
verifyChannelUpdate(Uri channelsUri, ContentValues values, int expectedCount, boolean expectedException)118     private void verifyChannelUpdate(Uri channelsUri, ContentValues values,
119             int expectedCount, boolean expectedException) {
120         try {
121             int count = mResolver.update(channelsUri, values, null, null);
122             if (expectedException) {
123                 fail("Update:{Uri=" + channelsUri + "} should throw exception");
124             }
125             assertEquals(expectedCount, count);
126         } catch (SecurityException e) {
127             if (!expectedException) {
128                 fail("Update failed due to:" + e);
129             }
130         }
131     }
132 
verifyChannelDelete(Uri channelsUri, int expectedCount, boolean expectedException)133     private void verifyChannelDelete(Uri channelsUri, int expectedCount,
134             boolean expectedException) {
135         try {
136             int count = mResolver.delete(channelsUri, null, null);
137             if (expectedException) {
138                 fail("Delete:{Uri=" + channelsUri + "} should throw exception");
139             }
140             assertEquals(expectedCount, count);
141         } catch (SecurityException e) {
142             if (!expectedException) {
143                 fail("Delete failed due to:" + e);
144             }
145         }
146     }
147 
testTypePreviewQueryChannel()148     public void testTypePreviewQueryChannel() {
149         // Check if there is not any preview and non-preview channels.
150         verifyChannelCountWithPreview(0, true);
151         verifyChannelCountWithPreview(0, false);
152         // Insert one preview channel and then check if the count of preview channels is 0 and the
153         // count of non-preview channels is 0.
154         ContentValues previewChannelContentValue = createDummyChannelValues(1, true);
155         mResolver.insert(Channels.CONTENT_URI, previewChannelContentValue);
156         verifyChannelCountWithPreview(1, true);
157         verifyChannelCountWithPreview(0, false);
158         // Insert one non-preview channel and then check if the count of preview channels or
159         // non-preview channels are both 1.
160         ContentValues nonPreviewChannelContentValue = createDummyChannelValues(1, false);
161         mResolver.insert(Channels.CONTENT_URI, nonPreviewChannelContentValue);
162         verifyChannelCountWithPreview(1, true);
163         verifyChannelCountWithPreview(1, false);
164     }
165 
testPackageNameOperateChannels()166     public void testPackageNameOperateChannels() {
167         String packageName = getContext().getPackageName();
168         String otherPackageName = packageName + ".other";
169         Uri ownPackageChannelsUri = Channels.CONTENT_URI.buildUpon()
170                 .appendQueryParameter(TvContract.PARAM_PACKAGE, packageName).build();
171         Uri otherPackageChannelsUri = Channels.CONTENT_URI.buildUpon()
172                 .appendQueryParameter(TvContract.PARAM_PACKAGE, otherPackageName).build();
173 
174         // Tests with PERMISSION_ACCESS_ALL_EPG_DATA.
175         ContentValues values = createDummyChannelValues(1, false);
176         insertChannelWithPackageName(values, packageName);
177         verifyChannelQuery(ownPackageChannelsUri, 1, false);
178         ContentValues otherValues1 = createDummyChannelValues(1, false);
179         ContentValues otherValues2 = createDummyChannelValues(0, false);
180         insertChannelWithPackageName(otherValues1, otherPackageName);
181         verifyChannelQuery(otherPackageChannelsUri, 1, false);
182         insertChannelWithPackageName(otherValues2, otherPackageName);
183         verifyChannelQuery(otherPackageChannelsUri, 2, false);
184         values.remove(Channels.COLUMN_TYPE);
185         values.put(Channels.COLUMN_DISPLAY_NUMBER, "2");
186         verifyChannelUpdate(ownPackageChannelsUri, values, 1, false);
187         verifyChannelDelete(ownPackageChannelsUri, 1, false);
188         otherValues1.remove(Channels.COLUMN_TYPE);
189         otherValues1.put(Channels.COLUMN_DISPLAY_NUMBER, "2");
190         verifyChannelUpdate(otherPackageChannelsUri, otherValues1, 2, false);
191         verifyChannelDelete(otherPackageChannelsUri, 2, false);
192 
193         // Tests with PERMISSION_READ_TV_LISTINGS, without PERMISSION_ACCESS_ALL_EPG_DATA.
194         mContext.grantOrRejectPermission(PERMISSION_ACCESS_ALL_EPG_DATA, false);
195         values = createDummyChannelValues(1, false);
196         insertChannelWithPackageName(values, packageName);
197         verifyChannelQuery(ownPackageChannelsUri, 1, false);
198         otherValues1 = createDummyChannelValues(1, false);
199         otherValues2 = createDummyChannelValues(1, false);
200         ContentValues otherValues3 = createDummyChannelValues(0, false);
201         insertChannelWithPackageName(otherValues1, otherPackageName);
202         verifyChannelQuery(otherPackageChannelsUri, 1, false);
203         insertChannelWithPackageName(otherValues2, otherPackageName);
204         verifyChannelQuery(otherPackageChannelsUri, 2, false);
205         insertChannelWithPackageName(otherValues3, otherPackageName);
206         verifyChannelQuery(otherPackageChannelsUri, 2, false);
207         values.remove(Channels.COLUMN_TYPE);
208         values.put(Channels.COLUMN_DISPLAY_NUMBER, "2");
209         verifyChannelUpdate(ownPackageChannelsUri, values, 1, false);
210         verifyChannelDelete(ownPackageChannelsUri, 1, false);
211         otherValues1.remove(Channels.COLUMN_TYPE);
212         otherValues1.remove(Channels.COLUMN_PACKAGE_NAME);
213         otherValues1.put(Channels.COLUMN_DISPLAY_NUMBER, "2");
214         verifyChannelUpdate(otherPackageChannelsUri, otherValues1, 0, false);
215         verifyChannelDelete(otherPackageChannelsUri, 0, false);
216 
217         // Tests without PERMISSION_ACCESS_ALL_EPG_DATA and PERMISSION_READ_TV_LISTINGS.
218         mContext.grantOrRejectPermission(PERMISSION_READ_TV_LISTINGS, false);
219         values = createDummyChannelValues(1, false);
220         insertChannelWithPackageName(values, packageName);
221         verifyChannelQuery(ownPackageChannelsUri, 1, false);
222         otherValues1 = createDummyChannelValues(1, false);
223         insertChannelWithPackageName(otherValues1, otherPackageName);
224         verifyChannelQuery(otherPackageChannelsUri, 0, false);
225         values.remove(Channels.COLUMN_TYPE);
226         values.put(Channels.COLUMN_DISPLAY_NUMBER, "2");
227         verifyChannelUpdate(ownPackageChannelsUri, values, 1, false);
228         verifyChannelDelete(ownPackageChannelsUri, 1, false);
229         otherValues1.remove(Channels.COLUMN_TYPE);
230         otherValues1.remove(Channels.COLUMN_PACKAGE_NAME);
231         otherValues1.put(Channels.COLUMN_DISPLAY_NUMBER, "2");
232         verifyChannelUpdate(otherPackageChannelsUri, otherValues1, 0, false);
233         verifyChannelDelete(otherPackageChannelsUri, 0, false);
234     }
235 }
236