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