• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.phone;
18 
19 import static android.content.pm.PackageManager.PERMISSION_DENIED;
20 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
21 import static android.provider.Telephony.ServiceStateTable;
22 import static android.provider.Telephony.ServiceStateTable.DATA_NETWORK_TYPE;
23 import static android.provider.Telephony.ServiceStateTable.DATA_REG_STATE;
24 import static android.provider.Telephony.ServiceStateTable.DUPLEX_MODE;
25 import static android.provider.Telephony.ServiceStateTable.VOICE_OPERATOR_NUMERIC;
26 import static android.provider.Telephony.ServiceStateTable.VOICE_REG_STATE;
27 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
28 import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
29 
30 import static com.android.phone.ServiceStateProvider.ENFORCE_LOCATION_PERMISSION_CHECK;
31 import static com.android.phone.ServiceStateProvider.NETWORK_ID;
32 
33 import static org.junit.Assert.assertEquals;
34 import static org.junit.Assert.assertFalse;
35 import static org.junit.Assert.assertNotNull;
36 import static org.junit.Assert.assertThrows;
37 import static org.junit.Assert.assertTrue;
38 import static org.mockito.ArgumentMatchers.any;
39 import static org.mockito.ArgumentMatchers.anyInt;
40 import static org.mockito.ArgumentMatchers.anyString;
41 import static org.mockito.ArgumentMatchers.eq;
42 import static org.mockito.ArgumentMatchers.nullable;
43 import static org.mockito.Mockito.doReturn;
44 import static org.mockito.Mockito.never;
45 import static org.mockito.Mockito.verify;
46 import static org.mockito.Mockito.when;
47 
48 import android.Manifest;
49 import android.app.AppOpsManager;
50 import android.compat.testing.PlatformCompatChangeRule;
51 import android.content.Context;
52 import android.content.pm.ApplicationInfo;
53 import android.content.pm.PackageManager;
54 import android.content.pm.ProviderInfo;
55 import android.database.ContentObserver;
56 import android.database.Cursor;
57 import android.location.LocationManager;
58 import android.net.Uri;
59 import android.os.Build;
60 import android.os.UserHandle;
61 import android.telephony.AccessNetworkConstants;
62 import android.telephony.NetworkRegistrationInfo;
63 import android.telephony.ServiceState;
64 import android.telephony.SubscriptionManager;
65 import android.telephony.TelephonyManager;
66 import android.test.mock.MockContentResolver;
67 import android.test.suitebuilder.annotation.SmallTest;
68 
69 import androidx.test.ext.junit.runners.AndroidJUnit4;
70 
71 import libcore.junit.util.compat.CoreCompatChangeRule;
72 
73 import org.junit.After;
74 import org.junit.Before;
75 import org.junit.Ignore;
76 import org.junit.Rule;
77 import org.junit.Test;
78 import org.junit.rules.TestRule;
79 import org.junit.runner.RunWith;
80 import org.mockito.Mock;
81 import org.mockito.MockitoAnnotations;
82 
83 /**
84  * Tests for simple queries of ServiceStateProvider.
85  *
86  * Build, install and run the tests by running the commands below:
87  *     atest ServiceStateProviderTest
88  */
89 @RunWith(AndroidJUnit4.class)
90 public class ServiceStateProviderTest {
91     private static final String TAG = "ServiceStateProviderTest";
92     private static final int TEST_NETWORK_ID = 123;
93     private static final int TEST_SYSTEM_ID = 123;
94 
95     private MockContentResolver mContentResolver;
96     private ServiceState mTestServiceState;
97     private ServiceState mTestServiceStateForSubId1;
98 
99     @Mock Context mContext;
100     @Mock AppOpsManager mAppOpsManager;
101     @Mock LocationManager mLocationManager;
102     @Mock PackageManager mPackageManager;
103 
104     @Rule
105     public TestRule compatChangeRule = new PlatformCompatChangeRule();
106 
107     // Exception used internally to verify if the Resolver#notifyChange has been called.
108     private class TestNotifierException extends RuntimeException {
TestNotifierException()109         TestNotifierException() {
110             super();
111         }
112     }
113 
114     @Before
setUp()115     public void setUp() throws Exception {
116         MockitoAnnotations.initMocks(this);
117         mockSystemService(AppOpsManager.class, mAppOpsManager, Context.APP_OPS_SERVICE);
118         mockSystemService(LocationManager.class, mLocationManager, Context.LOCATION_SERVICE);
119         doReturn(mPackageManager).when(mContext).getPackageManager();
120 
121         mContentResolver = new MockContentResolver() {
122             @Override
123             public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
124                 throw new TestNotifierException();
125             }
126         };
127         doReturn(mContentResolver).when(mContext).getContentResolver();
128 
129         mTestServiceState = new ServiceState();
130         mTestServiceState.setStateOutOfService();
131         mTestServiceState.setCdmaSystemAndNetworkId(TEST_SYSTEM_ID, TEST_NETWORK_ID);
132         mTestServiceStateForSubId1 = new ServiceState();
133         mTestServiceStateForSubId1.setStateOff();
134 
135         // Add NRI to trigger SS with non-default values (e.g. duplex mode)
136         NetworkRegistrationInfo nriWwan = new NetworkRegistrationInfo.Builder()
137                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
138                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
139                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
140                 .build();
141         mTestServiceStateForSubId1.addNetworkRegistrationInfo(nriWwan);
142         mTestServiceStateForSubId1.setChannelNumber(65536); // EutranBand.BAND_65, DUPLEX_MODE_FDD
143 
144         // Mock out the actual phone state
145         ServiceStateProvider provider = new ServiceStateProvider() {
146             @Override
147             public ServiceState getServiceState(int subId) {
148                 if (subId == 1) {
149                     return mTestServiceStateForSubId1;
150                 } else {
151                     return mTestServiceState;
152                 }
153             }
154 
155             @Override
156             public int getDefaultSubId() {
157                 return 0;
158             }
159         };
160         ProviderInfo providerInfo = new ProviderInfo();
161         providerInfo.authority = "service-state";
162         provider.attachInfoForTesting(mContext, providerInfo);
163         mContentResolver.addProvider("service-state", provider);
164 
165         // By default, test with app target R, no READ_PRIVILEGED_PHONE_STATE permission
166         setTargetSdkVersion(Build.VERSION_CODES.R);
167         setCanReadPrivilegedPhoneState(false);
168 
169         // TODO(b/191995565): Turn on all ignored cases once location access is allow to be off
170         // Do not allow phone process to always access location so we can test various scenarios
171         // LocationAccessPolicy.alwaysAllowPrivilegedProcessToAccessLocationForTesting(false);
172     }
173 
174     @After
tearDown()175     public void tearDown() throws Exception {
176         // LocationAccessPolicy.alwaysAllowPrivilegedProcessToAccessLocationForTesting(true);
177     }
178 
179     /**
180      * Verify that when calling query with no subId in the uri the default ServiceState is returned.
181      * In this case the subId is set to 0 and the expected service state is mTestServiceState.
182      */
183     // TODO(b/191995565): Turn this on when location access can be off
184     @Ignore
185     @SmallTest
186     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
testQueryServiceState_withNoSubId_withoutLocation()187     public void testQueryServiceState_withNoSubId_withoutLocation() {
188         setLocationPermissions(false);
189 
190         verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, mTestServiceState,
191                 false /*hasLocation*/);
192     }
193 
194     @Test
195     @SmallTest
testQueryServiceState_withNoSubId_withLocation()196     public void testQueryServiceState_withNoSubId_withLocation() {
197         setLocationPermissions(true);
198 
199         verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, mTestServiceState,
200                 true /*hasLocation*/);
201     }
202 
203     /**
204      * Verify that when calling with the DEFAULT_SUBSCRIPTION_ID the correct ServiceState is
205      * returned. In this case the subId is set to 0 and the expected service state is
206      * mTestServiceState.
207      */
208     // TODO(b/191995565): Turn case on when location access can be off
209     @Ignore
210     @SmallTest
testGetServiceState_withDefaultSubId_withoutLocation()211     public void testGetServiceState_withDefaultSubId_withoutLocation() {
212         setLocationPermissions(false);
213 
214         verifyServiceStateForSubId(
215                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
216                 mTestServiceState, false /*hasLocation*/);
217     }
218 
219     @Test
220     @SmallTest
testGetServiceState_withDefaultSubId_withLocation()221     public void testGetServiceState_withDefaultSubId_withLocation() {
222         setLocationPermissions(true);
223 
224         verifyServiceStateForSubId(
225                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
226                 mTestServiceState, true /*hasLocation*/);
227     }
228 
229     /**
230      * Verify that when calling with a specific subId the correct ServiceState is returned. In this
231      * case the subId is set to 1 and the expected service state is mTestServiceStateForSubId1
232      */
233     @Test
234     @SmallTest
testGetServiceStateForSubId_withoutLocation()235     public void testGetServiceStateForSubId_withoutLocation() {
236         setLocationPermissions(false);
237 
238         verifyServiceStateForSubId(getUriForSubscriptionId(1), mTestServiceStateForSubId1,
239                 false /*hasLocation*/);
240     }
241 
242     @Test
243     @SmallTest
testGetServiceStateForSubId_withLocation()244     public void testGetServiceStateForSubId_withLocation() {
245         setLocationPermissions(true);
246 
247         verifyServiceStateForSubId(getUriForSubscriptionId(1), mTestServiceStateForSubId1,
248                 true /*hasLocation*/);
249     }
250 
251     /**
252      * Verify that apps target S+ without READ_PRIVILEGED_PHONE_STATE permission can access the
253      * public columns of ServiceStateTable.
254      */
255     @Test
256     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
257     public void
query_publicColumns_enforceLocatoinEnabled_targetS_noReadPrivilege_getPublicColumns()258     query_publicColumns_enforceLocatoinEnabled_targetS_noReadPrivilege_getPublicColumns() {
259         setTargetSdkVersion(Build.VERSION_CODES.S);
260         setCanReadPrivilegedPhoneState(false);
261 
262         verifyServiceStateWithPublicColumns(mTestServiceState, null /*projection*/);
263     }
264 
265     @Test
266     @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
267     public void
query_publicColumns_enforceLocationDisabled_targetS_noReadPrivilege_getPublicColumns()268     query_publicColumns_enforceLocationDisabled_targetS_noReadPrivilege_getPublicColumns() {
269         setTargetSdkVersion(Build.VERSION_CODES.S);
270         setCanReadPrivilegedPhoneState(false);
271 
272         verifyServiceStateWithPublicColumns(mTestServiceState, null /*projection*/);
273     }
274 
275     /**
276      * Verify that apps target S+ without READ_PRIVILEGED_PHONE_STATE permission try to access
277      * non-public columns should throw IllegalArgumentException.
278      */
279     @Test
280     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
query_hideColumn_targetS_noReadPrivilege_throwIllegalArgumentException()281     public void query_hideColumn_targetS_noReadPrivilege_throwIllegalArgumentException() {
282         setTargetSdkVersion(Build.VERSION_CODES.S);
283         setCanReadPrivilegedPhoneState(false);
284 
285         // DATA_ROAMING_TYPE is a non-public column
286         String[] projection = new String[]{"data_roaming_type"};
287 
288         assertThrows(IllegalArgumentException.class,
289                 () -> verifyServiceStateWithPublicColumns(mTestServiceState, projection));
290     }
291 
292     /**
293      * Verify that with changeId ENFORCE_LOCATION_PERMISSION_CHECK enabled, apps target S+ with
294      * READ_PRIVILEGED_PHONE_STATE and location permissions should be able to access all columns.
295      */
296     @Test
297     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
298     public void
query_allColumn_enforceLocationEnabled_targetS_withReadPrivilegedAndLocation_getUnredacted()299     query_allColumn_enforceLocationEnabled_targetS_withReadPrivilegedAndLocation_getUnredacted() {
300         setTargetSdkVersion(Build.VERSION_CODES.S);
301         setCanReadPrivilegedPhoneState(true);
302         setLocationPermissions(true);
303 
304         verifyServiceStateForSubId(
305                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
306                 mTestServiceState, true /*hasPermission*/);
307     }
308 
309     /**
310      * Verify that with changeId ENFORCE_LOCATION_PERMISSION_CHECK disabled, apps target S+ with
311      * READ_PRIVILEGED_PHONE_STATE and location permissions should be able to access all columns.
312      */
313     @Test
314     @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
315     public void
query_allColumn_enforceLocationDisabled_targetS_withReadPrivilegedAndLocation_getUnredacted()316     query_allColumn_enforceLocationDisabled_targetS_withReadPrivilegedAndLocation_getUnredacted() {
317         setTargetSdkVersion(Build.VERSION_CODES.S);
318         setCanReadPrivilegedPhoneState(true);
319         setLocationPermissions(true);
320 
321         verifyServiceStateForSubId(
322                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
323                 mTestServiceState, true /*hasPermission*/);
324     }
325 
326     /**
327      * Verify that apps target S+ with READ_PRIVILEGED_PHONE_STATE permission but no location
328      * permission, try to access location sensitive columns should throw SecurityException.
329      */
330     // TODO(b/191995565): Turn this on once b/191995565 is integrated
331     @Ignore
332     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
query_locationColumn_targetS_withReadPrivilegeNoLocation_throwSecurityExecption()333     public void query_locationColumn_targetS_withReadPrivilegeNoLocation_throwSecurityExecption() {
334         setTargetSdkVersion(Build.VERSION_CODES.S);
335         setCanReadPrivilegedPhoneState(true);
336         setLocationPermissions(false);
337 
338         assertThrows(SecurityException.class,
339                 () -> verifyServiceStateWithLocationColumns(mTestServiceState));
340     }
341 
342     /**
343      * Verify that when changeId ENFORCE_LOCATION_PERMISSION_CHECK is enabled, apps target R- with
344      * location permissions should be able to access all columns.
345      */
346     @Test
347     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
query_allColumn_enforceLocationEnabled_targetR_withLocation_getUnredacted()348     public void query_allColumn_enforceLocationEnabled_targetR_withLocation_getUnredacted() {
349         setTargetSdkVersion(Build.VERSION_CODES.R);
350         setLocationPermissions(true);
351 
352         verifyServiceStateForSubId(
353                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
354                 mTestServiceState, true /*hasPermission*/);
355     }
356 
357     /**
358      * Verify that when changeId ENFORCE_LOCATION_PERMISSION_CHECK is disabled, apps target R- with
359      * location permissions should be able to access all columns.
360      */
361     @Test
362     @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
query_allColumn_enforceLocationDisabled_targetR_withLocation_getUnredacted()363     public void query_allColumn_enforceLocationDisabled_targetR_withLocation_getUnredacted() {
364         setTargetSdkVersion(Build.VERSION_CODES.R);
365         setLocationPermissions(true);
366 
367         verifyServiceStateForSubId(
368                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
369                 mTestServiceState, true /*hasPermission*/);
370     }
371 
372     /**
373      * Verify that changeId ENFORCE_LOCATION_PERMISSION_CHECK is enabled, apps target R- w/o
374      * location permissions should be able to access all columns but with redacted ServiceState.
375      */
376     // TODO(b/191995565): Turn case on when location access can be off
377     @Ignore
378     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
query_allColumn_enforceLocationEnabled_targetR_noLocation_getRedacted()379     public void query_allColumn_enforceLocationEnabled_targetR_noLocation_getRedacted() {
380         setTargetSdkVersion(Build.VERSION_CODES.R);
381         setLocationPermissions(false);
382 
383         verifyServiceStateForSubId(
384                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
385                 ServiceStateProvider.getLocationRedactedServiceState(mTestServiceState),
386                 true /*hasPermission*/);
387     }
388 
389     /**
390      * Verify that changeId ENFORCE_LOCATION_PERMISSION_CHECK is disabled, apps target R- w/o
391      * location permissions should be able to access all columns and with unredacted ServiceState.
392      */
393     // TODO(b/191995565): Turn case on when location access can be off
394     @Ignore
395     @CoreCompatChangeRule.DisableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
query_allColumn_enforceLocationDisabled_targetR_noLocation_getUnredacted()396     public void query_allColumn_enforceLocationDisabled_targetR_noLocation_getUnredacted() {
397         setTargetSdkVersion(Build.VERSION_CODES.R);
398         setLocationPermissions(false);
399 
400         verifyServiceStateForSubId(
401                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
402                 mTestServiceState, true /*hasPermission*/);
403     }
404 
405     /**
406      * Verify that when caller with targetSDK S+ has location permission and try to query
407      * location non-sensitive info, it should not get blamed.
408      */
409     @Test
410     @CoreCompatChangeRule.EnableCompatChanges({ENFORCE_LOCATION_PERMISSION_CHECK})
testQuery_noLocationBlamed_whenQueryNonLocationInfo_withPermission()411     public void testQuery_noLocationBlamed_whenQueryNonLocationInfo_withPermission() {
412         setTargetSdkVersion(Build.VERSION_CODES.S);
413         setLocationPermissions(true);
414 
415         verifyServiceStateWithPublicColumns(mTestServiceState, null /*projection*/);
416         verify(mAppOpsManager, never()).noteOpNoThrow(any(), anyInt(), any(), any(), any());
417     }
418 
verifyServiceStateWithLocationColumns(ServiceState ss)419     private void verifyServiceStateWithLocationColumns(ServiceState ss) {
420         // NETWORK_ID is a location-sensitive column
421         try (Cursor cursor = mContentResolver.query(ServiceStateTable.CONTENT_URI,
422                 new String[]{NETWORK_ID}, null, null)) {
423             assertNotNull(cursor);
424         }
425     }
426 
verifyServiceStateWithPublicColumns(ServiceState ss, String[] projection)427     private void verifyServiceStateWithPublicColumns(ServiceState ss, String[] projection) {
428         try (Cursor cursor = mContentResolver.query(ServiceStateTable.CONTENT_URI, projection, null,
429                 null)) {
430             assertNotNull(cursor);
431 
432             cursor.moveToFirst();
433             assertEquals(ss.getVoiceRegState(),
434                     cursor.getInt(cursor.getColumnIndex(VOICE_REG_STATE)));
435             assertEquals(ss.getDataRegistrationState(),
436                     cursor.getInt(cursor.getColumnIndex(DATA_REG_STATE)));
437             assertEquals(ss.getOperatorNumeric(),
438                     cursor.getString(cursor.getColumnIndex(VOICE_OPERATOR_NUMERIC)));
439             assertEquals(ss.getDataNetworkType(),
440                     cursor.getInt(cursor.getColumnIndex(DATA_NETWORK_TYPE)));
441             assertEquals(ss.getDuplexMode(), cursor.getInt(cursor.getColumnIndex(DUPLEX_MODE)));
442         }
443     }
444 
verifyServiceStateForSubId(Uri uri, ServiceState ss, boolean hasLocation)445     private void verifyServiceStateForSubId(Uri uri, ServiceState ss, boolean hasLocation) {
446         Cursor cursor = mContentResolver.query(uri, ServiceStateProvider.ALL_COLUMNS, "",
447                 null, null);
448         assertNotNull(cursor);
449         cursor.moveToFirst();
450 
451         final int voiceRegState = ss.getState();
452         final int dataRegState = ss.getDataRegistrationState();
453         final int voiceRoamingType = ss.getVoiceRoamingType();
454         final int dataRoamingType = ss.getDataRoamingType();
455         final String voiceOperatorAlphaLong = hasLocation ? ss.getOperatorAlphaLong() : null;
456         final String voiceOperatorAlphaShort = hasLocation ? ss.getOperatorAlphaShort() : null;
457         final String voiceOperatorNumeric = hasLocation ? ss.getOperatorNumeric() : null;
458         final String dataOperatorAlphaLong = hasLocation ? ss.getOperatorAlphaLong() : null;
459         final String dataOperatorAlphaShort = hasLocation ? ss.getOperatorAlphaShort() : null;
460         final String dataOperatorNumeric = hasLocation ? ss.getOperatorNumeric() : null;
461         final int isManualNetworkSelection = (ss.getIsManualSelection()) ? 1 : 0;
462         final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology();
463         final int rilDataRadioTechnology = ss.getRilDataRadioTechnology();
464         final int cssIndicator = ss.getCssIndicator();
465         final int networkId = hasLocation ? ss.getCdmaNetworkId() : ServiceState.UNKNOWN_ID;
466         final int systemId = hasLocation ? ss.getCdmaSystemId() : ServiceState.UNKNOWN_ID;
467         final int cdmaRoamingIndicator = ss.getCdmaRoamingIndicator();
468         final int cdmaDefaultRoamingIndicator = ss.getCdmaDefaultRoamingIndicator();
469         final int cdmaEriIconIndex = ss.getCdmaEriIconIndex();
470         final int cdmaEriIconMode = ss.getCdmaEriIconMode();
471         final int isEmergencyOnly = (ss.isEmergencyOnly()) ? 1 : 0;
472         final int isUsingCarrierAggregation = (ss.isUsingCarrierAggregation()) ? 1 : 0;
473         final String operatorAlphaLongRaw = ss.getOperatorAlphaLongRaw();
474         final String operatorAlphaShortRaw = ss.getOperatorAlphaShortRaw();
475         final int dataNetworkType = ss.getDataNetworkType();
476         final int duplexMode = ss.getDuplexMode();
477 
478         assertEquals(voiceRegState, cursor.getInt(0));
479         assertEquals(dataRegState, cursor.getInt(1));
480         assertEquals(voiceRoamingType, cursor.getInt(2));
481         assertEquals(dataRoamingType, cursor.getInt(3));
482         assertEquals(voiceOperatorAlphaLong, cursor.getString(4));
483         assertEquals(voiceOperatorAlphaShort, cursor.getString(5));
484         assertEquals(voiceOperatorNumeric, cursor.getString(6));
485         assertEquals(dataOperatorAlphaLong, cursor.getString(7));
486         assertEquals(dataOperatorAlphaShort, cursor.getString(8));
487         assertEquals(dataOperatorNumeric, cursor.getString(9));
488         assertEquals(isManualNetworkSelection, cursor.getInt(10));
489         assertEquals(rilVoiceRadioTechnology, cursor.getInt(11));
490         assertEquals(rilDataRadioTechnology, cursor.getInt(12));
491         assertEquals(cssIndicator, cursor.getInt(13));
492         assertEquals(networkId, cursor.getInt(14));
493         assertEquals(systemId, cursor.getInt(15));
494         assertEquals(cdmaRoamingIndicator, cursor.getInt(16));
495         assertEquals(cdmaDefaultRoamingIndicator, cursor.getInt(17));
496         assertEquals(cdmaEriIconIndex, cursor.getInt(18));
497         assertEquals(cdmaEriIconMode, cursor.getInt(19));
498         assertEquals(isEmergencyOnly, cursor.getInt(20));
499         assertEquals(isUsingCarrierAggregation, cursor.getInt(21));
500         assertEquals(operatorAlphaLongRaw, cursor.getString(22));
501         assertEquals(operatorAlphaShortRaw, cursor.getString(23));
502         assertEquals(dataNetworkType, cursor.getInt(24));
503         assertEquals(duplexMode, cursor.getInt(25));
504     }
505 
506     /**
507      * Test that we don't notify for certain field changes. (e.g. we don't notify when the NetworkId
508      * or SystemId change) This is an intentional behavior change from the broadcast.
509      */
510     @Test
511     @SmallTest
testNoNotify()512     public void testNoNotify() {
513         int subId = 0;
514 
515         ServiceState oldSS = new ServiceState();
516         oldSS.setStateOutOfService();
517         oldSS.setCdmaSystemAndNetworkId(1, 1);
518 
519         ServiceState newSS = new ServiceState();
520         newSS.setStateOutOfService();
521         newSS.setCdmaSystemAndNetworkId(0, 0);
522 
523         // Test that notifyChange is not called for these fields
524         assertFalse(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId));
525     }
526 
527     @Test
528     @SmallTest
testNotifyChanged_noStateUpdated()529     public void testNotifyChanged_noStateUpdated() {
530         int subId = 0;
531 
532         ServiceState oldSS = new ServiceState();
533         oldSS.setStateOutOfService();
534         oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
535 
536         ServiceState copyOfOldSS = new ServiceState();
537         copyOfOldSS.setStateOutOfService();
538         copyOfOldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
539 
540         // Test that notifyChange is not called with no change in notifyChangeForSubIdAndField
541         assertFalse(notifyChangeCalledForSubId(oldSS, copyOfOldSS, subId));
542 
543         // Test that notifyChange is not called with no change in notifyChangeForSubId
544         assertFalse(notifyChangeCalledForSubIdAndField(oldSS, copyOfOldSS, subId));
545     }
546 
547     @Test
548     @SmallTest
testNotifyChanged_voiceRegStateUpdated()549     public void testNotifyChanged_voiceRegStateUpdated() {
550         int subId = 0;
551 
552         ServiceState oldSS = new ServiceState();
553         oldSS.setStateOutOfService();
554         oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
555 
556         ServiceState newSS = new ServiceState();
557         newSS.setStateOutOfService();
558         newSS.setVoiceRegState(ServiceState.STATE_POWER_OFF);
559 
560         // Test that notifyChange is called by notifyChangeForSubIdAndField when the voice_reg_state
561         // changes
562         assertTrue(notifyChangeCalledForSubId(oldSS, newSS, subId));
563 
564         // Test that notifyChange is called by notifyChangeForSubId when the voice_reg_state changes
565         assertTrue(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId));
566     }
567 
568     @Test
569     @SmallTest
testNotifyChanged_dataNetworkTypeUpdated()570     public void testNotifyChanged_dataNetworkTypeUpdated() {
571         int subId = 0;
572 
573         // While we don't have a method to directly set dataNetworkType, we emulate a ServiceState
574         // change that will trigger the change of dataNetworkType, according to the logic in
575         // ServiceState#getDataNetworkType
576         ServiceState oldSS = new ServiceState();
577         oldSS.setStateOutOfService();
578 
579         ServiceState newSS = new ServiceState();
580         newSS.setStateOutOfService();
581 
582         NetworkRegistrationInfo nriWwan = new NetworkRegistrationInfo.Builder()
583                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
584                 .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
585                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
586                 .setRegistrationState(REGISTRATION_STATE_HOME)
587                 .build();
588         newSS.addNetworkRegistrationInfo(nriWwan);
589 
590         // Test that notifyChange is called by notifyChangeForSubId when the
591         // data_network_type changes
592         assertTrue(notifyChangeCalledForSubId(oldSS, newSS, subId));
593 
594         // Test that notifyChange is called by notifyChangeForSubIdAndField when the
595         // data_network_type changes
596         assertTrue(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId));
597     }
598 
599     @Test
600     @SmallTest
testNotifyChanged_dataRegStateUpdated()601     public void testNotifyChanged_dataRegStateUpdated() {
602         int subId = 0;
603 
604         ServiceState oldSS = new ServiceState();
605         oldSS.setStateOutOfService();
606         oldSS.setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
607 
608         ServiceState newSS = new ServiceState();
609         newSS.setStateOutOfService();
610         newSS.setDataRegState(ServiceState.STATE_POWER_OFF);
611 
612         // Test that notifyChange is called by notifyChangeForSubId
613         // when the data_reg_state changes
614         assertTrue(notifyChangeCalledForSubId(oldSS, newSS, subId));
615 
616         // Test that notifyChange is called by notifyChangeForSubIdAndField
617         // when the data_reg_state changes
618         assertTrue(notifyChangeCalledForSubIdAndField(oldSS, newSS, subId));
619     }
620 
621     // Check if notifyChange was called by notifyChangeForSubId
notifyChangeCalledForSubId(ServiceState oldSS, ServiceState newSS, int subId)622     private boolean notifyChangeCalledForSubId(ServiceState oldSS,
623             ServiceState newSS, int subId) {
624         try {
625             ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, newSS, subId);
626         } catch (TestNotifierException e) {
627             return true;
628         }
629         return false;
630     }
631 
632     // Check if notifyChange was called by notifyChangeForSubIdAndField
notifyChangeCalledForSubIdAndField(ServiceState oldSS, ServiceState newSS, int subId)633     private boolean notifyChangeCalledForSubIdAndField(ServiceState oldSS,
634             ServiceState newSS, int subId) {
635         try {
636             ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId);
637         } catch (TestNotifierException e) {
638             return true;
639         }
640         return false;
641     }
642 
setLocationPermissions(boolean hasPermission)643     private void setLocationPermissions(boolean hasPermission) {
644         if (!hasPermission) {
645             // System location off, LocationAccessPolicy#checkLocationPermission returns DENIED_SOFT
646             when(mLocationManager.isLocationEnabledForUser(any(UserHandle.class)))
647                     .thenReturn(false);
648         } else {
649             // Turn on all to let LocationAccessPolicy#checkLocationPermission returns ALLOWED
650             when(mContext.checkPermission(eq(Manifest.permission.ACCESS_FINE_LOCATION),
651                     anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
652 
653             when(mContext.checkPermission(eq(Manifest.permission.ACCESS_COARSE_LOCATION),
654                     anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
655 
656             when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_FINE_LOCATION),
657                     anyInt(), anyString(), nullable(String.class), nullable(String.class)))
658                     .thenReturn(AppOpsManager.MODE_ALLOWED);
659             when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OPSTR_COARSE_LOCATION),
660                     anyInt(), anyString(), nullable(String.class), nullable(String.class)))
661                     .thenReturn(AppOpsManager.MODE_ALLOWED);
662 
663             when(mLocationManager.isLocationEnabledForUser(any(UserHandle.class))).thenReturn(true);
664             when(mContext.checkPermission(eq(Manifest.permission.INTERACT_ACROSS_USERS_FULL),
665                     anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
666         }
667     }
668 
mockSystemService(Class<T> clazz , T obj, String serviceName)669     private <T> void mockSystemService(Class<T> clazz , T obj, String serviceName) {
670         when(mContext.getSystemServiceName(eq(clazz))).thenReturn(serviceName);
671         when(mContext.getSystemService(eq(serviceName))).thenReturn(obj);
672     }
673 
setTargetSdkVersion(int version)674     private void setTargetSdkVersion(int version) {
675         ApplicationInfo testAppInfo = new ApplicationInfo();
676         testAppInfo.targetSdkVersion = version;
677         try {
678             when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
679                     .thenReturn(testAppInfo);
680         } catch (Exception ignored) {
681         }
682     }
683 
setCanReadPrivilegedPhoneState(boolean granted)684     private void setCanReadPrivilegedPhoneState(boolean granted) {
685         doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED).when(mContext)
686                 .checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
687     }
688 }
689