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