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