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