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.provider.Telephony.ServiceStateTable;
20 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.mockito.Mockito.doReturn;
27 import static org.mockito.Mockito.mock;
28 
29 import android.content.Context;
30 import android.content.pm.ProviderInfo;
31 import android.database.ContentObserver;
32 import android.database.Cursor;
33 import android.net.Uri;
34 import android.telephony.ServiceState;
35 import android.telephony.SubscriptionManager;
36 import android.test.mock.MockContentResolver;
37 import android.test.suitebuilder.annotation.SmallTest;
38 
39 import org.junit.Before;
40 import org.junit.Test;
41 
42 /**
43  * Tests for simple queries of ServiceStateProvider.
44  *
45  * Build, install and run the tests by running the commands below:
46  *     runtest --path <dir or file>
47  *     runtest --path <dir or file> --test-method <testMethodName>
48  *     e.g.)
49  *         runtest --path tests/src/com/android/phone/ServiceStateProviderTest.java \
50  *                 --test-method testGetServiceState
51  */
52 public class ServiceStateProviderTest {
53     private static final String TAG = "ServiceStateProviderTest";
54 
55     private Context mContext;
56     private MockContentResolver mContentResolver;
57     private ServiceState mTestServiceState;
58     private ServiceState mTestServiceStateForSubId1;
59 
60     private final String[] mTestProjection =
61     {
62         ServiceStateTable.VOICE_REG_STATE,
63         ServiceStateTable.DATA_REG_STATE,
64         ServiceStateTable.VOICE_OPERATOR_ALPHA_LONG,
65         ServiceStateTable.VOICE_OPERATOR_ALPHA_SHORT,
66         ServiceStateTable.VOICE_OPERATOR_NUMERIC,
67         ServiceStateTable.DATA_OPERATOR_ALPHA_LONG,
68         ServiceStateTable.DATA_OPERATOR_ALPHA_SHORT,
69         ServiceStateTable.DATA_OPERATOR_NUMERIC,
70         ServiceStateTable.IS_MANUAL_NETWORK_SELECTION,
71         ServiceStateTable.RIL_VOICE_RADIO_TECHNOLOGY,
72         ServiceStateTable.RIL_DATA_RADIO_TECHNOLOGY,
73         ServiceStateTable.CSS_INDICATOR,
74         ServiceStateTable.NETWORK_ID,
75         ServiceStateTable.SYSTEM_ID,
76         ServiceStateTable.CDMA_ROAMING_INDICATOR,
77         ServiceStateTable.CDMA_DEFAULT_ROAMING_INDICATOR,
78         ServiceStateTable.CDMA_ERI_ICON_INDEX,
79         ServiceStateTable.CDMA_ERI_ICON_MODE,
80         ServiceStateTable.IS_EMERGENCY_ONLY,
81         ServiceStateTable.IS_USING_CARRIER_AGGREGATION,
82         ServiceStateTable.OPERATOR_ALPHA_LONG_RAW,
83         ServiceStateTable.OPERATOR_ALPHA_SHORT_RAW,
84     };
85 
86     @Before
setUp()87     public void setUp() throws Exception {
88         mContext = mock(Context.class);
89         mContentResolver = new MockContentResolver() {
90             @Override
91             public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
92                 throw new RuntimeException("notifyChange!");
93             }
94         };
95         doReturn(mContentResolver).when(mContext).getContentResolver();
96 
97         mTestServiceState = new ServiceState();
98         mTestServiceState.setStateOutOfService();
99         mTestServiceStateForSubId1 = new ServiceState();
100         mTestServiceStateForSubId1.setStateOff();
101 
102         // Mock out the actual phone state
103         ServiceStateProvider provider = new ServiceStateProvider() {
104             @Override
105             public ServiceState getServiceState(int subId) {
106                 if (subId == 1) {
107                     return mTestServiceStateForSubId1;
108                 } else {
109                     return mTestServiceState;
110                 }
111             }
112 
113             @Override
114             public int getDefaultSubId() {
115                 return 0;
116             }
117         };
118         ProviderInfo providerInfo = new ProviderInfo();
119         providerInfo.authority = "service-state";
120         provider.attachInfoForTesting(mContext, providerInfo);
121         mContentResolver.addProvider("service-state", provider);
122     }
123 
124     @Test
125     @SmallTest
testQueryServiceStateWithNoSubId()126     public void testQueryServiceStateWithNoSubId() {
127         // Verify that when calling query with no subId in the uri the default ServiceState is
128         // returned.
129         // In this case the subId is set to 0 and the expected service state is
130         // mTestServiceState.
131         verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, mTestServiceState);
132     }
133 
134     @Test
135     @SmallTest
testGetServiceStateWithDefaultSubId()136     public void testGetServiceStateWithDefaultSubId() {
137         // Verify that when calling with the DEFAULT_SUBSCRIPTION_ID the correct ServiceState is
138         // returned
139         // In this case the subId is set to 0 and the expected service state is
140         // mTestServiceState.
141         verifyServiceStateForSubId(
142                 getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
143                 mTestServiceState);
144     }
145 
146     /**
147      * Test querying the service state for a given subId
148      */
149     @Test
150     @SmallTest
testGetServiceStateForSubId()151     public void testGetServiceStateForSubId() {
152         // Verify that when calling with a specific subId the correct ServiceState is returned
153         // In this case the subId is set to 1 and the expected service state is
154         // mTestServiceStateForSubId1
155         verifyServiceStateForSubId(getUriForSubscriptionId(1), mTestServiceStateForSubId1);
156     }
157 
verifyServiceStateForSubId(Uri uri, ServiceState ss)158     private void verifyServiceStateForSubId(Uri uri, ServiceState ss) {
159         Cursor cursor = mContentResolver.query(uri, mTestProjection, "",
160                 null, null);
161         assertNotNull(cursor);
162         cursor.moveToFirst();
163 
164         final int voiceRegState = ss.getState();
165         final int dataRegState = ss.getDataRegistrationState();
166         final String voiceOperatorAlphaLong = ss.getOperatorAlphaLong();
167         final String voiceOperatorAlphaShort = ss.getOperatorAlphaShort();
168         final String voiceOperatorNumeric = ss.getOperatorNumeric();
169         final String dataOperatorAlphaLong = ss.getOperatorAlphaLong();
170         final String dataOperatorAlphaShort = ss.getOperatorAlphaShort();
171         final String dataOperatorNumeric = ss.getOperatorNumeric();
172         final int isManualNetworkSelection = (ss.getIsManualSelection()) ? 1 : 0;
173         final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology();
174         final int rilDataRadioTechnology = ss.getRilDataRadioTechnology();
175         final int cssIndicator = ss.getCssIndicator();
176         final int networkId = ss.getCdmaNetworkId();
177         final int systemId = ss.getCdmaSystemId();
178         final int cdmaRoamingIndicator = ss.getCdmaRoamingIndicator();
179         final int cdmaDefaultRoamingIndicator = ss.getCdmaDefaultRoamingIndicator();
180         final int cdmaEriIconIndex = ss.getCdmaEriIconIndex();
181         final int cdmaEriIconMode = ss.getCdmaEriIconMode();
182         final int isEmergencyOnly = (ss.isEmergencyOnly()) ? 1 : 0;
183         final int isUsingCarrierAggregation = (ss.isUsingCarrierAggregation()) ? 1 : 0;
184         final String operatorAlphaLongRaw = ss.getOperatorAlphaLongRaw();
185         final String operatorAlphaShortRaw = ss.getOperatorAlphaShortRaw();
186 
187         assertEquals(voiceRegState, cursor.getInt(0));
188         assertEquals(dataRegState, cursor.getInt(1));
189         assertEquals(voiceOperatorAlphaLong, cursor.getString(2));
190         assertEquals(voiceOperatorAlphaShort, cursor.getString(3));
191         assertEquals(voiceOperatorNumeric, cursor.getString(4));
192         assertEquals(dataOperatorAlphaLong, cursor.getString(5));
193         assertEquals(dataOperatorAlphaShort, cursor.getString(6));
194         assertEquals(dataOperatorNumeric, cursor.getString(7));
195         assertEquals(isManualNetworkSelection, cursor.getInt(8));
196         assertEquals(rilVoiceRadioTechnology, cursor.getInt(9));
197         assertEquals(rilDataRadioTechnology, cursor.getInt(10));
198         assertEquals(cssIndicator, cursor.getInt(11));
199         assertEquals(networkId, cursor.getInt(12));
200         assertEquals(systemId, cursor.getInt(13));
201         assertEquals(cdmaRoamingIndicator, cursor.getInt(14));
202         assertEquals(cdmaDefaultRoamingIndicator, cursor.getInt(15));
203         assertEquals(cdmaEriIconIndex, cursor.getInt(16));
204         assertEquals(cdmaEriIconMode, cursor.getInt(17));
205         assertEquals(isEmergencyOnly, cursor.getInt(18));
206         assertEquals(isUsingCarrierAggregation, cursor.getInt(19));
207         assertEquals(operatorAlphaLongRaw, cursor.getString(20));
208         assertEquals(operatorAlphaShortRaw, cursor.getString(21));
209     }
210 
211     /**
212      * Test that we don't notify for certain field changes. (e.g. we don't notify when the NetworkId
213      * or SystemId change) This is an intentional behavior change from the broadcast.
214      */
215     @Test
216     @SmallTest
testNoNotify()217     public void testNoNotify() {
218         int subId = 0;
219 
220         ServiceState oldSS = new ServiceState();
221         oldSS.setStateOutOfService();
222         oldSS.setCdmaSystemAndNetworkId(1, 1);
223 
224         ServiceState newSS = new ServiceState();
225         newSS.setStateOutOfService();
226         newSS.setCdmaSystemAndNetworkId(0, 0);
227 
228         // Test that notifyChange is not called for these fields
229         boolean notifyChangeWasCalled = false;
230         try {
231             ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId);
232         } catch (RuntimeException e) {
233             final String message = e.getMessage();
234             if (message != null &&  message.equals("notifyChange!")) {
235                 notifyChangeWasCalled = true;
236             }
237         }
238         assertFalse(notifyChangeWasCalled);
239     }
240 
241     @Test
242     @SmallTest
testNotifyChanged()243     public void testNotifyChanged() {
244         int subId = 0;
245 
246         ServiceState oldSS = new ServiceState();
247         oldSS.setStateOutOfService();
248         oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
249 
250         ServiceState copyOfOldSS = new ServiceState();
251         copyOfOldSS.setStateOutOfService();
252         copyOfOldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
253 
254         ServiceState newSS = new ServiceState();
255         newSS.setStateOutOfService();
256         newSS.setVoiceRegState(ServiceState.STATE_POWER_OFF);
257 
258         // Test that notifyChange is not called with no change in notifyChangeForSubIdAndField
259         boolean notifyChangeWasCalled = false;
260         try {
261             ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, copyOfOldSS, subId);
262         } catch (RuntimeException e) {
263             final String message = e.getMessage();
264             if (message != null &&  message.equals("notifyChange!")) {
265                 notifyChangeWasCalled = true;
266             }
267         }
268         assertFalse(notifyChangeWasCalled);
269 
270         // Test that notifyChange is not called with no change in notifyChangeForSubId
271         notifyChangeWasCalled = false;
272         try {
273             ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, copyOfOldSS, subId);
274         } catch (RuntimeException e) {
275             final String message = e.getMessage();
276             if (message != null &&  message.equals("notifyChange!")) {
277                 notifyChangeWasCalled = true;
278             }
279         }
280         assertFalse(notifyChangeWasCalled);
281 
282         // Test that notifyChange is called by notifyChangeForSubIdAndField when the voice_reg_state
283         // changes
284         notifyChangeWasCalled = false;
285         try {
286             ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId);
287         } catch (RuntimeException e) {
288             final String message = e.getMessage();
289             if (message != null &&  message.equals("notifyChange!")) {
290                 notifyChangeWasCalled = true;
291             }
292         }
293         assertTrue(notifyChangeWasCalled);
294 
295         // Test that notifyChange is called by notifyChangeForSubId when the voice_reg_state changes
296         notifyChangeWasCalled = false;
297         try {
298             ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, newSS, subId);
299         } catch (RuntimeException e) {
300             final String message = e.getMessage();
301             if (message != null &&  message.equals("notifyChange!")) {
302                 notifyChangeWasCalled = true;
303             }
304         }
305         assertTrue(notifyChangeWasCalled);
306     }
307 }
308