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