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