/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.providers.telephony; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.ProviderInfo; import android.content.res.Resources; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.IBinder; import android.os.Looper; import android.support.test.InstrumentationRegistry; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import com.android.internal.telephony.CarrierActionAgent; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.GsmCdmaPhone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.ServiceStateTracker; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import static android.app.job.JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS; import static android.Manifest.permission.MODIFY_PHONE_STATE; import static android.provider.Telephony.ServiceStateTable; import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId; import static android.provider.Telephony.ServiceStateTable.getContentValuesForServiceState; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; /** * Tests for simple queries of ServiceStateProvider. * * Build, install and run the tests by running the commands below: * runtest --path <dir or file> * runtest --path <dir or file> --test-method <testMethodName> * e.g.) * runtest --path tests/src/com/android/providers/telephony/ServiceStateProviderTest.java \ * --test-method testGetServiceState */ public class ServiceStateProviderTest { private static final String TAG = "ServiceStateProviderTest"; private Context mContext; private MockContentResolver mContentResolver; private ServiceState testServiceState; private ServiceState testServiceStateForSubId1; private final String[] testProjection = { ServiceStateTable.VOICE_REG_STATE, ServiceStateTable.DATA_REG_STATE, ServiceStateTable.VOICE_OPERATOR_ALPHA_LONG, ServiceStateTable.VOICE_OPERATOR_ALPHA_SHORT, ServiceStateTable.VOICE_OPERATOR_NUMERIC, ServiceStateTable.DATA_OPERATOR_ALPHA_LONG, ServiceStateTable.DATA_OPERATOR_ALPHA_SHORT, ServiceStateTable.DATA_OPERATOR_NUMERIC, ServiceStateTable.IS_MANUAL_NETWORK_SELECTION, ServiceStateTable.RIL_VOICE_RADIO_TECHNOLOGY, ServiceStateTable.RIL_DATA_RADIO_TECHNOLOGY, ServiceStateTable.CSS_INDICATOR, ServiceStateTable.NETWORK_ID, ServiceStateTable.SYSTEM_ID, ServiceStateTable.CDMA_ROAMING_INDICATOR, ServiceStateTable.CDMA_DEFAULT_ROAMING_INDICATOR, ServiceStateTable.CDMA_ERI_ICON_INDEX, ServiceStateTable.CDMA_ERI_ICON_MODE, ServiceStateTable.IS_EMERGENCY_ONLY, ServiceStateTable.IS_DATA_ROAMING_FROM_REGISTRATION, ServiceStateTable.IS_USING_CARRIER_AGGREGATION, }; @Before public void setUp() throws Exception { mContext = mock(Context.class); mContentResolver = new MockContentResolver() { @Override public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { throw new RuntimeException("notifyChange!"); } }; doReturn(mContentResolver).when(mContext).getContentResolver(); testServiceState = new ServiceState(); testServiceState.setStateOutOfService(); testServiceStateForSubId1 = new ServiceState(); testServiceStateForSubId1.setStateOff(); // Mock out the actual phone state ServiceStateProvider provider = new ServiceStateProvider() { @Override public ServiceState getServiceState(int subId) { if (subId == 1) { return testServiceStateForSubId1; } else { return testServiceState; } } @Override public int getDefaultSubId() { return 0; } }; ProviderInfo providerInfo = new ProviderInfo(); providerInfo.authority = "service-state"; provider.attachInfoForTesting(mContext, providerInfo); mContentResolver.addProvider("service-state", provider); } @Test @SmallTest public void testQueryServiceStateWithNoSubId() { // Verify that when calling query with no subId in the uri the default ServiceState is // returned. // In this case the subId is set to 0 and the expected service state is // testServiceState. verifyServiceStateForSubId(ServiceStateTable.CONTENT_URI, testServiceState); } @Test @SmallTest public void testGetServiceStateWithDefaultSubId() { // Verify that when calling with the DEFAULT_SUBSCRIPTION_ID the correct ServiceState is // returned // In this case the subId is set to 0 and the expected service state is // testServiceState. verifyServiceStateForSubId( getUriForSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID), testServiceState); } /** * Test querying the service state for a given subId */ @Test @SmallTest public void testGetServiceStateForSubId() { // Verify that when calling with a specific subId the correct ServiceState is returned // In this case the subId is set to 1 and the expected service state is // testServiceStateForSubId1 verifyServiceStateForSubId(getUriForSubscriptionId(1), testServiceStateForSubId1); } private void verifyServiceStateForSubId(Uri uri, ServiceState ss) { Cursor cursor = mContentResolver.query(uri, testProjection, "", null, null); assertNotNull(cursor); cursor.moveToFirst(); final int voiceRegState = ss.getVoiceRegState(); final int dataRegState = ss.getDataRegState(); final String voiceOperatorAlphaLong = ss.getVoiceOperatorAlphaLong(); final String voiceOperatorAlphaShort = ss.getVoiceOperatorAlphaShort(); final String voiceOperatorNumeric = ss.getVoiceOperatorNumeric(); final String dataOperatorAlphaLong = ss.getDataOperatorAlphaLong(); final String dataOperatorAlphaShort = ss.getDataOperatorAlphaShort(); final String dataOperatorNumeric = ss.getDataOperatorNumeric(); final int isManualNetworkSelection = (ss.getIsManualSelection()) ? 1 : 0; final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology(); final int rilDataRadioTechnology = ss.getRilDataRadioTechnology(); final int cssIndicator = ss.getCssIndicator(); final int networkId = ss.getNetworkId(); final int systemId = ss.getSystemId(); final int cdmaRoamingIndicator = ss.getCdmaRoamingIndicator(); final int cdmaDefaultRoamingIndicator = ss.getCdmaDefaultRoamingIndicator(); final int cdmaEriIconIndex = ss.getCdmaEriIconIndex(); final int cdmaEriIconMode = ss.getCdmaEriIconMode(); final int isEmergencyOnly = (ss.isEmergencyOnly()) ? 1 : 0; final int isDataRoamingFromRegistration = (ss.getDataRoamingFromRegistration()) ? 1 : 0; final int isUsingCarrierAggregation = (ss.isUsingCarrierAggregation()) ? 1 : 0; assertEquals(voiceRegState, cursor.getInt(0)); assertEquals(dataRegState, cursor.getInt(1)); assertEquals(voiceOperatorAlphaLong, cursor.getString(2)); assertEquals(voiceOperatorAlphaShort, cursor.getString(3)); assertEquals(voiceOperatorNumeric, cursor.getString(4)); assertEquals(dataOperatorAlphaLong, cursor.getString(5)); assertEquals(dataOperatorAlphaShort, cursor.getString(6)); assertEquals(dataOperatorNumeric, cursor.getString(7)); assertEquals(isManualNetworkSelection, cursor.getInt(8)); assertEquals(rilVoiceRadioTechnology, cursor.getInt(9)); assertEquals(rilDataRadioTechnology, cursor.getInt(10)); assertEquals(cssIndicator, cursor.getInt(11)); assertEquals(networkId, cursor.getInt(12)); assertEquals(systemId, cursor.getInt(13)); assertEquals(cdmaRoamingIndicator, cursor.getInt(14)); assertEquals(cdmaDefaultRoamingIndicator, cursor.getInt(15)); assertEquals(cdmaEriIconIndex, cursor.getInt(16)); assertEquals(cdmaEriIconMode, cursor.getInt(17)); assertEquals(isEmergencyOnly, cursor.getInt(18)); assertEquals(isDataRoamingFromRegistration, cursor.getInt(19)); assertEquals(isUsingCarrierAggregation, cursor.getInt(20)); } /** * Test that we don't notify for certain field changes. (e.g. we don't notify when the NetworkId * or SystemId change) This is an intentional behavior change from the broadcast. */ @Test @SmallTest public void testNoNotify() { int subId = 0; ServiceState oldSS = new ServiceState(); oldSS.setStateOutOfService(); oldSS.setSystemAndNetworkId(1, 1); ServiceState newSS = new ServiceState(); newSS.setStateOutOfService(); newSS.setSystemAndNetworkId(0, 0); // Test that notifyChange is not called for these fields boolean notifyChangeWasCalled = false; try { ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId); } catch (RuntimeException e) { final String message = e.getMessage(); if (message != null && message.equals("notifyChange!")) { notifyChangeWasCalled = true; } } assertFalse(notifyChangeWasCalled); } @Test @SmallTest public void testNotifyChanged() { int subId = 0; ServiceState oldSS = new ServiceState(); oldSS.setStateOutOfService(); oldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); ServiceState copyOfOldSS = new ServiceState(); copyOfOldSS.setStateOutOfService(); copyOfOldSS.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE); ServiceState newSS = new ServiceState(); newSS.setStateOutOfService(); newSS.setVoiceRegState(ServiceState.STATE_POWER_OFF); // Test that notifyChange is not called with no change in notifyChangeForSubIdAndField boolean notifyChangeWasCalled = false; try { ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, copyOfOldSS, subId); } catch (RuntimeException e) { final String message = e.getMessage(); if (message != null && message.equals("notifyChange!")) { notifyChangeWasCalled = true; } } assertFalse(notifyChangeWasCalled); // Test that notifyChange is not called with no change in notifyChangeForSubId notifyChangeWasCalled = false; try { ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, copyOfOldSS, subId); } catch (RuntimeException e) { final String message = e.getMessage(); if (message != null && message.equals("notifyChange!")) { notifyChangeWasCalled = true; } } assertFalse(notifyChangeWasCalled); // Test that notifyChange is called by notifyChangeForSubIdAndField when the voice_reg_state // changes notifyChangeWasCalled = false; try { ServiceStateProvider.notifyChangeForSubIdAndField(mContext, oldSS, newSS, subId); } catch (RuntimeException e) { final String message = e.getMessage(); if (message != null && message.equals("notifyChange!")) { notifyChangeWasCalled = true; } } assertTrue(notifyChangeWasCalled); // Test that notifyChange is called by notifyChangeForSubId when the voice_reg_state changes notifyChangeWasCalled = false; try { ServiceStateProvider.notifyChangeForSubId(mContext, oldSS, newSS, subId); } catch (RuntimeException e) { final String message = e.getMessage(); if (message != null && message.equals("notifyChange!")) { notifyChangeWasCalled = true; } } assertTrue(notifyChangeWasCalled); } }