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