1 /*
2  * Copyright (C) 2016 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.telephony;
18 
19 import static org.mockito.ArgumentMatchers.anyInt;
20 import static org.mockito.ArgumentMatchers.anyString;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.eq;
23 import static org.mockito.Mockito.mock;
24 
25 
26 import android.Manifest;
27 import android.content.ContentUris;
28 import android.content.ContentValues;
29 import android.content.Context;
30 import android.content.SharedPreferences;
31 import android.content.pm.PackageManager;
32 import android.content.pm.ProviderInfo;
33 import android.content.res.Resources;
34 import android.database.ContentObserver;
35 import android.database.Cursor;
36 import android.net.Uri;
37 import android.os.Process;
38 import android.provider.Telephony;
39 import android.provider.Telephony.Carriers;
40 import android.provider.Telephony.SimInfo;
41 import android.telephony.SubscriptionManager;
42 import android.telephony.TelephonyManager;
43 import android.test.mock.MockContentResolver;
44 import android.test.mock.MockContext;
45 import android.test.suitebuilder.annotation.SmallTest;
46 import android.text.TextUtils;
47 import android.util.Log;
48 
49 import androidx.test.InstrumentationRegistry;
50 
51 import junit.framework.TestCase;
52 
53 import org.junit.Test;
54 import org.mockito.ArgumentMatchers;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 
58 import java.lang.reflect.Field;
59 import java.util.Arrays;
60 import java.util.List;
61 import java.util.stream.IntStream;
62 
63 /**
64  * Tests for testing CRUD operations of TelephonyProvider.
65  * Uses a MockContentResolver to get permission WRITE_APN_SETTINGS in order to test insert/delete
66  * Uses TelephonyProviderTestable to set up in-memory database
67  *
68  * Build, install and run the tests by running the commands below:
69  *     runtest --path <dir or file>
70  *     runtest --path <dir or file> --test-method <testMethodName>
71  *     e.g.)
72  *         runtest --path tests/src/com/android/providers/telephony/TelephonyProviderTest.java \
73  *                 --test-method testInsertCarriers
74  */
75 public class TelephonyProviderTest extends TestCase {
76     private static final String TAG = "TelephonyProviderTest";
77 
78     private MockContextWithProvider mContext;
79     private MockContentResolver mContentResolver;
80     private TelephonyProviderTestable mTelephonyProviderTestable;
81 
82     private int notifyChangeCount;
83     private int notifyChangeRestoreCount;
84     private int notifyWfcCount;
85     private int notifyWfcCountWithTestSubId;
86 
87     private static final String TEST_SUBID = "1";
88     private static final String TEST_OPERATOR = "123456";
89     private static final String TEST_MCC = "123";
90     private static final String TEST_MNC = "456";
91     private static final String TEST_SPN = TelephonyProviderTestable.TEST_SPN;
92     private static final int TEST_CARRIERID = 1;
93 
94     // Used to test the path for URL_TELEPHONY_USING_SUBID with subid 1
95     private static final Uri CONTENT_URI_WITH_SUBID = Uri.parse(
96             "content://telephony/carriers/subId/" + TEST_SUBID);
97 
98     // Used to test the "restore to default"
99     private static final Uri URL_RESTOREAPN_USING_SUBID = Uri.parse(
100             "content://telephony/carriers/restore/subId/" + TEST_SUBID);
101     // Used to test the preferred apn
102     private static final Uri URL_PREFERAPN_USING_SUBID = Uri.parse(
103             "content://telephony/carriers/preferapn/subId/" + TEST_SUBID);
104     private static final Uri URL_WFC_ENABLED_USING_SUBID = Uri.parse(
105             "content://telephony/siminfo/" + TEST_SUBID);
106     private static final Uri URL_SIM_APN_LIST = Uri.parse(
107         "content://telephony/carriers/sim_apn_list");
108 
109     private static final String COLUMN_APN_ID = "apn_id";
110 
111     // Constants for DPC related tests.
112     private static final Uri URI_DPC = Uri.parse("content://telephony/carriers/dpc");
113     private static final Uri URI_TELEPHONY = Carriers.CONTENT_URI;
114     private static final Uri URI_FILTERED = Uri.parse("content://telephony/carriers/filtered");
115     private static final Uri URI_ENFORCE_MANAGED= Uri.parse("content://telephony/carriers/enforce_managed");
116     private static final String ENFORCED_KEY = "enforced";
117 
118     /**
119      * This is used to give the TelephonyProviderTest a mocked context which takes a
120      * TelephonyProvider and attaches it to the ContentResolver with telephony authority.
121      * The mocked context also gives WRITE_APN_SETTINGS permissions
122      */
123     private class MockContextWithProvider extends MockContext {
124         private final MockContentResolver mResolver;
125         private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
126 
127         private final List<String> GRANTED_PERMISSIONS = Arrays.asList(
128                 Manifest.permission.MODIFY_PHONE_STATE, Manifest.permission.WRITE_APN_SETTINGS,
129                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
130 
MockContextWithProvider(TelephonyProvider telephonyProvider)131         public MockContextWithProvider(TelephonyProvider telephonyProvider) {
132             mResolver = new MockContentResolver() {
133                 @Override
134                 public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
135                         int userHandle) {
136                     notifyChangeCount++;
137                     if (URL_RESTOREAPN_USING_SUBID.equals(uri)) {
138                         notifyChangeRestoreCount++;
139                     } else if (SubscriptionManager.WFC_ENABLED_CONTENT_URI.equals(uri)) {
140                         notifyWfcCount++;
141                     } else if (URL_WFC_ENABLED_USING_SUBID.equals(uri)) {
142                         notifyWfcCountWithTestSubId++;
143                     }
144                 }
145             };
146 
147             // return test subId 0 for all operators
148             doReturn(TEST_OPERATOR).when(mTelephonyManager).getSimOperator(anyInt());
149 
150             doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
151             doReturn(TEST_OPERATOR).when(mTelephonyManager).getSimOperator();
152             doReturn(TEST_CARRIERID).when(mTelephonyManager).getSimCarrierId();
153 
154             // Add authority="telephony" to given telephonyProvider
155             ProviderInfo providerInfo = new ProviderInfo();
156             providerInfo.authority = "telephony";
157 
158             // Add context to given telephonyProvider
159             telephonyProvider.attachInfoForTesting(this, providerInfo);
160             Log.d(TAG, "MockContextWithProvider: telephonyProvider.getContext(): "
161                     + telephonyProvider.getContext());
162 
163             // Add given telephonyProvider to mResolver with authority="telephony" so that
164             // mResolver can send queries to mTelephonyProvider
165             mResolver.addProvider("telephony", telephonyProvider);
166             Log.d(TAG, "MockContextWithProvider: Add telephonyProvider to mResolver");
167         }
168 
169         @Override
getSystemService(String name)170         public Object getSystemService(String name) {
171             if (name.equals(Context.TELEPHONY_SERVICE)) {
172                 Log.d(TAG, "getSystemService: returning mock TM");
173                 return mTelephonyManager;
174             } else {
175                 Log.d(TAG, "getSystemService: returning null");
176                 return null;
177             }
178         }
179 
180         @Override
getSystemServiceName(Class<?> serviceClass)181         public String getSystemServiceName(Class<?> serviceClass) {
182             if (serviceClass.equals(TelephonyManager.class)) {
183               return Context.TELEPHONY_SERVICE;
184             } else {
185                 Log.d(TAG, "getSystemServiceName: returning null");
186                 return null;
187             }
188         }
189 
190         @Override
getResources()191         public Resources getResources() {
192             Log.d(TAG, "getResources: returning null");
193             return null;
194         }
195 
196         @Override
getContentResolver()197         public MockContentResolver getContentResolver() {
198             return mResolver;
199         }
200 
201         @Override
getSharedPreferences(String name, int mode)202         public SharedPreferences getSharedPreferences(String name, int mode) {
203             return InstrumentationRegistry.getContext().getSharedPreferences(name, mode);
204         }
205 
206         // Gives permission to write to the APN table within the MockContext
207         @Override
checkCallingOrSelfPermission(String permission)208         public int checkCallingOrSelfPermission(String permission) {
209             if (GRANTED_PERMISSIONS.contains(permission)) {
210                 Log.d(TAG, "checkCallingOrSelfPermission: permission=" + permission
211                         + ", returning PackageManager.PERMISSION_GRANTED");
212                 return PackageManager.PERMISSION_GRANTED;
213             } else {
214                 Log.d(TAG, "checkCallingOrSelfPermission: permission=" + permission
215                         + ", returning PackageManager.PERMISSION_DENIED");
216                 return PackageManager.PERMISSION_DENIED;
217             }
218         }
219     }
220 
221     @Override
setUp()222     protected void setUp() throws Exception {
223         super.setUp();
224         MockitoAnnotations.initMocks(this);
225         mTelephonyProviderTestable = new TelephonyProviderTestable();
226         mContext = new MockContextWithProvider(mTelephonyProviderTestable);
227         mContentResolver = (MockContentResolver) mContext.getContentResolver();
228         notifyChangeCount = 0;
229         notifyChangeRestoreCount = 0;
230     }
231 
232     @Override
tearDown()233     protected void tearDown() throws Exception {
234         super.tearDown();
235         mTelephonyProviderTestable.closeDatabase();
236     }
237 
238     /**
239      * Test bulk inserting, querying;
240      * Verify that the inserted values match the result of the query.
241      */
242     @Test
243     @SmallTest
testBulkInsertCarriers()244     public void testBulkInsertCarriers() {
245         // insert 2 test contentValues
246         ContentValues contentValues = new ContentValues();
247         final String insertApn = "exampleApnName";
248         final String insertName = "exampleName";
249         final Integer insertCurrent = 1;
250         final String insertNumeric = TEST_OPERATOR;
251         contentValues.put(Carriers.APN, insertApn);
252         contentValues.put(Carriers.NAME, insertName);
253         contentValues.put(Carriers.CURRENT, insertCurrent);
254         contentValues.put(Carriers.NUMERIC, insertNumeric);
255 
256         ContentValues contentValues2 = new ContentValues();
257         final String insertApn2 = "exampleApnName2";
258         final String insertName2 = "exampleName2";
259         final Integer insertCurrent2 = 1;
260         final String insertNumeric2 = "789123";
261         contentValues2.put(Carriers.APN, insertApn2);
262         contentValues2.put(Carriers.NAME, insertName2);
263         contentValues2.put(Carriers.CURRENT, insertCurrent2);
264         contentValues2.put(Carriers.NUMERIC, insertNumeric2);
265 
266         Log.d(TAG, "testInsertCarriers: Bulk inserting contentValues=" + contentValues
267                 + ", " + contentValues2);
268         ContentValues[] values = new ContentValues[]{ contentValues, contentValues2 };
269         int rows = mContentResolver.bulkInsert(Carriers.CONTENT_URI, values);
270         assertEquals(2, rows);
271         assertEquals(1, notifyChangeCount);
272 
273         // get values in table
274         final String[] testProjection =
275         {
276             Carriers.APN,
277             Carriers.NAME,
278             Carriers.CURRENT,
279         };
280         final String selection = Carriers.NUMERIC + "=?";
281         String[] selectionArgs = { insertNumeric };
282         Log.d(TAG, "testInsertCarriers query projection: " + testProjection
283                 + "\ntestInsertCarriers selection: " + selection
284                 + "\ntestInsertCarriers selectionArgs: " + selectionArgs);
285         Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI,
286                 testProjection, selection, selectionArgs, null);
287 
288         // verify that inserted values match results of query
289         assertNotNull(cursor);
290         assertEquals(1, cursor.getCount());
291         cursor.moveToFirst();
292         final String resultApn = cursor.getString(0);
293         final String resultName = cursor.getString(1);
294         final Integer resultCurrent = cursor.getInt(2);
295         assertEquals(insertApn, resultApn);
296         assertEquals(insertName, resultName);
297         assertEquals(insertCurrent, resultCurrent);
298     }
299 
300     /**
301      * Test inserting, querying, and deleting values in carriers table.
302      * Verify that the inserted values match the result of the query and are deleted.
303      */
304     @Test
305     @SmallTest
testInsertCarriers()306     public void testInsertCarriers() {
307         doSimpleTestForUri(Carriers.CONTENT_URI);
308     }
309 
310     /**
311      * Test migrating int-based MCC/MNCs over to Strings in the sim info table
312      */
313     @Test
314     @SmallTest
testMccMncMigration()315     public void testMccMncMigration() {
316         CarrierIdProviderTestable carrierIdProvider = new CarrierIdProviderTestable();
317         carrierIdProvider.initializeForTesting(mContext);
318         mContentResolver.addProvider(Telephony.CarrierId.All.CONTENT_URI.getAuthority(),
319                 carrierIdProvider);
320         // Insert a few values into the carrier ID db
321         List<String> mccMncs = Arrays.asList("99910", "999110", "999060", "99905");
322         ContentValues[] carrierIdMccMncs = mccMncs.stream()
323                 .map((mccMnc) -> {
324                     ContentValues cv = new ContentValues(1);
325                     cv.put(Telephony.CarrierId.All.MCCMNC, mccMnc);
326                     return cv;
327                 }).toArray(ContentValues[]::new);
328         mContentResolver.bulkInsert(Telephony.CarrierId.All.CONTENT_URI, carrierIdMccMncs);
329 
330         // Populate the sim info db with int-format entries
331         ContentValues[] existingSimInfoEntries = IntStream.range(0, mccMncs.size())
332                 .mapToObj((idx) -> {
333                     int mcc = Integer.valueOf(mccMncs.get(idx).substring(0, 3));
334                     int mnc = Integer.valueOf(mccMncs.get(idx).substring(3));
335                     ContentValues cv = new ContentValues(4);
336                     cv.put(SubscriptionManager.MCC, mcc);
337                     cv.put(SubscriptionManager.MNC, mnc);
338                     cv.put(SubscriptionManager.ICC_ID, String.valueOf(idx));
339                     cv.put(SubscriptionManager.CARD_ID, String.valueOf(idx));
340                     return cv;
341         }).toArray(ContentValues[]::new);
342 
343         mContentResolver.bulkInsert(SimInfo.CONTENT_URI, existingSimInfoEntries);
344 
345         // Run the upgrade helper on all the sim info entries.
346         String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
347                 SubscriptionManager.MCC, SubscriptionManager.MNC,
348                 SubscriptionManager.MCC_STRING, SubscriptionManager.MNC_STRING};
349         try (Cursor c = mContentResolver.query(SimInfo.CONTENT_URI, proj,
350                 null, null, null)) {
351             while (c.moveToNext()) {
352                 TelephonyProvider.fillInMccMncStringAtCursor(mContext,
353                         mTelephonyProviderTestable.getWritableDatabase(), c);
354             }
355         }
356 
357         // Loop through and make sure that everything got filled in correctly.
358         try (Cursor c = mContentResolver.query(SimInfo.CONTENT_URI, proj,
359                 null, null, null)) {
360             while (c.moveToNext()) {
361                 String mcc = c.getString(c.getColumnIndexOrThrow(SubscriptionManager.MCC_STRING));
362                 String mnc = c.getString(c.getColumnIndexOrThrow(SubscriptionManager.MNC_STRING));
363                 assertTrue(mccMncs.contains(mcc + mnc));
364             }
365         }
366     }
367 
368     /**
369      * Test updating values in carriers table. Verify that when update hits a conflict using URL_ID
370      * we merge the rows.
371      */
372     @Test
373     @SmallTest
testUpdateConflictingCarriers()374     public void testUpdateConflictingCarriers() {
375         // insert 2 test contentValues
376         ContentValues contentValues = new ContentValues();
377         final String insertApn = "exampleApnName";
378         final String insertName = "exampleName";
379         final String insertNumeric = TEST_OPERATOR;
380         final String insertMcc = TEST_MCC;
381         final String insertMnc = TEST_MNC;
382         contentValues.put(Carriers.APN, insertApn);
383         contentValues.put(Carriers.NAME, insertName);
384         contentValues.put(Carriers.NUMERIC, insertNumeric);
385         contentValues.put(Carriers.MCC, insertMcc);
386         contentValues.put(Carriers.MNC, insertMnc);
387 
388         ContentValues contentValues2 = new ContentValues();
389         final String insertName2 = "exampleName2";
390         contentValues2.put(Carriers.NAME, insertName2);
391 
392         Uri row1 = mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
393         Uri row2 = mContentResolver.insert(Carriers.CONTENT_URI, contentValues2);
394 
395         // use URL_ID to update row2 apn so it conflicts with row1
396         Log.d(TAG, "testUpdateConflictingCarriers: update row2=" + row2);
397         contentValues.put(Carriers.NAME, insertName2);
398         mContentResolver.update(row2, contentValues, null, null);
399 
400         // verify that only 1 APN now exists and it has the fields from row1 and row2
401         final String[] testProjection =
402         {
403             Carriers.APN,
404             Carriers.NAME,
405             Carriers.NUMERIC,
406             Carriers.MCC,
407             Carriers.MNC
408         };
409         Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection, null, null,
410                 null);
411         assertNotNull(cursor);
412         assertEquals(1, cursor.getCount());
413         cursor.moveToFirst();
414         assertEquals(insertApn, cursor.getString(0 /* APN */));
415         assertEquals(insertName2, cursor.getString(1 /* NAME */));
416         assertEquals(insertNumeric, cursor.getString(2 /* NUMERIC */));
417         assertEquals(insertMcc, cursor.getString(3 /* MCC */));
418         assertEquals(insertMnc, cursor.getString(4 /* MNC */));
419     }
420 
421     /**
422      * Test inserting, querying, and deleting values in carriers table.
423      * Verify that the inserted values match the result of the query and are deleted.
424      */
425     @Test
426     @SmallTest
testInsertCarriersWithSubId()427     public void testInsertCarriersWithSubId() {
428         doSimpleTestForUri(CONTENT_URI_WITH_SUBID);
429     }
430 
doSimpleTestForUri(Uri uri)431     private void doSimpleTestForUri(Uri uri) {
432         // insert test contentValues
433         ContentValues contentValues = new ContentValues();
434         final String insertApn = "exampleApnName";
435         final String insertName = "exampleName";
436         final String insertNumeric = TEST_OPERATOR;
437         contentValues.put(Carriers.APN, insertApn);
438         contentValues.put(Carriers.NAME, insertName);
439         contentValues.put(Carriers.NUMERIC, insertNumeric);
440 
441         Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues);
442         mContentResolver.insert(uri, contentValues);
443 
444         // get values in table
445         final String[] testProjection =
446         {
447             Carriers.APN,
448             Carriers.NAME,
449         };
450         final String selection = Carriers.NUMERIC + "=?";
451         String[] selectionArgs = { insertNumeric };
452         Log.d(TAG, "testInsertCarriers query projection: " + testProjection
453                 + "\ntestInsertCarriers selection: " + selection
454                 + "\ntestInsertCarriers selectionArgs: " + selectionArgs);
455         Cursor cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
456 
457         // verify that inserted values match results of query
458         assertNotNull(cursor);
459         assertEquals(1, cursor.getCount());
460         cursor.moveToFirst();
461         final String resultApn = cursor.getString(0);
462         final String resultName = cursor.getString(1);
463         assertEquals(insertApn, resultApn);
464         assertEquals(insertName, resultName);
465 
466         // delete test content
467         final String selectionToDelete = Carriers.NUMERIC + "=?";
468         String[] selectionArgsToDelete = { insertNumeric };
469         Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
470                 + "testInsertCarriers selectionArgs: " + selectionArgs);
471         int numRowsDeleted = mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
472         assertEquals(1, numRowsDeleted);
473 
474         // verify that deleted values are gone
475         cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
476         assertEquals(0, cursor.getCount());
477     }
478 
479     @Test
480     @SmallTest
testOwnedBy()481     public void testOwnedBy() {
482         // insert test contentValues
483         ContentValues contentValues = new ContentValues();
484         final String insertApn = "exampleApnName";
485         final String insertName = "exampleName";
486         final String insertNumeric = TEST_OPERATOR;
487         final Integer insertOwnedBy = Carriers.OWNED_BY_OTHERS;
488         contentValues.put(Carriers.APN, insertApn);
489         contentValues.put(Carriers.NAME, insertName);
490         contentValues.put(Carriers.NUMERIC, insertNumeric);
491         contentValues.put(Carriers.OWNED_BY, insertOwnedBy);
492 
493         Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues);
494         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
495 
496         // get values in table
497         final String[] testProjection =
498         {
499             Carriers.APN,
500             Carriers.NAME,
501             Carriers.OWNED_BY,
502         };
503         final String selection = Carriers.NUMERIC + "=?";
504         String[] selectionArgs = { insertNumeric };
505         Log.d(TAG, "testInsertCarriers query projection: " + testProjection
506                 + "\ntestInsertCarriers selection: " + selection
507                 + "\ntestInsertCarriers selectionArgs: " + selectionArgs);
508         Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI,
509                 testProjection, selection, selectionArgs, null);
510 
511         // verify that inserted values match results of query
512         assertNotNull(cursor);
513         assertEquals(1, cursor.getCount());
514         cursor.moveToFirst();
515         final String resultApn = cursor.getString(0);
516         final String resultName = cursor.getString(1);
517         final Integer resultOwnedBy = cursor.getInt(2);
518         assertEquals(insertApn, resultApn);
519         assertEquals(insertName, resultName);
520         // Verify that OWNED_BY is force set to OWNED_BY_OTHERS when inserted with general uri
521         assertEquals(insertOwnedBy, resultOwnedBy);
522 
523         // delete test content
524         final String selectionToDelete = Carriers.NUMERIC + "=?";
525         String[] selectionArgsToDelete = { insertNumeric };
526         Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
527                 + "testInsertCarriers selectionArgs: " + selectionArgs);
528         int numRowsDeleted = mContentResolver.delete(Carriers.CONTENT_URI,
529                 selectionToDelete, selectionArgsToDelete);
530         assertEquals(1, numRowsDeleted);
531 
532         // verify that deleted values are gone
533         cursor = mContentResolver.query(Carriers.CONTENT_URI,
534                 testProjection, selection, selectionArgs, null);
535         assertEquals(0, cursor.getCount());
536     }
537 
538     /**
539      * Test inserting, querying, and deleting values in carriers table.
540      * Verify that the inserted values match the result of the query and are deleted.
541      */
542     @Test
543     @SmallTest
testSimTable()544     public void testSimTable() {
545         // insert test contentValues
546         ContentValues contentValues = new ContentValues();
547         final int insertSubId = 11;
548         final String insertDisplayName = "exampleDisplayName";
549         final String insertCarrierName = "exampleCarrierName";
550         final String insertIccId = "exampleIccId";
551         final String insertCardId = "exampleCardId";
552         final int insertProfileClass = SubscriptionManager.PROFILE_CLASS_DEFAULT;
553         contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
554         contentValues.put(SubscriptionManager.DISPLAY_NAME, insertDisplayName);
555         contentValues.put(SubscriptionManager.CARRIER_NAME, insertCarrierName);
556         contentValues.put(SubscriptionManager.ICC_ID, insertIccId);
557         contentValues.put(SubscriptionManager.CARD_ID, insertCardId);
558         contentValues.put(SubscriptionManager.PROFILE_CLASS, insertProfileClass);
559 
560         Log.d(TAG, "testSimTable Inserting contentValues: " + contentValues);
561         mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
562 
563         // get values in table
564         final String[] testProjection =
565         {
566             SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
567             SubscriptionManager.CARRIER_NAME,
568             SubscriptionManager.CARD_ID,
569             SubscriptionManager.PROFILE_CLASS,
570         };
571         final String selection = SubscriptionManager.DISPLAY_NAME + "=?";
572         String[] selectionArgs = { insertDisplayName };
573         Log.d(TAG,"\ntestSimTable selection: " + selection
574                 + "\ntestSimTable selectionArgs: " + selectionArgs.toString());
575         Cursor cursor = mContentResolver.query(SimInfo.CONTENT_URI,
576                 testProjection, selection, selectionArgs, null);
577 
578         // verify that inserted values match results of query
579         assertNotNull(cursor);
580         assertEquals(1, cursor.getCount());
581         cursor.moveToFirst();
582         final int resultSubId = cursor.getInt(0);
583         final String resultCarrierName = cursor.getString(1);
584         final String resultCardId = cursor.getString(2);
585         final int resultProfileClass = cursor.getInt(3);
586         assertEquals(insertSubId, resultSubId);
587         assertEquals(insertCarrierName, resultCarrierName);
588         assertEquals(insertCardId, resultCardId);
589         assertEquals(insertProfileClass, resultProfileClass);
590 
591         // delete test content
592         final String selectionToDelete = SubscriptionManager.DISPLAY_NAME + "=?";
593         String[] selectionArgsToDelete = { insertDisplayName };
594         Log.d(TAG, "testSimTable deleting selection: " + selectionToDelete
595                 + "testSimTable selectionArgs: " + selectionArgs);
596         int numRowsDeleted = mContentResolver.delete(SimInfo.CONTENT_URI,
597                 selectionToDelete, selectionArgsToDelete);
598         assertEquals(1, numRowsDeleted);
599 
600         // verify that deleted values are gone
601         cursor = mContentResolver.query(SimInfo.CONTENT_URI,
602                 testProjection, selection, selectionArgs, null);
603         assertEquals(0, cursor.getCount());
604     }
605 
parseIdFromInsertedUri(Uri uri)606     private int parseIdFromInsertedUri(Uri uri) throws NumberFormatException {
607         return (uri != null) ? Integer.parseInt(uri.getLastPathSegment()) : -1;
608     }
609 
insertApnRecord(Uri uri, String apn, String name, int current, String numeric)610     private int insertApnRecord(Uri uri, String apn, String name, int current, String numeric) {
611         ContentValues contentValues = new ContentValues();
612         contentValues.put(Carriers.APN, apn);
613         contentValues.put(Carriers.NAME, name);
614         contentValues.put(Carriers.CURRENT, current);
615         contentValues.put(Carriers.NUMERIC, numeric);
616         Uri resultUri = mContentResolver.insert(uri, contentValues);
617         return parseIdFromInsertedUri(resultUri);
618     }
619 
620     /**
621      * Test URL_ENFORCE_MANAGED and URL_FILTERED works correctly.
622      * Verify that when enforce is set true via URL_ENFORCE_MANAGED, only DPC records are returned
623      * for URL_FILTERED and URL_FILTERED_ID.
624      * Verify that when enforce is set false via URL_ENFORCE_MANAGED, only non-DPC records
625      * are returned for URL_FILTERED and URL_FILTERED_ID.
626      */
627     @Test
628     @SmallTest
testEnforceManagedUri()629     public void testEnforceManagedUri() {
630         mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
631 
632         final int current = 1;
633         final String numeric = TEST_OPERATOR;
634 
635         // Insert DPC record.
636         final String dpcRecordApn = "exampleApnNameDPC";
637         final String dpcRecordName = "exampleNameDPC";
638         final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
639                 current, numeric);
640 
641         // Insert non-DPC record.
642         final String othersRecordApn = "exampleApnNameOTHERS";
643         final String othersRecordName = "exampleNameDPOTHERS";
644         final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
645                 current, numeric);
646 
647         // Set enforced = false.
648         ContentValues enforceManagedValue = new ContentValues();
649         enforceManagedValue.put(ENFORCED_KEY, false);
650         Log.d(TAG, "testEnforceManagedUri Updating enforced = false: "
651                 + enforceManagedValue);
652         mContentResolver.update(URI_ENFORCE_MANAGED, enforceManagedValue, "", new String[]{});
653 
654         // Verify that enforced is set to false in TelephonyProvider.
655         Cursor enforceCursor = mContentResolver.query(URI_ENFORCE_MANAGED,
656             null, null, null, null);
657         assertNotNull(enforceCursor);
658         assertEquals(1, enforceCursor.getCount());
659         enforceCursor.moveToFirst();
660         assertEquals(0, enforceCursor.getInt(0));
661 
662         // Verify URL_FILTERED query only returns non-DPC record.
663         final String[] testProjection =
664         {
665             Carriers._ID,
666             Carriers.OWNED_BY
667         };
668         final String selection = Carriers.NUMERIC + "=?";
669         final String[] selectionArgs = { numeric };
670         final Cursor cursorNotEnforced = mContentResolver.query(URI_FILTERED,
671             testProjection, selection, selectionArgs, null);
672         assertNotNull(cursorNotEnforced);
673         assertEquals(1, cursorNotEnforced.getCount());
674         cursorNotEnforced.moveToFirst();
675         assertEquals(othersRecordId, cursorNotEnforced.getInt(0));
676         assertEquals(Carriers.OWNED_BY_OTHERS, cursorNotEnforced.getInt(1));
677 
678         // Verify that URL_FILTERED_ID cannot get DPC record.
679         Cursor cursorNotEnforcedDpc = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
680                 Integer.toString(dpcRecordId)), null, null, null, null);
681         assertNotNull(cursorNotEnforcedDpc);
682         assertTrue(cursorNotEnforcedDpc.getCount() == 0);
683         // Verify that URL_FILTERED_ID can get non-DPC record.
684         Cursor cursorNotEnforcedOthers = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
685                 Integer.toString(othersRecordId)), null, null, null, null);
686         assertNotNull(cursorNotEnforcedOthers);
687         assertTrue(cursorNotEnforcedOthers.getCount() == 1);
688 
689         // Set enforced = true.
690         enforceManagedValue.put(ENFORCED_KEY, true);
691         Log.d(TAG, "testEnforceManagedUri Updating enforced = true: "
692                 + enforceManagedValue);
693         mContentResolver.update(URI_ENFORCE_MANAGED, enforceManagedValue, "", new String[]{});
694 
695         // Verify that enforced is set to true in TelephonyProvider.
696         enforceCursor = mContentResolver.query(URI_ENFORCE_MANAGED,
697             null, null, null, null);
698         assertNotNull(enforceCursor);
699         assertEquals(1, enforceCursor.getCount());
700         enforceCursor.moveToFirst();
701         assertEquals(1, enforceCursor.getInt(0));
702 
703         // Verify URL_FILTERED query only returns DPC record.
704         final Cursor cursorEnforced = mContentResolver.query(URI_FILTERED,
705                 testProjection, selection, selectionArgs, null);
706         assertNotNull(cursorEnforced);
707         assertEquals(1, cursorEnforced.getCount());
708         cursorEnforced.moveToFirst();
709         assertEquals(dpcRecordId, cursorEnforced.getInt(0));
710         assertEquals(Carriers.OWNED_BY_DPC, cursorEnforced.getInt(1));
711 
712         // Verify that URL_FILTERED_ID can get DPC record.
713         cursorNotEnforcedDpc = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
714                 Integer.toString(dpcRecordId)), null, null, null, null);
715         assertNotNull(cursorNotEnforcedDpc);
716         assertTrue(cursorNotEnforcedDpc.getCount() == 1);
717         // Verify that URL_FILTERED_ID cannot get non-DPC record.
718         cursorNotEnforcedOthers = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
719                 Integer.toString(othersRecordId)), null, null, null, null);
720         assertNotNull(cursorNotEnforcedOthers);
721         assertTrue(cursorNotEnforcedOthers.getCount() == 0);
722 
723         // Delete testing records.
724         int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
725         assertEquals(1, numRowsDeleted);
726 
727         numRowsDeleted = mContentResolver.delete(
728                 ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
729         assertEquals(1, numRowsDeleted);
730     }
731 
queryFullTestApnRecord(Uri uri, String numeric)732     private Cursor queryFullTestApnRecord(Uri uri, String numeric) {
733         final String selection = Carriers.NUMERIC + "=?";
734         String[] selectionArgs = { numeric };
735         final String[] testProjection =
736                 {
737                         Carriers._ID,
738                         Carriers.APN,
739                         Carriers.NAME,
740                         Carriers.CURRENT,
741                         Carriers.OWNED_BY,
742                 };
743         return mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
744     }
745 
746     @Test
747     @SmallTest
748     /**
749      * Test URL_TELEPHONY cannot insert, query, update or delete DPC records.
750      */
testTelephonyUriDpcRecordAccessControl()751     public void testTelephonyUriDpcRecordAccessControl() {
752         mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
753 
754         final int current = 1;
755         final String numeric = TEST_OPERATOR;
756         final String selection = Carriers.NUMERIC + "=?";
757         final String[] selectionArgs = { numeric };
758 
759         // Insert DPC record.
760         final String dpcRecordApn = "exampleApnNameDPC";
761         final String dpcRecordName = "exampleNameDPC";
762         final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
763                 current, numeric);
764 
765         // Insert non-DPC record.
766         final String othersRecordApn = "exampleApnNameOTHERS";
767         final String othersRecordName = "exampleNameDPOTHERS";
768         final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
769                 current, numeric);
770 
771         // Verify URL_TELEPHONY query only returns non-DPC record.
772         final Cursor cursorTelephony = queryFullTestApnRecord(URI_TELEPHONY, numeric);
773         assertNotNull(cursorTelephony);
774         assertEquals(1, cursorTelephony.getCount());
775         cursorTelephony.moveToFirst();
776         assertApnEquals(cursorTelephony, othersRecordId, othersRecordApn, othersRecordName,
777                 current, Carriers.OWNED_BY_OTHERS);
778 
779         // Verify URI_TELEPHONY updates only non-DPC records.
780         ContentValues contentValuesOthersUpdate = new ContentValues();
781         final String othersRecordUpdatedApn = "exampleApnNameOTHERSUpdated";
782         final String othersRecordUpdatedName = "exampleNameOTHERSpdated";
783         contentValuesOthersUpdate.put(Carriers.APN, othersRecordUpdatedApn);
784         contentValuesOthersUpdate.put(Carriers.NAME, othersRecordUpdatedName);
785 
786         final int updateCount = mContentResolver.update(URI_TELEPHONY, contentValuesOthersUpdate,
787                 selection, selectionArgs);
788         assertEquals(1, updateCount);
789         final Cursor cursorNonDPCUpdate = queryFullTestApnRecord(URI_TELEPHONY, numeric);
790         final Cursor cursorDPCUpdate = queryFullTestApnRecord(URI_DPC, numeric);
791 
792         // Verify that non-DPC records are updated.
793         assertNotNull(cursorNonDPCUpdate);
794         assertEquals(1, cursorNonDPCUpdate.getCount());
795         cursorNonDPCUpdate.moveToFirst();
796         assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordUpdatedApn,
797                 othersRecordUpdatedName);
798 
799         // Verify that DPC records are not updated.
800         assertNotNull(cursorDPCUpdate);
801         assertEquals(1, cursorDPCUpdate.getCount());
802         cursorDPCUpdate.moveToFirst();
803         assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordApn, dpcRecordName);
804 
805         // Verify URI_TELEPHONY deletes only non-DPC records.
806         int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
807         assertEquals(1, numRowsDeleted);
808         final Cursor cursorTelephonyRemaining = queryFullTestApnRecord(URI_TELEPHONY, numeric);
809         assertNotNull(cursorTelephonyRemaining);
810         assertEquals(0, cursorTelephonyRemaining.getCount());
811         final Cursor cursorDPCDeleted = queryFullTestApnRecord(URI_DPC, numeric);
812         assertNotNull(cursorDPCDeleted);
813         assertEquals(1, cursorDPCDeleted.getCount());
814 
815         // Delete remaining test records.
816         numRowsDeleted = mContentResolver.delete(
817                 ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
818         assertEquals(1, numRowsDeleted);
819     }
820 
821     /**
822      * Test URL_DPC cannot insert or query non-DPC records.
823      * Test URL_DPC_ID cannot update or delete non-DPC records.
824      */
825     @Test
826     @SmallTest
testDpcUri()827     public void testDpcUri() {
828         int dpcRecordId = 0, othersRecordId = 0;
829         try {
830             mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
831 
832             final int current = 1;
833             final String numeric = TEST_OPERATOR;
834 
835             // Insert DPC record.
836             final String dpcRecordApn = "exampleApnNameDPC";
837             final String dpcRecordName = "exampleNameDPC";
838             dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
839                     current, numeric);
840 
841             // Insert non-DPC record.
842             final String othersRecordApn = "exampleApnNameOTHERS";
843             final String othersRecordName = "exampleNameDPOTHERS";
844             othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
845                     current, numeric);
846 
847             Log.d(TAG, "testDPCIdUri Id for inserted DPC record: " + dpcRecordId);
848             Log.d(TAG, "testDPCIdUri Id for inserted non-DPC record: " + othersRecordId);
849 
850             // Verify that URI_DPC query only returns DPC records.
851             final Cursor cursorDPC = queryFullTestApnRecord(URI_DPC, numeric);
852             assertNotNull(cursorDPC);
853             assertEquals(1, cursorDPC.getCount());
854             cursorDPC.moveToFirst();
855             assertApnEquals(cursorDPC, dpcRecordId, dpcRecordApn, dpcRecordName, current,
856                     Carriers.OWNED_BY_DPC);
857 
858             // Verify that URI_DPC_ID updates only DPC records.
859             ContentValues contentValuesDpcUpdate = new ContentValues();
860             final String dpcRecordUpdatedApn = "exampleApnNameDPCUpdated";
861             final String dpcRecordUpdatedName = "exampleNameDPCUpdated";
862             contentValuesDpcUpdate.put(Carriers.APN, dpcRecordUpdatedApn);
863             contentValuesDpcUpdate.put(Carriers.NAME, dpcRecordUpdatedName);
864             final int updateCount = mContentResolver.update(
865                     ContentUris.withAppendedId(URI_DPC, dpcRecordId),
866                     contentValuesDpcUpdate, null, null);
867             assertEquals(1, updateCount);
868             final Cursor cursorNonDPCUpdate = queryFullTestApnRecord(URI_TELEPHONY, numeric);
869             final Cursor cursorDPCUpdate = queryFullTestApnRecord(URI_DPC, numeric);
870 
871             // Verify that non-DPC records are not updated.
872             assertNotNull(cursorNonDPCUpdate);
873             assertEquals(1, cursorNonDPCUpdate.getCount());
874             cursorNonDPCUpdate.moveToFirst();
875             assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordApn, othersRecordName);
876 
877             // Verify that DPC records are updated.
878             assertNotNull(cursorDPCUpdate);
879             assertEquals(1, cursorDPCUpdate.getCount());
880             cursorDPCUpdate.moveToFirst();
881             assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordUpdatedApn,
882                     dpcRecordUpdatedName);
883 
884             // Test URI_DPC_ID deletes only DPC records.
885             int numRowsDeleted = mContentResolver.delete(
886                     ContentUris.withAppendedId(URI_DPC, dpcRecordId), null, null);
887             assertEquals(1, numRowsDeleted);
888             numRowsDeleted = mContentResolver.delete(
889                     ContentUris.withAppendedId(URI_DPC, dpcRecordId), null, null);
890             assertEquals(0, numRowsDeleted);
891 
892         } finally {
893             // Delete remaining test records.
894             int numRowsDeleted = mContentResolver.delete(
895                     ContentUris.withAppendedId(URI_TELEPHONY, othersRecordId), null, null);
896             assertEquals(1, numRowsDeleted);
897         }
898     }
899 
assertApnEquals(Cursor cursor, Object... values)900     private void assertApnEquals(Cursor cursor, Object... values) {
901         assertTrue(values.length <= cursor.getColumnCount());
902         for (int i = 0; i < values.length; i ++) {
903             if (values[i] instanceof Integer) {
904                 assertEquals(values[i], cursor.getInt(i));
905             } else if (values[i] instanceof String) {
906                 assertEquals(values[i], cursor.getString(i));
907             } else {
908                 fail("values input type not correct");
909             }
910         }
911     }
912 
913     /**
914      * Test URL_DPC does not change database on conflict for insert and update.
915      */
916     @Test
917     @SmallTest
testDpcUriOnConflict()918     public void testDpcUriOnConflict() {
919         int dpcRecordId1 = 0, dpcRecordId2 = 0;
920         try {
921             mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
922 
923             final int current = 1;
924             final String numeric = TEST_OPERATOR;
925 
926             // Insert DPC record 1.
927             final String dpcRecordApn1 = "exampleApnNameDPC";
928             final String dpcRecordName = "exampleNameDPC";
929             dpcRecordId1 = insertApnRecord(URI_DPC, dpcRecordApn1, dpcRecordName,
930                     current, numeric);
931             Log.d(TAG, "testDpcUriOnConflict Id for DPC record 1: " + dpcRecordId1);
932 
933             // Insert conflicting DPC record.
934             final String dpcRecordNameConflict = "exampleNameDPCConflict";
935             final int dpcRecordIdConflict = insertApnRecord(URI_DPC, dpcRecordApn1,
936                     dpcRecordNameConflict, current, numeric);
937 
938             // Verity that conflicting DPC record is not inserted.
939             assertEquals(-1, dpcRecordIdConflict);
940             // Verify that APN 1 is not replaced or updated.
941             Cursor cursorDPC1 = queryFullTestApnRecord(URI_DPC, numeric);
942             assertNotNull(cursorDPC1);
943             assertEquals(1, cursorDPC1.getCount());
944             cursorDPC1.moveToFirst();
945             assertApnEquals(cursorDPC1, dpcRecordId1, dpcRecordApn1, dpcRecordName, current,
946                     Carriers.OWNED_BY_DPC);
947 
948             // Insert DPC record 2.
949             final String dpcRecordApn2 = "exampleApnNameDPC2";
950             dpcRecordId2 = insertApnRecord(URI_DPC, dpcRecordApn2, dpcRecordName,
951                     current, numeric);
952             Log.d(TAG, "testDpcUriOnConflict Id for DPC record 2: " + dpcRecordId2);
953 
954             // Update DPC record 2 to the values of DPC record 1.
955             ContentValues contentValuesDpcUpdate = new ContentValues();
956             contentValuesDpcUpdate.put(Carriers.APN, dpcRecordApn1);
957             contentValuesDpcUpdate.put(Carriers.NAME, dpcRecordNameConflict);
958             final int updateCount = mContentResolver.update(
959                     ContentUris.withAppendedId(URI_DPC, dpcRecordId2),
960                     contentValuesDpcUpdate, null, null);
961 
962             // Verify that database is not updated.
963             assertEquals(0, updateCount);
964             Cursor cursorDPC2 = queryFullTestApnRecord(URI_DPC, numeric);
965             assertNotNull(cursorDPC2);
966             assertEquals(2, cursorDPC2.getCount());
967             cursorDPC2.moveToFirst();
968             assertApnEquals(cursorDPC2, dpcRecordId1, dpcRecordApn1, dpcRecordName, current,
969                     Carriers.OWNED_BY_DPC);
970             cursorDPC2.moveToNext();
971             assertApnEquals(cursorDPC2, dpcRecordId2, dpcRecordApn2, dpcRecordName, current,
972                     Carriers.OWNED_BY_DPC);
973         } finally {
974             // Delete test records.
975             int numRowsDeleted = mContentResolver.delete(
976                     ContentUris.withAppendedId(URI_DPC, dpcRecordId1), null, null);
977             assertEquals(1, numRowsDeleted);
978             numRowsDeleted = mContentResolver.delete(
979                     ContentUris.withAppendedId(URI_DPC, dpcRecordId2), null, null);
980             assertEquals(1, numRowsDeleted);
981         }
982     }
983 
984     /**
985      * Verify that SecurityException is thrown if URL_DPC, URL_FILTERED and
986      * URL_ENFORCE_MANAGED is accessed from neither SYSTEM_UID nor PHONE_UID.
987      */
988     @Test
989     @SmallTest
testAccessUrlDpcThrowSecurityExceptionFromOtherUid()990     public void testAccessUrlDpcThrowSecurityExceptionFromOtherUid() {
991         mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID + 123456);
992 
993         // Test insert().
994         ContentValues contentValuesDPC = new ContentValues();
995         try {
996             mContentResolver.insert(URI_DPC, contentValuesDPC);
997             assertFalse("SecurityException should be thrown when URI_DPC is called from"
998                     + " neither SYSTEM_UID nor PHONE_UID", true);
999         } catch (SecurityException e) {
1000             // Should catch SecurityException.
1001         }
1002 
1003         // Test query().
1004         try {
1005             mContentResolver.query(URI_DPC,
1006                     new String[]{}, "", new String[]{}, null);
1007             assertFalse("SecurityException should be thrown when URI_DPC is called from"
1008                     + " neither SYSTEM_UID nor PHONE_UID", true);
1009         } catch (SecurityException e) {
1010             // Should catch SecurityException.
1011         }
1012         try {
1013             mContentResolver.query(URI_ENFORCE_MANAGED,
1014             new String[]{}, "", new String[]{}, null);
1015             assertFalse("SecurityException should be thrown when URI_ENFORCE_MANAGED is "
1016                     + "called from neither SYSTEM_UID nor PHONE_UID", true);
1017         } catch (SecurityException e) {
1018             // Should catch SecurityException.
1019         }
1020 
1021         // Test update().
1022         ContentValues contentValuesDPCUpdate = new ContentValues();
1023         try {
1024             mContentResolver.update(
1025                     Uri.parse(URI_DPC + "/1"),
1026                     contentValuesDPCUpdate, "", new String[]{});
1027             assertFalse("SecurityException should be thrown when URI_DPC is called"
1028                     + " from neither SYSTEM_UID nor PHONE_UID", true);
1029         } catch (SecurityException e) {
1030             // Should catch SecurityException.
1031         }
1032         try {
1033             mContentResolver.update(URI_ENFORCE_MANAGED, contentValuesDPCUpdate,
1034                     "", new String[]{});
1035             assertFalse("SecurityException should be thrown when URI_DPC is called"
1036                     + " from neither SYSTEM_UID nor PHONE_UID", true);
1037         } catch (SecurityException e) {
1038             // Should catch SecurityException.
1039         }
1040 
1041         // Test delete().
1042         try {
1043             mContentResolver.delete(
1044                     Uri.parse(URI_DPC + "/0"), "", new String[]{});
1045             assertFalse("SecurityException should be thrown when URI_DPC is called"
1046                     + " from neither SYSTEM_UID nor PHONE_UID", true);
1047         } catch (SecurityException e) {
1048             // Should catch SecurityException.
1049         }
1050     }
1051 
1052     /**
1053      * Verify that user/carrier edited/deleted APNs have priority in the EDITED field over
1054      * insertions which set EDITED=UNEDITED. In these cases instead of merging the APNs using the
1055      * new APN's value we keep the old value.
1056      */
1057     @Test
1058     @SmallTest
testPreserveEdited()1059     public void testPreserveEdited() {
1060         preserveEditedValueInMerge(Carriers.USER_EDITED);
1061     }
1062 
1063     @Test
1064     @SmallTest
testPreserveUserDeleted()1065     public void testPreserveUserDeleted() {
1066         preserveDeletedValueInMerge(Carriers.USER_DELETED);
1067     }
1068 
1069     @Test
1070     @SmallTest
testPreserveUserDeletedButPresentInXml()1071     public void testPreserveUserDeletedButPresentInXml() {
1072         preserveDeletedValueInMerge(Carriers.USER_DELETED_BUT_PRESENT_IN_XML);
1073     }
1074 
1075     @Test
1076     @SmallTest
testPreserveCarrierEdited()1077     public void testPreserveCarrierEdited() {
1078         preserveEditedValueInMerge(Carriers.CARRIER_EDITED);
1079     }
1080 
1081     @Test
1082     @SmallTest
testPreserveCarrierDeleted()1083     public void testPreserveCarrierDeleted() {
1084         preserveDeletedValueInMerge(Carriers.CARRIER_DELETED);
1085     }
1086 
1087     @Test
1088     @SmallTest
testPreserveCarrierDeletedButPresentInXml()1089     public void testPreserveCarrierDeletedButPresentInXml() {
1090         preserveDeletedValueInMerge(Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML);
1091     }
1092 
preserveEditedValueInMerge(int value)1093     private void preserveEditedValueInMerge(int value) {
1094         // insert user deleted APN
1095         String carrierName1 = "carrier1";
1096         String numeric1 = "123234";
1097         String mcc1 = "123";
1098         String mnc1 = "234";
1099         ContentValues editedValue = new ContentValues();
1100         editedValue.put(Carriers.NAME, carrierName1);
1101         editedValue.put(Carriers.NUMERIC, numeric1);
1102         editedValue.put(Carriers.MCC, mcc1);
1103         editedValue.put(Carriers.MNC, mnc1);
1104         editedValue.put(Carriers.EDITED_STATUS, value);
1105         assertNotNull(mContentResolver.insert(URI_TELEPHONY, editedValue));
1106 
1107         Cursor cur = mContentResolver.query(URI_TELEPHONY, null, null, null, null);
1108         assertEquals(1, cur.getCount());
1109 
1110         // insert APN that conflicts with edited APN
1111         String carrierName2 = "carrier2";
1112         ContentValues values = new ContentValues();
1113         values.put(Carriers.NAME, carrierName2);
1114         values.put(Carriers.NUMERIC, numeric1);
1115         values.put(Carriers.MCC, mcc1);
1116         values.put(Carriers.MNC, mnc1);
1117         values.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
1118         mContentResolver.insert(URI_TELEPHONY, values);
1119 
1120         String[] testProjection = {
1121             Carriers.NAME,
1122             Carriers.APN,
1123             Carriers.EDITED_STATUS,
1124             Carriers.TYPE,
1125             Carriers.PROTOCOL,
1126             Carriers.BEARER_BITMASK,
1127         };
1128         final int indexOfName = 0;
1129         final int indexOfEdited = 2;
1130 
1131         // Assert that the conflicting APN is merged into the existing user-edited APN, so only 1
1132         // APN exists in the db
1133         cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
1134         assertEquals(1, cur.getCount());
1135         cur.moveToFirst();
1136         assertEquals(carrierName2, cur.getString(indexOfName));
1137         assertEquals(value, cur.getInt(indexOfEdited));
1138     }
1139 
preserveDeletedValueInMerge(int value)1140     private void preserveDeletedValueInMerge(int value) {
1141         // insert user deleted APN
1142         String carrierName1 = "carrier1";
1143         String numeric1 = "123234";
1144         String mcc1 = "123";
1145         String mnc1 = "234";
1146         ContentValues editedValue = new ContentValues();
1147         editedValue.put(Carriers.NAME, carrierName1);
1148         editedValue.put(Carriers.NUMERIC, numeric1);
1149         editedValue.put(Carriers.MCC, mcc1);
1150         editedValue.put(Carriers.MNC, mnc1);
1151         editedValue.put(Carriers.EDITED_STATUS, value);
1152         assertNotNull(mContentResolver.insert(URI_TELEPHONY, editedValue));
1153 
1154         // insert APN that conflicts with edited APN
1155         String carrierName2 = "carrier2";
1156         ContentValues values = new ContentValues();
1157         values.put(Carriers.NAME, carrierName2);
1158         values.put(Carriers.NUMERIC, numeric1);
1159         values.put(Carriers.MCC, mcc1);
1160         values.put(Carriers.MNC, mnc1);
1161         values.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
1162         mContentResolver.insert(URI_TELEPHONY, values);
1163 
1164         String[] testProjection = {
1165             Carriers.NAME,
1166             Carriers.APN,
1167             Carriers.EDITED_STATUS,
1168             Carriers.TYPE,
1169             Carriers.PROTOCOL,
1170             Carriers.BEARER_BITMASK,
1171         };
1172         final int indexOfEdited = 2;
1173 
1174         // Assert that the conflicting APN is merged into the existing user-deleted APN.
1175         // Entries marked deleted will not show up in queries so we verify that no APNs can
1176         // be seen
1177         Cursor cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
1178         assertEquals(0, cur.getCount());
1179     }
1180 
1181     /**
1182      * Test URL_PREFERAPN_USING_SUBID works correctly.
1183      */
1184     @Test
1185     @SmallTest
testQueryPreferredApn()1186     public void testQueryPreferredApn() {
1187         // create APNs
1188         ContentValues preferredValues = new ContentValues();
1189         final String preferredApn = "preferredApn";
1190         final String preferredName = "preferredName";
1191         preferredValues.put(Carriers.APN, preferredApn);
1192         preferredValues.put(Carriers.NAME, preferredName);
1193         preferredValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1194         ContentValues otherValues = new ContentValues();
1195         final String otherApn = "otherApnName";
1196         final String otherName = "otherName";
1197         otherValues.put(Carriers.APN, otherApn);
1198         otherValues.put(Carriers.NAME, otherName);
1199         otherValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1200 
1201         // insert APNs
1202         // TODO if using URL_TELEPHONY, SubscriptionManager.getDefaultSubscriptionId() returns -1
1203         Log.d(TAG, "testQueryPreferredApn: Bulk inserting contentValues=" + preferredValues + ", "
1204                 + otherValues);
1205         Uri uri = mContentResolver.insert(CONTENT_URI_WITH_SUBID, preferredValues);
1206         mContentResolver.insert(CONTENT_URI_WITH_SUBID, otherValues);
1207         final String preferredApnIdString = uri.getLastPathSegment();
1208         final long preferredApnId = Long.parseLong(preferredApnIdString);
1209         Log.d(TAG, "testQueryPreferredApn: preferredApnString=" + preferredApnIdString);
1210 
1211         // set preferred apn
1212         preferredValues.put(COLUMN_APN_ID, preferredApnIdString);
1213         mContentResolver.insert(URL_PREFERAPN_USING_SUBID, preferredValues);
1214 
1215         // query preferred APN
1216         final String[] testProjection = { Carriers.APN, Carriers.NAME };
1217         Cursor cursor = mContentResolver.query(
1218                 URL_PREFERAPN_USING_SUBID, testProjection, null, null, null);
1219 
1220         // verify that preferred apn was set and retreived
1221         assertEquals(1, cursor.getCount());
1222         cursor.moveToFirst();
1223         assertEquals(preferredApn, cursor.getString(0));
1224         assertEquals(preferredName, cursor.getString(1));
1225     }
1226 
1227     /**
1228      *  Test that APN_SET_ID works correctly.
1229      */
1230     @Test
1231     @SmallTest
testApnSetId()1232     public void testApnSetId() {
1233         // create APNs
1234         ContentValues values1 = new ContentValues();
1235         final String apn = "apnName";
1236         final String apnName = "name";
1237         values1.put(Carriers.APN, apn);
1238         values1.put(Carriers.NAME, apnName);
1239         values1.put(Carriers.NUMERIC, TEST_OPERATOR);
1240 
1241         ContentValues values2 = new ContentValues();
1242         final String otherApn = "otherApnName";
1243         final String otherName = "otherName";
1244         values2.put(Carriers.APN, otherApn);
1245         values2.put(Carriers.NAME, otherName);
1246         values2.put(Carriers.NUMERIC, TEST_OPERATOR);
1247         values2.put(Carriers.APN_SET_ID, 1);
1248 
1249         // insert APNs
1250         // TODO if using URL_TELEPHONY, SubscriptionManager.getDefaultSubscriptionId() returns -1
1251         Log.d(TAG, "testApnSetId: inserting contentValues=" + values1 + ", " + values2);
1252         mContentResolver.insert(CONTENT_URI_WITH_SUBID, values1);
1253         mContentResolver.insert(CONTENT_URI_WITH_SUBID, values2);
1254 
1255         // query APN with default APN_SET_ID
1256         final String[] testProjection = { Carriers.NAME };
1257         Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection,
1258                 Carriers.APN_SET_ID + "=?", new String[] { "0" }, null);
1259         assertEquals(1, cursor.getCount());
1260         cursor.moveToFirst();
1261         assertEquals(apnName, cursor.getString(0));
1262 
1263         // query APN with APN_SET_ID=1
1264         cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection,
1265                 Carriers.APN_SET_ID + "=?", new String[] { "1" }, null);
1266         assertEquals(1, cursor.getCount());
1267         cursor.moveToFirst();
1268         assertEquals(otherName, cursor.getString(0));
1269     }
1270 
1271     /**
1272      *  Test that querying with the PREFERAPNSET url yields all APNs in the preferred set.
1273      */
1274     @Test
1275     @SmallTest
testPreferApnSetUrl()1276     public void testPreferApnSetUrl() {
1277         // create APNs
1278         ContentValues values1 = new ContentValues();
1279         final String apn = "apnName";
1280         final String apnName = "name";
1281         values1.put(Carriers.APN, apn);
1282         values1.put(Carriers.NAME, apnName);
1283         values1.put(Carriers.NUMERIC, TEST_OPERATOR);
1284 
1285         ContentValues values2 = new ContentValues();
1286         final String apn2 = "otherApnName";
1287         final String name2 = "name2";
1288         values2.put(Carriers.APN, apn2);
1289         values2.put(Carriers.NAME, name2);
1290         values2.put(Carriers.NUMERIC, TEST_OPERATOR);
1291         values2.put(Carriers.APN_SET_ID, 1);
1292 
1293         ContentValues values3 = new ContentValues();
1294         final String apn3 = "thirdApnName";
1295         final String name3 = "name3";
1296         values3.put(Carriers.APN, apn3);
1297         values3.put(Carriers.NAME, name3);
1298         values3.put(Carriers.NUMERIC, TEST_OPERATOR);
1299         values3.put(Carriers.APN_SET_ID, 1);
1300 
1301         // insert APNs
1302         // we explicitly include subid, as SubscriptionManager.getDefaultSubscriptionId() returns -1
1303         Log.d(TAG, "testPreferApnSetUrl: inserting contentValues=" + values1 + ", " + values2
1304                 + ", " + values3);
1305         mContentResolver.insert(CONTENT_URI_WITH_SUBID, values1);
1306         mContentResolver.insert(CONTENT_URI_WITH_SUBID, values2);
1307         Uri uri = mContentResolver.insert(CONTENT_URI_WITH_SUBID, values3);
1308 
1309         // before there's a preferred APN set, assert that all APNs are returned
1310         final String[] testProjection = { Carriers.NAME };
1311         Cursor cursor = mContentResolver.query(
1312                 Uri.withAppendedPath(Carriers.CONTENT_URI, "preferapnset/subId/" + TEST_SUBID),
1313                 testProjection, null, null, null);
1314         assertEquals(3, cursor.getCount());
1315 
1316         // set the APN from values3 (apn_set_id = 1) to the preferred APN
1317         final String preferredApnIdString = uri.getLastPathSegment();
1318         final long preferredApnId = Long.parseLong(preferredApnIdString);
1319         ContentValues prefer = new ContentValues();
1320         prefer.put("apn_id", preferredApnId);
1321         int count = mContentResolver.update(URL_PREFERAPN_USING_SUBID, prefer, null, null);
1322         assertEquals(1, count);
1323 
1324         // query APN with PREFERAPNSET url
1325         // explicitly include SUB_ID, as SubscriptionManager.getDefaultSubscriptionId() returns -1
1326         cursor = mContentResolver.query(
1327                 Uri.withAppendedPath(Carriers.CONTENT_URI, "preferapnset/subId/" + TEST_SUBID),
1328                 testProjection, null, null, null);
1329         assertEquals(2, cursor.getCount());
1330         cursor.moveToFirst();
1331         assertEquals(name2, cursor.getString(0));
1332         cursor.moveToNext();
1333         assertEquals(name3, cursor.getString(0));
1334     }
1335 
1336     /**
1337      * Test URL_RESTOREAPN_USING_SUBID works correctly.
1338      */
1339     @Test
1340     @SmallTest
testRestoreDefaultApn()1341     public void testRestoreDefaultApn() {
1342         // setup for multi-SIM
1343         TelephonyManager telephonyManager =
1344                 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
1345         doReturn(2).when(telephonyManager).getPhoneCount();
1346 
1347         // create APN to be deleted (including MVNO values)
1348         ContentValues targetValues = new ContentValues();
1349         targetValues.put(Carriers.APN, "apnName");
1350         targetValues.put(Carriers.NAME, "name");
1351         targetValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1352         targetValues.put(Carriers.MVNO_TYPE, "spn");
1353         targetValues.put(Carriers.MVNO_MATCH_DATA, TelephonyProviderTestable.TEST_SPN);
1354         // create other operator APN (sama MCCMNC)
1355         ContentValues otherValues = new ContentValues();
1356         final String otherApn = "otherApnName";
1357         final String otherName = "otherName";
1358         final String otherMvnoTyp = "spn";
1359         final String otherMvnoMatchData = "testOtherOperator";
1360         otherValues.put(Carriers.APN, otherApn);
1361         otherValues.put(Carriers.NAME, otherName);
1362         otherValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1363         otherValues.put(Carriers.MVNO_TYPE, otherMvnoTyp);
1364         otherValues.put(Carriers.MVNO_MATCH_DATA, otherMvnoMatchData);
1365 
1366         doReturn(true).when(telephonyManager).matchesCurrentSimOperator(
1367             anyString(), anyInt(), eq(TelephonyProviderTestable.TEST_SPN));
1368         doReturn(false).when(telephonyManager).matchesCurrentSimOperator(
1369             anyString(), anyInt(), eq(otherMvnoMatchData));
1370 
1371         // insert APNs
1372         Log.d(TAG, "testRestoreDefaultApn: Bulk inserting contentValues=" + targetValues + ", "
1373                 + otherValues);
1374         ContentValues[] values = new ContentValues[]{ targetValues, otherValues };
1375         mContentResolver.bulkInsert(Carriers.CONTENT_URI, values);
1376 
1377         // restore to default
1378         mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
1379 
1380         // get values in table
1381         final String[] testProjection =
1382         {
1383             Carriers.APN,
1384             Carriers.NAME,
1385             Carriers.MVNO_TYPE,
1386             Carriers.MVNO_MATCH_DATA,
1387         };
1388         // verify that deleted result match results of query
1389         Cursor cursor = mContentResolver.query(
1390                 Carriers.CONTENT_URI, testProjection, null, null, null);
1391         assertEquals(1, cursor.getCount());
1392         cursor.moveToFirst();
1393         assertEquals(otherApn, cursor.getString(0));
1394         assertEquals(otherName, cursor.getString(1));
1395         assertEquals(otherMvnoTyp, cursor.getString(2));
1396         assertEquals(otherMvnoMatchData, cursor.getString(3));
1397 
1398         // create APN to be deleted (not include MVNO values)
1399         ContentValues targetValues2 = new ContentValues();
1400         targetValues2.put(Carriers.APN, "apnName");
1401         targetValues2.put(Carriers.NAME, "name");
1402         targetValues2.put(Carriers.NUMERIC, TEST_OPERATOR);
1403 
1404         // insert APN
1405         mContentResolver.insert(Carriers.CONTENT_URI, targetValues2);
1406 
1407         // restore to default
1408         mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
1409 
1410         // verify that deleted result match results of query
1411         cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection, null, null, null);
1412         assertEquals(1, cursor.getCount());
1413         cursor.moveToFirst();
1414         assertEquals(otherApn, cursor.getString(0));
1415         assertEquals(otherName, cursor.getString(1));
1416         assertEquals(otherMvnoTyp, cursor.getString(2));
1417         assertEquals(otherMvnoMatchData, cursor.getString(3));
1418 
1419         // setup for single-SIM
1420         doReturn(1).when(telephonyManager).getPhoneCount();
1421 
1422         // restore to default
1423         mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
1424 
1425         // verify that deleted values are gone
1426         cursor = mContentResolver.query(
1427                 Carriers.CONTENT_URI, testProjection, null, null, null);
1428         assertEquals(0, cursor.getCount());
1429         assertEquals(3, notifyChangeRestoreCount);
1430     }
1431 
1432     /**
1433      * Test changes to siminfo/WFC_IMS_ENABLED and simInfo/ENHANCED_4G
1434      */
1435     @Test
1436     @SmallTest
testUpdateWfcEnabled()1437     public void testUpdateWfcEnabled() {
1438         // insert test contentValues
1439         ContentValues contentValues = new ContentValues();
1440         final int insertSubId = 1;
1441         final String insertDisplayName = "exampleDisplayName";
1442         final String insertCarrierName = "exampleCarrierName";
1443         final String insertIccId = "exampleIccId";
1444         final String insertCardId = "exampleCardId";
1445         contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
1446         contentValues.put(SubscriptionManager.DISPLAY_NAME, insertDisplayName);
1447         contentValues.put(SubscriptionManager.CARRIER_NAME, insertCarrierName);
1448         contentValues.put(SubscriptionManager.ICC_ID, insertIccId);
1449         contentValues.put(SubscriptionManager.CARD_ID, insertCardId);
1450 
1451         Log.d(TAG, "testSimTable Inserting wfc contentValues: " + contentValues);
1452         mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
1453         assertEquals(0, notifyWfcCount);
1454 
1455         // update wfc_enabled
1456         ContentValues values = new ContentValues();
1457         values.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, true);
1458         final String selection = SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?";
1459         final String[] selectionArgs = { "" + insertSubId };
1460         mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
1461         assertEquals(1, notifyWfcCount);
1462         assertEquals(0, notifyWfcCountWithTestSubId);
1463 
1464         // update other fields
1465         values = new ContentValues();
1466         values.put(SubscriptionManager.DISPLAY_NAME, "exampleDisplayNameNew");
1467         mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
1468         // expect no change on wfc count
1469         assertEquals(1, notifyWfcCount);
1470         assertEquals(0, notifyWfcCountWithTestSubId);
1471 
1472         // update WFC using subId
1473         values = new ContentValues();
1474         values.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, false);
1475         mContentResolver.update(SubscriptionManager.getUriForSubscriptionId(insertSubId),
1476                 values, null, null);
1477         assertEquals(1, notifyWfcCount);
1478         assertEquals(0, notifyWfcCountWithTestSubId);
1479     }
1480 
1481     @Test
1482     @SmallTest
testSIMAPNLIST_MatchTheMVNOAPN()1483     public void testSIMAPNLIST_MatchTheMVNOAPN() {
1484         // Test on getSubscriptionMatchingAPNList() step 1
1485         final String apnName = "apnName";
1486         final String carrierName = "name";
1487         final String numeric = TEST_OPERATOR;
1488         final String mvnoType = "spn";
1489         final String mvnoData = TEST_SPN;
1490 
1491         // Insert the MVNO APN
1492         ContentValues contentValues = new ContentValues();
1493         contentValues.put(Carriers.APN, apnName);
1494         contentValues.put(Carriers.NAME, carrierName);
1495         contentValues.put(Carriers.NUMERIC, numeric);
1496         contentValues.put(Carriers.MVNO_TYPE, mvnoType);
1497         contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
1498         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1499 
1500         // Insert the MNO APN
1501         contentValues = new ContentValues();
1502         contentValues.put(Carriers.APN, apnName);
1503         contentValues.put(Carriers.NAME, carrierName);
1504         contentValues.put(Carriers.NUMERIC, numeric);
1505         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1506 
1507         TelephonyManager telephonyManager =
1508             (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
1509         doReturn(true).when(telephonyManager).matchesCurrentSimOperator(
1510             anyString(), anyInt(), eq(mvnoData));
1511         doReturn(false).when(telephonyManager).matchesCurrentSimOperator(
1512             anyString(), anyInt(), eq(""));
1513 
1514         // Query DB
1515         final String[] testProjection =
1516                 {
1517                         Carriers.APN,
1518                         Carriers.NAME,
1519                         Carriers.NUMERIC,
1520                         Carriers.MVNO_MATCH_DATA
1521                 };
1522         Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
1523                 testProjection, null, null, null);
1524 
1525         // When the DB has MVNO and MNO APN, the query based on SIM_APN_LIST will return MVNO APN
1526         cursor.moveToFirst();
1527         assertEquals(cursor.getCount(), 1);
1528         assertEquals(apnName, cursor.getString(0));
1529         assertEquals(carrierName, cursor.getString(1));
1530         assertEquals(numeric, cursor.getString(2));
1531         assertEquals(mvnoData, cursor.getString(3));
1532     }
1533 
1534     @Test
1535     @SmallTest
testSIMAPNLIST_MatchTheMNOAPN()1536     public void testSIMAPNLIST_MatchTheMNOAPN() {
1537         // Test on getSubscriptionMatchingAPNList() step 2
1538         final String apnName = "apnName";
1539         final String carrierName = "name";
1540         final String numeric = TEST_OPERATOR;
1541 
1542         // Insert the MNO APN
1543         ContentValues contentValues = new ContentValues();
1544         contentValues.put(Carriers.APN, apnName);
1545         contentValues.put(Carriers.NAME, carrierName);
1546         contentValues.put(Carriers.NUMERIC, numeric);
1547         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1548 
1549         // Query DB
1550         final String[] testProjection =
1551                 {
1552                         Carriers.APN,
1553                         Carriers.NAME,
1554                         Carriers.NUMERIC,
1555                 };
1556         Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
1557                 testProjection, null, null, null);
1558 
1559         cursor.moveToFirst();
1560         assertEquals(apnName, cursor.getString(0));
1561         assertEquals(carrierName, cursor.getString(1));
1562         assertEquals(numeric, cursor.getString(2));
1563     }
1564 
1565     @Test
1566     @SmallTest
testSIMAPNLIST_MatchTheCarrierIDANDMNOAPN()1567     public void testSIMAPNLIST_MatchTheCarrierIDANDMNOAPN() {
1568         // Test on getSubscriptionMatchingAPNList() will return the {MCCMNC}
1569         final String apnName = "apnName";
1570         final String carrierName = "name";
1571         final int carrierId = TEST_CARRIERID;
1572 
1573         // Add the APN that only have carrier id
1574         ContentValues contentValues = new ContentValues();
1575         contentValues.put(Carriers.APN, apnName);
1576         contentValues.put(Carriers.NAME, carrierName);
1577         contentValues.put(Carriers.CARRIER_ID, carrierId);
1578         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1579 
1580         // Add MNO APN that added by user
1581         contentValues = new ContentValues();
1582         contentValues.put(Carriers.APN, apnName);
1583         contentValues.put(Carriers.NAME, carrierName);
1584         contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1585         contentValues.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
1586         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1587 
1588         // Query DB
1589         final String[] testProjection =
1590             {
1591                 Carriers.APN,
1592                 Carriers.NAME,
1593                 Carriers.CARRIER_ID,
1594             };
1595         Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST, testProjection, null, null, null);
1596 
1597         // The query based on SIM_APN_LIST will return MNO APN and the APN that has carrier id
1598         assertEquals(cursor.getCount(), 2);
1599     }
1600 
1601     @Test
1602     @SmallTest
testSIMAPNLIST_MatchTheCarrierAPNAndMVNOAPN()1603     public void testSIMAPNLIST_MatchTheCarrierAPNAndMVNOAPN() {
1604         final String apnName = "apnName";
1605         final String carrierName = "name";
1606         final String mvnoType = "spn";
1607         final String mvnoData = TEST_SPN;
1608         final int carrierId = TEST_CARRIERID;
1609 
1610         // Add the APN that only have carrier id
1611         ContentValues contentValues = new ContentValues();
1612         contentValues.put(Carriers.APN, apnName);
1613         contentValues.put(Carriers.NAME, carrierName);
1614         contentValues.put(Carriers.CARRIER_ID, carrierId);
1615         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1616 
1617         // Add MVNO APN that added by user
1618         contentValues = new ContentValues();
1619         contentValues.put(Carriers.APN, apnName);
1620         contentValues.put(Carriers.NAME, carrierName);
1621         contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1622         contentValues.put(Carriers.MVNO_TYPE, mvnoType);
1623         contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
1624         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1625 
1626         // Add MNO APN that added by user
1627         contentValues = new ContentValues();
1628         contentValues.put(Carriers.APN, apnName);
1629         contentValues.put(Carriers.NAME, carrierName);
1630         contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
1631         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
1632 
1633         // Query DB
1634         final String[] testProjection =
1635             {
1636                 Carriers.APN,
1637                 Carriers.NAME,
1638                 Carriers.CARRIER_ID,
1639                 Carriers.MVNO_TYPE,
1640             };
1641         Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
1642             testProjection, null, null, null);
1643 
1644         // The query based on SIM_APN_LIST will return MVNO APN and the APN that has carrier id
1645         assertEquals(cursor.getCount(), 2);
1646         while(cursor.moveToNext()) {
1647             assertTrue(!TextUtils.isEmpty(cursor.getString(2))
1648                     || !TextUtils.isEmpty(cursor.getString(3)));
1649         }
1650     }
1651 }
1652