| /* |
| * 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.internal.telephony; |
| |
| import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION; |
| |
| import static com.android.internal.telephony.uicc.IccCardStatus.CardState.CARDSTATE_PRESENT; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNotSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.anyInt; |
| import static org.mockito.ArgumentMatchers.anyLong; |
| import static org.mockito.ArgumentMatchers.anyString; |
| import static org.mockito.ArgumentMatchers.nullable; |
| import static org.mockito.Mockito.atLeast; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.eq; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import android.Manifest; |
| import android.app.AppOpsManager; |
| import android.content.ContentResolver; |
| import android.content.ContentValues; |
| import android.content.Intent; |
| import android.os.Build; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.ParcelUuid; |
| import android.os.PersistableBundle; |
| import android.os.UserHandle; |
| import android.provider.Settings; |
| import android.telephony.CarrierConfigManager; |
| import android.telephony.SubscriptionInfo; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.UiccSlotInfo; |
| import android.test.mock.MockContentResolver; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import androidx.test.filters.FlakyTest; |
| |
| import com.android.internal.telephony.uicc.IccCardStatus; |
| import com.android.internal.telephony.uicc.UiccController; |
| import com.android.internal.telephony.uicc.UiccSlot; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.Mock; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| public class SubscriptionControllerTest extends TelephonyTest { |
| private static final int SINGLE_SIM = 1; |
| private static final int DUAL_SIM = 2; |
| private static final int FAKE_SUBID = 123; |
| private String mCallingPackage; |
| private String mCallingFeature; |
| private SubscriptionController mSubscriptionControllerUT; |
| private MockContentResolver mMockContentResolver; |
| private FakeTelephonyProvider mFakeTelephonyProvider; |
| @Mock |
| private UiccSlot mUiccSlot; |
| @Mock |
| private ITelephonyRegistry.Stub mTelephonyRegisteryMock; |
| @Mock |
| private MultiSimSettingController mMultiSimSettingControllerMock; |
| @Mock |
| private ISetOpportunisticDataCallback mSetOpptDataCallback; |
| @Mock |
| private Handler mHandler; |
| @Mock |
| private SubscriptionInfo mMockSubscriptionInfo; |
| private PersistableBundle mCarrierConfigs; |
| |
| private static final String MAC_ADDRESS_PREFIX = "mac_"; |
| private static final String DISPLAY_NAME_PREFIX = "my_phone_"; |
| |
| private static final String UNAVAILABLE_ICCID = ""; |
| private static final String UNAVAILABLE_NUMBER = ""; |
| private static final String DISPLAY_NUMBER = "123456"; |
| private static final String DISPLAY_NAME = "testing_display_name"; |
| |
| @Before |
| public void setUp() throws Exception { |
| super.setUp("SubscriptionControllerTest"); |
| |
| doReturn(SINGLE_SIM).when(mTelephonyManager).getSimCount(); |
| doReturn(SINGLE_SIM).when(mTelephonyManager).getPhoneCount(); |
| mMockContentResolver = (MockContentResolver) mContext.getContentResolver(); |
| mFakeTelephonyProvider = new FakeTelephonyProvider(); |
| mMockContentResolver.addProvider(SubscriptionManager.CONTENT_URI.getAuthority(), |
| mFakeTelephonyProvider); |
| replaceInstance(SubscriptionController.class, "sInstance", null, null); |
| replaceInstance(MultiSimSettingController.class, "sInstance", null, |
| mMultiSimSettingControllerMock); |
| |
| mSubscriptionControllerUT = SubscriptionController.init(mContext); |
| mCallingPackage = mContext.getOpPackageName(); |
| mCallingFeature = mContext.getAttributionTag(); |
| |
| doReturn(1).when(mProxyController).getMaxRafSupported(); |
| |
| // Carrier Config |
| mCarrierConfigs = mContextFixture.getCarrierConfigBundle(); |
| |
| mContextFixture.putIntArrayResource(com.android.internal.R.array.sim_colors, new int[]{5}); |
| |
| setupMocksForTelephonyPermissions(Build.VERSION_CODES.R); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| mContextFixture.addCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| /* should clear fake content provider and resolver here */ |
| mContext.getContentResolver().delete(SubscriptionManager.CONTENT_URI, null, null); |
| |
| /*clear sub info in mSubscriptionControllerUT since they will otherwise be persistent |
| * between each test case. */ |
| mSubscriptionControllerUT.clearSubInfo(); |
| mSubscriptionControllerUT.resetStaticMembers(); |
| |
| /* clear settings for default voice/data/sms sub ID */ |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, |
| SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION, |
| SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION, |
| SubscriptionManager.INVALID_SUBSCRIPTION_ID); |
| |
| mSubscriptionControllerUT = null; |
| super.tearDown(); |
| } |
| |
| @Test @SmallTest |
| public void testInsertSim() { |
| //verify there is no sim inserted in the SubscriptionManager |
| assertEquals(0, mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage, |
| mCallingFeature)); |
| |
| int slotID = 0; |
| //insert one Subscription Info |
| mSubscriptionControllerUT.addSubInfoRecord("test", slotID); |
| |
| //verify there is one sim |
| assertEquals(1, mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage, |
| mCallingFeature)); |
| |
| //sanity for slot id and sub id |
| List<SubscriptionInfo> mSubList = mSubscriptionControllerUT |
| .getActiveSubscriptionInfoList(mCallingPackage, mCallingFeature); |
| assertTrue(mSubList != null && mSubList.size() > 0); |
| for (int i = 0; i < mSubList.size(); i++) { |
| assertTrue(SubscriptionManager.isValidSubscriptionId( |
| mSubList.get(i).getSubscriptionId())); |
| assertTrue(SubscriptionManager.isValidSlotIndex(mSubList.get(i).getSimSlotIndex())); |
| } |
| } |
| |
| @Test @SmallTest |
| public void testChangeSIMProperty() { |
| int dataRoaming = 1; |
| int iconTint = 1; |
| String disName = "TESTING"; |
| String disNum = "12345"; |
| boolean isOpportunistic = true; |
| |
| testInsertSim(); |
| /* Get SUB ID */ |
| int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false); |
| assertTrue(subIds != null && subIds.length != 0); |
| int subID = subIds[0]; |
| |
| /* Getting, there is no direct getter function for each fields of property */ |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subID, mCallingPackage, mCallingFeature); |
| |
| /* Setting */ |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(disName, subID, |
| SubscriptionManager.NAME_SOURCE_USER_INPUT); |
| mSubscriptionControllerUT.setDataRoaming(dataRoaming, subID); |
| mSubscriptionControllerUT.setDisplayNumber(disNum, subID); |
| mSubscriptionControllerUT.setIconTint(iconTint, subID); |
| mSubscriptionControllerUT.setOpportunistic(isOpportunistic, subID, mCallingPackage); |
| |
| subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subID, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(dataRoaming, subInfo.getDataRoaming()); |
| assertEquals(disName, subInfo.getDisplayName()); |
| assertEquals(iconTint, subInfo.getIconTint()); |
| assertEquals(disNum, subInfo.getNumber()); |
| assertEquals(isOpportunistic, subInfo.isOpportunistic()); |
| |
| /* verify broadcast intent */ |
| ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); |
| verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture()); |
| assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED, |
| captorIntent.getValue().getAction()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc() { |
| testInsertSim(); |
| |
| /* Get SUB ID */ |
| int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false); |
| assertTrue(subIds != null && subIds.length != 0); |
| int subID = subIds[0]; |
| |
| /* Setting */ |
| String disName = "TESTING"; |
| int nameSource = SubscriptionManager.NAME_SOURCE_SIM_SPN; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(disName, subID, nameSource); |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subID, mCallingPackage, mCallingFeature); |
| assertNotNull(subInfo); |
| assertEquals(disName, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| |
| /* verify broadcast intent */ |
| ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); |
| verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture()); |
| assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED, |
| captorIntent.getValue().getAction()); |
| |
| } |
| |
| private void setSimEmbedded(boolean isEmbedded) throws Exception { |
| ContentValues values = new ContentValues(); |
| values.put(SubscriptionManager.IS_EMBEDDED, isEmbedded ? 1 : 0); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + getFirstSubId(), |
| null); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc_updateNameSourceCarrierWithEmbeddedSim() |
| throws Exception { |
| testInsertSim(); |
| |
| // Set values of DB |
| setSimEmbedded(true); |
| int subId = getFirstSubId(); |
| int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(DISPLAY_NAME, subId, nameSource); |
| |
| // Update with new value |
| String newDisplayName = "display_name_pnn"; |
| int newNameSource = SubscriptionManager.NAME_SOURCE_SIM_PNN; |
| |
| // Save to DB after updated |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(newDisplayName, subId, newNameSource); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(DISPLAY_NAME, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc_updateNameSourceCarrierWithConfigIsNull() |
| throws Exception { |
| testInsertSim(); |
| |
| // Set values of DB |
| setSimEmbedded(false); |
| int subId = getFirstSubId(); |
| int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(DISPLAY_NAME, subId, nameSource); |
| |
| // Update with new value |
| String newDisplayName = "display_name_spn"; |
| int newNameSource = SubscriptionManager.NAME_SOURCE_SIM_SPN; |
| when(mCarrierConfigManager.getConfigForSubId(subId)).thenReturn(null); |
| |
| // Save to DB after updated |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(newDisplayName, subId, newNameSource); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(DISPLAY_NAME, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc_updateNameSourceCarrierWithCarrierNameOverride() |
| throws Exception { |
| testInsertSim(); |
| |
| // Set values of DB |
| setSimEmbedded(false); |
| int subId = getFirstSubId(); |
| int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(DISPLAY_NAME, subId, nameSource); |
| |
| // Update with new value |
| int newNameSource = SubscriptionManager.NAME_SOURCE_SIM_SPN; |
| String newDisplayName = "display_name_spn"; |
| mCarrierConfigs.putBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL, true); |
| |
| // Save to DB after updated |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(newDisplayName, subId, newNameSource); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(DISPLAY_NAME, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc_updateNameSourceCarrierWithSpnAndCarrierName() |
| throws Exception { |
| testInsertSim(); |
| |
| // Set values of DB |
| setSimEmbedded(false); |
| int subId = getFirstSubId(); |
| int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(DISPLAY_NAME, subId, nameSource); |
| |
| // Update with new value |
| int newNameSource = SubscriptionManager.NAME_SOURCE_SIM_SPN; |
| String carrierName = "testing_carrier_name"; |
| String newDisplayName = "display_name_spn"; |
| when(mUiccController.getUiccProfileForPhone(anyInt())).thenReturn(mUiccProfile); |
| when(mUiccProfile.getServiceProviderName()).thenReturn(null); |
| mCarrierConfigs.putBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL, false); |
| mCarrierConfigs.putString(CarrierConfigManager.KEY_CARRIER_NAME_STRING, carrierName); |
| |
| // Save to DB after updated |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(newDisplayName, subId, newNameSource); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(DISPLAY_NAME, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc_updateNameSourcePnnToNameSourceCarrierId() |
| throws Exception { |
| testInsertSim(); |
| |
| // Set values of DB |
| int subId = getFirstSubId(); |
| int nameSource = SubscriptionManager.NAME_SOURCE_SIM_PNN; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(DISPLAY_NAME, subId, nameSource); |
| |
| // Update with new value |
| String newDisplayName = "display_name_carrier_id"; |
| int newNameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID; |
| when(mPhone.getPlmn()).thenReturn("testing_pnn"); |
| |
| // Save to DB after updated |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(newDisplayName, subId, newNameSource); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(DISPLAY_NAME, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetDisplayNameSrc_updateNameSourceUserInputToNameSourceSpn() |
| throws Exception { |
| testInsertSim(); |
| |
| // Set values of DB |
| int subId = getFirstSubId(); |
| int nameSource = SubscriptionManager.NAME_SOURCE_USER_INPUT; |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(DISPLAY_NAME, subId, nameSource); |
| |
| // Update with new value |
| String newDisplayName = "display_name_spn"; |
| int newNameSource = SubscriptionManager.NAME_SOURCE_SIM_SPN; |
| |
| // Save to DB after updated |
| mSubscriptionControllerUT.setDisplayNameUsingSrc(newDisplayName, subId, newNameSource); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subInfo); |
| assertEquals(DISPLAY_NAME, subInfo.getDisplayName()); |
| assertEquals(nameSource, subInfo.getNameSource()); |
| } |
| |
| @Test @SmallTest |
| public void testIsExistingNameSourceStillValid_pnnIsNotNull_returnTrue() { |
| when((mMockSubscriptionInfo).getSubscriptionId()).thenReturn(FAKE_SUBID); |
| when(mMockSubscriptionInfo.getNameSource()) |
| .thenReturn(SubscriptionManager.NAME_SOURCE_SIM_PNN); |
| when(mPhone.getPlmn()).thenReturn("testing_pnn"); |
| |
| assertTrue(mSubscriptionControllerUT.isExistingNameSourceStillValid(mMockSubscriptionInfo)); |
| } |
| |
| @Test @SmallTest |
| public void testIsExistingNameSourceStillValid_spnIsNotNull_returnTrue() { |
| when((mMockSubscriptionInfo).getSubscriptionId()).thenReturn(FAKE_SUBID); |
| when(mMockSubscriptionInfo.getNameSource()) |
| .thenReturn(SubscriptionManager.NAME_SOURCE_SIM_SPN); |
| when(mUiccController.getUiccProfileForPhone(anyInt())).thenReturn(mUiccProfile); |
| when(mUiccProfile.getServiceProviderName()).thenReturn("testing_spn"); |
| |
| assertTrue(mSubscriptionControllerUT.isExistingNameSourceStillValid(mMockSubscriptionInfo)); |
| } |
| |
| @Test @SmallTest |
| public void testIsExistingNameSourceStillValid_simIsEmbedded_returnTrue() { |
| when(mMockSubscriptionInfo.isEmbedded()).thenReturn(true); |
| when((mMockSubscriptionInfo).getSubscriptionId()).thenReturn(FAKE_SUBID); |
| when(mMockSubscriptionInfo.getNameSource()) |
| .thenReturn(SubscriptionManager.NAME_SOURCE_CARRIER); |
| |
| assertTrue(mSubscriptionControllerUT.isExistingNameSourceStillValid(mMockSubscriptionInfo)); |
| } |
| |
| @Test @SmallTest |
| public void testIsExistingNameSourceStillValid_carrierConfigIsNull_returnTrue() { |
| when(mMockSubscriptionInfo.isEmbedded()).thenReturn(false); |
| when((mMockSubscriptionInfo).getSubscriptionId()).thenReturn(FAKE_SUBID); |
| when(mMockSubscriptionInfo.getNameSource()) |
| .thenReturn(SubscriptionManager.NAME_SOURCE_CARRIER); |
| when(mCarrierConfigManager.getConfigForSubId(FAKE_SUBID)).thenReturn(null); |
| |
| assertTrue(mSubscriptionControllerUT.isExistingNameSourceStillValid(mMockSubscriptionInfo)); |
| } |
| |
| @Test @SmallTest |
| public void testIsExistingNameSourceStillValid_carrierNameOverrideIsTrue_returnTrue() { |
| when(mMockSubscriptionInfo.isEmbedded()).thenReturn(false); |
| when((mMockSubscriptionInfo).getSubscriptionId()).thenReturn(FAKE_SUBID); |
| when(mMockSubscriptionInfo.getNameSource()) |
| .thenReturn(SubscriptionManager.NAME_SOURCE_CARRIER); |
| mCarrierConfigs.putBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL, true); |
| |
| assertTrue(mSubscriptionControllerUT.isExistingNameSourceStillValid(mMockSubscriptionInfo)); |
| } |
| |
| @Test @SmallTest |
| public void testIsExistingNameSourceStillValid_spnIsNullAndCarrierNameIsNotNull_returnTrue() { |
| when(mMockSubscriptionInfo.isEmbedded()).thenReturn(false); |
| when((mMockSubscriptionInfo).getSubscriptionId()).thenReturn(FAKE_SUBID); |
| when(mMockSubscriptionInfo.getNameSource()) |
| .thenReturn(SubscriptionManager.NAME_SOURCE_CARRIER); |
| when(mUiccController.getUiccProfileForPhone(anyInt())).thenReturn(mUiccProfile); |
| when(mUiccProfile.getServiceProviderName()).thenReturn(null); |
| mCarrierConfigs.putBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL, false); |
| mCarrierConfigs.putString(CarrierConfigManager.KEY_CARRIER_NAME_STRING, |
| "testing_carrier_name"); |
| |
| assertTrue(mSubscriptionControllerUT.isExistingNameSourceStillValid(mMockSubscriptionInfo)); |
| } |
| |
| @Test @SmallTest |
| public void testCleanUpSIM() { |
| testInsertSim(); |
| assertFalse(mSubscriptionControllerUT.isActiveSubId(2)); |
| mSubscriptionControllerUT.clearSubInfo(); |
| assertFalse(mSubscriptionControllerUT.isActiveSubId(1)); |
| assertEquals(SubscriptionManager.SIM_NOT_INSERTED, |
| mSubscriptionControllerUT.getSlotIndex(1)); |
| } |
| |
| @Test @SmallTest |
| public void testDefaultSubIdOnSingleSimDevice() { |
| assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getDefaultDataSubId()); |
| assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getDefaultSmsSubId()); |
| assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getDefaultSmsSubId()); |
| /* insert one sim */ |
| testInsertSim(); |
| // if support single sim, sms/data/voice default sub should be the same |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultDataSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSmsSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultVoiceSubId()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetMCCMNC() { |
| testInsertSim(); |
| String mCcMncVERIZON = "310004"; |
| mSubscriptionControllerUT.setMccMnc(mCcMncVERIZON, 1); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(1, mCallingPackage, mCallingFeature); |
| assertNotNull(subInfo); |
| assertEquals(Integer.parseInt(mCcMncVERIZON.substring(0, 3)), subInfo.getMcc()); |
| assertEquals(Integer.parseInt(mCcMncVERIZON.substring(3)), subInfo.getMnc()); |
| |
| /* verify broadcast intent */ |
| ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); |
| verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture()); |
| assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED, |
| captorIntent.getValue().getAction()); |
| } |
| |
| @Test @SmallTest |
| public void testSetGetCarrierId() { |
| testInsertSim(); |
| int carrierId = 1234; |
| mSubscriptionControllerUT.setCarrierId(carrierId, 1); |
| |
| SubscriptionInfo subInfo = mSubscriptionControllerUT |
| .getActiveSubscriptionInfo(1, mCallingPackage, mCallingFeature); |
| assertNotNull(subInfo); |
| assertEquals(carrierId, subInfo.getCarrierId()); |
| |
| /* verify broadcast intent */ |
| ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); |
| verify(mContext, atLeast(1)).sendBroadcast(captorIntent.capture()); |
| assertEquals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED, |
| captorIntent.getValue().getAction()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testSetDefaultDataSubId() throws Exception { |
| doReturn(1).when(mPhone).getSubId(); |
| |
| mSubscriptionControllerUT.setDefaultDataSubId(1); |
| |
| ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class); |
| verify(mContext, times(1)).sendStickyBroadcastAsUser( |
| captorIntent.capture(), eq(UserHandle.ALL)); |
| |
| Intent intent = captorIntent.getValue(); |
| assertEquals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED, intent.getAction()); |
| |
| Bundle b = intent.getExtras(); |
| |
| assertTrue(b.containsKey(PhoneConstants.SUBSCRIPTION_KEY)); |
| assertEquals(1, b.getInt(PhoneConstants.SUBSCRIPTION_KEY)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testMigrateImsSettings() throws Exception { |
| testInsertSim(); |
| int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false); |
| assertTrue(subIds != null && subIds.length != 0); |
| int subID = subIds[0]; |
| |
| // Set default void subId. |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, |
| subID); |
| |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.ENHANCED_4G_MODE_ENABLED, |
| 1); |
| |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.VT_IMS_ENABLED, |
| 0); |
| |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ENABLED, |
| 1); |
| |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_MODE, |
| 2); |
| |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ROAMING_MODE, |
| 3); |
| |
| mSubscriptionControllerUT.migrateImsSettings(); |
| |
| // Global settings should be all set. |
| assertEquals(-1, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.ENHANCED_4G_MODE_ENABLED)); |
| |
| assertEquals(-1, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.VT_IMS_ENABLED)); |
| |
| assertEquals(-1, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ENABLED)); |
| |
| assertEquals(-1, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_MODE)); |
| |
| assertEquals(-1, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ROAMING_MODE)); |
| |
| // The values should be migrated to its DB. |
| assertEquals("1", mSubscriptionControllerUT.getSubscriptionProperty( |
| subID, |
| SubscriptionManager.ENHANCED_4G_MODE_ENABLED, |
| mCallingPackage, |
| mCallingFeature)); |
| |
| assertEquals("0", mSubscriptionControllerUT.getSubscriptionProperty( |
| subID, |
| SubscriptionManager.VT_IMS_ENABLED, |
| mCallingPackage, |
| mCallingFeature)); |
| |
| assertEquals("1", mSubscriptionControllerUT.getSubscriptionProperty( |
| subID, |
| SubscriptionManager.WFC_IMS_ENABLED, |
| mCallingPackage, |
| mCallingFeature)); |
| |
| assertEquals("2", mSubscriptionControllerUT.getSubscriptionProperty( |
| subID, |
| SubscriptionManager.WFC_IMS_MODE, |
| mCallingPackage, |
| mCallingFeature)); |
| |
| assertEquals("3", mSubscriptionControllerUT.getSubscriptionProperty( |
| subID, |
| SubscriptionManager.WFC_IMS_ROAMING_MODE, |
| mCallingPackage, |
| mCallingFeature)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testSkipMigrateImsSettings() throws Exception { |
| |
| // Set default invalid subId. |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, |
| -1); |
| |
| int enhanced4gModeEnabled = 1; |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.ENHANCED_4G_MODE_ENABLED, |
| enhanced4gModeEnabled); |
| |
| int vtImsEnabled = 0; |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.VT_IMS_ENABLED, |
| vtImsEnabled); |
| |
| int wfcImsEnabled = 1; |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ENABLED, |
| wfcImsEnabled); |
| |
| int wfcImsMode = 2; |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_MODE, |
| wfcImsMode); |
| |
| int wfcImsRoamingMode = 3; |
| Settings.Global.putInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ROAMING_MODE, |
| wfcImsRoamingMode); |
| |
| mSubscriptionControllerUT.migrateImsSettings(); |
| |
| // Migration should be skipped because subId was invalid |
| assertEquals(enhanced4gModeEnabled, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.ENHANCED_4G_MODE_ENABLED)); |
| |
| assertEquals(vtImsEnabled, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.VT_IMS_ENABLED)); |
| |
| assertEquals(wfcImsEnabled, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ENABLED)); |
| |
| assertEquals(wfcImsMode, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_MODE)); |
| |
| assertEquals(wfcImsRoamingMode, Settings.Global.getInt(mContext.getContentResolver(), |
| Settings.Global.WFC_IMS_ROAMING_MODE)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testOpptSubInfoListChanged() throws Exception { |
| registerMockTelephonyRegistry(); |
| verify(mTelephonyRegistryManager, times(0)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| |
| testInsertSim(); |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 0); |
| |
| // Neither sub1 or sub2 are opportunistic. So getOpportunisticSubscriptions |
| // should return empty list and no callback triggered. |
| List<SubscriptionInfo> opptSubList = mSubscriptionControllerUT |
| .getOpportunisticSubscriptions(mCallingPackage, mCallingFeature); |
| |
| assertTrue(opptSubList.isEmpty()); |
| verify(mTelephonyRegistryManager, times(0)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| |
| // Setting sub2 as opportunistic should trigger callback. |
| mSubscriptionControllerUT.setOpportunistic(true, 2, mCallingPackage); |
| |
| verify(mTelephonyRegistryManager, times(1)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| opptSubList = mSubscriptionControllerUT |
| .getOpportunisticSubscriptions(mCallingPackage, mCallingFeature); |
| assertEquals(1, opptSubList.size()); |
| assertEquals("test2", opptSubList.get(0).getIccId()); |
| |
| // Changing non-opportunistic sub1 shouldn't trigger callback. |
| mSubscriptionControllerUT.setDisplayNameUsingSrc("DisplayName", 1, |
| SubscriptionManager.NAME_SOURCE_SIM_SPN); |
| verify(mTelephonyRegistryManager, times(1)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| |
| mSubscriptionControllerUT.setDisplayNameUsingSrc("DisplayName", 2, |
| SubscriptionManager.NAME_SOURCE_SIM_SPN); |
| verify(mTelephonyRegistryManager, times(2)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| } |
| |
| @Test @SmallTest |
| public void testInsertRemoteSim() { |
| makeThisDeviceMultiSimCapable(); |
| |
| // verify there are no sim's in the system. |
| assertEquals(0, mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage, |
| mCallingFeature)); |
| |
| addAndVerifyRemoteSimAddition(1, 0); |
| } |
| |
| private void addAndVerifyRemoteSimAddition(int num, int numOfCurrentSubs) { |
| // Verify the number of current subs in the system |
| assertEquals(numOfCurrentSubs, |
| mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage, mCallingFeature)); |
| |
| // if there are current subs in the system, get that info |
| List<SubscriptionInfo> mSubList; |
| ArrayList<String> macAddresses = new ArrayList<>(); |
| ArrayList<String> displayNames = new ArrayList<>(); |
| if (numOfCurrentSubs > 0) { |
| mSubList = mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| assertNotNull(mSubList); |
| assertEquals(numOfCurrentSubs, mSubList.size()); |
| for (SubscriptionInfo info : mSubList) { |
| assertNotNull(info.getIccId()); |
| assertNotNull(info.getDisplayName()); |
| macAddresses.add(info.getIccId()); |
| displayNames.add(info.getDisplayName().toString()); |
| } |
| } |
| |
| // To add more subs, we need to create macAddresses + displaynames. |
| for (int i = 0; i < num; i++) { |
| macAddresses.add(MAC_ADDRESS_PREFIX + (numOfCurrentSubs + i)); |
| displayNames.add(DISPLAY_NAME_PREFIX + (numOfCurrentSubs + i)); |
| } |
| |
| // Add subs - one at a time and verify the contents in subscription info data structs |
| for (int i = 0; i < num; i++) { |
| int index = numOfCurrentSubs + i; |
| mSubscriptionControllerUT.addSubInfo(macAddresses.get(index), displayNames.get(index), |
| SubscriptionManager.SLOT_INDEX_FOR_REMOTE_SIM_SUB, |
| SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM); |
| |
| // make sure the subscription is added in SubscriptionController data structs |
| Map<Integer, ArrayList<Integer>> slotIndexToSubsMap = |
| mSubscriptionControllerUT.getSlotIndexToSubIdsMap(); |
| assertNotNull(slotIndexToSubsMap); |
| // Since All remote sim's go to the same slot index, there should only be one entry |
| assertEquals(1, slotIndexToSubsMap.size()); |
| |
| // get all the subscriptions available. should be what is just added in this method |
| // PLUS the number of subs that already existed before |
| int expectedNumOfSubs = numOfCurrentSubs + i + 1; |
| ArrayList<Integer> subIdsList = |
| slotIndexToSubsMap.get(SubscriptionManager.SLOT_INDEX_FOR_REMOTE_SIM_SUB); |
| assertNotNull(subIdsList); |
| assertEquals(expectedNumOfSubs, subIdsList.size()); |
| |
| // validate slot index, sub id etc |
| mSubList = mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| assertNotNull(mSubList); |
| assertEquals(expectedNumOfSubs, mSubList.size()); |
| |
| // sort on subscription-id which will make sure the previously existing subscriptions |
| // are in earlier slots in the array |
| mSubList.sort(SUBSCRIPTION_INFO_COMPARATOR); |
| |
| // Verify the subscription data. Skip the verification for the existing subs. |
| for (int j = numOfCurrentSubs; j < mSubList.size(); j++) { |
| SubscriptionInfo info = mSubList.get(j); |
| assertTrue(SubscriptionManager.isValidSubscriptionId(info.getSubscriptionId())); |
| assertEquals(SubscriptionManager.SLOT_INDEX_FOR_REMOTE_SIM_SUB, |
| info.getSimSlotIndex()); |
| assertEquals(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM, |
| info.getSubscriptionType()); |
| assertEquals(macAddresses.get(j), info.getIccId()); |
| assertEquals(displayNames.get(j), info.getDisplayName()); |
| } |
| } |
| } |
| |
| private static final Comparator<SubscriptionInfo> SUBSCRIPTION_INFO_COMPARATOR = |
| Comparator.comparingInt(o -> o.getSubscriptionId()); |
| |
| @Test @SmallTest |
| public void testInsertMultipleRemoteSims() { |
| makeThisDeviceMultiSimCapable(); |
| |
| // verify that there are no subscription info records |
| assertEquals(0, mSubscriptionControllerUT.getAllSubInfoCount(mCallingPackage, |
| mCallingFeature)); |
| Map<Integer, ArrayList<Integer>> slotIndexToSubsMap = |
| mSubscriptionControllerUT.getSlotIndexToSubIdsMap(); |
| assertNotNull(slotIndexToSubsMap); |
| assertTrue(slotIndexToSubsMap.isEmpty()); |
| |
| // Add a few subscriptions |
| addAndVerifyRemoteSimAddition(4, 0); |
| } |
| |
| @FlakyTest |
| @Test @SmallTest |
| public void testDefaultSubIdOnMultiSimDevice() { |
| makeThisDeviceMultiSimCapable(); |
| |
| // Initially, defaults should be -1 |
| assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getDefaultDataSubId()); |
| assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getDefaultSmsSubId()); |
| assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getDefaultSmsSubId()); |
| |
| // Insert one Remote-Sim. |
| testInsertRemoteSim(); |
| |
| // defaults should be set to this newly-inserted subscription |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultDataSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSmsSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultVoiceSubId()); |
| |
| // Add a few subscriptions |
| addAndVerifyRemoteSimAddition(4, 1); |
| |
| // defaults should be still be set to the first sub - and unchanged by the addition of |
| // the above multiple sims. |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultDataSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSmsSubId()); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultVoiceSubId()); |
| } |
| |
| @Test @SmallTest |
| public void testRemoveSubscription() { |
| makeThisDeviceMultiSimCapable(); |
| |
| /* insert some sims */ |
| testInsertMultipleRemoteSims(); |
| assertEquals(1, mSubscriptionControllerUT.getDefaultSubId()); |
| int[] subIdsArray = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false); |
| assertTrue(subIdsArray.length > 0); |
| int len = subIdsArray.length; |
| |
| // remove the first sim - which also is the default sim. |
| int result = mSubscriptionControllerUT.removeSubInfo(MAC_ADDRESS_PREFIX + 0, |
| SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM); |
| |
| assertTrue(result > 0); |
| // now check the number of subs left. should be one less than earlier |
| int[] newSubIdsArray = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false); |
| assertTrue(newSubIdsArray.length > 0); |
| assertEquals(len - 1, newSubIdsArray.length); |
| |
| // now check that there is a new default |
| assertNotSame(1, mSubscriptionControllerUT.getDefaultSubId()); |
| } |
| |
| private void makeThisDeviceMultiSimCapable() { |
| doReturn(10).when(mTelephonyManager).getSimCount(); |
| } |
| |
| @Test |
| @SmallTest |
| public void testSetSubscriptionGroupWithModifyPermission() throws Exception { |
| testInsertSim(); |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 0); |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| |
| int[] subIdList = new int[] {1, 2}; |
| try { |
| mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| fail("createSubscriptionGroup should fail with no permission."); |
| } catch (SecurityException e) { |
| // Expected result. |
| } |
| |
| // With modify permission it should succeed. |
| mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE); |
| ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| assertNotEquals(null, groupId); |
| |
| // Calling it again should generate a new group ID. |
| ParcelUuid newGroupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| assertNotEquals(null, newGroupId); |
| assertNotEquals(groupId, newGroupId); |
| } |
| |
| @Test |
| @SmallTest |
| public void testCreateSubscriptionGroupWithCarrierPrivilegePermission() throws Exception { |
| testInsertSim(); |
| // Adding a second profile and mark as embedded. |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 1); |
| ContentValues values = new ContentValues(); |
| values.put(SubscriptionManager.IS_EMBEDDED, 1); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); |
| mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); |
| |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| |
| int[] subIdList = new int[] {1, 2}; |
| // It should fail since it has no permission. |
| try { |
| mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| fail("createSubscriptionGroup should fail with no permission."); |
| } catch (SecurityException e) { |
| // Expected result. |
| } |
| |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(1); |
| try { |
| mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| fail("createSubscriptionGroup should fail with no permission on sub 2."); |
| } catch (SecurityException e) { |
| // Expected result. |
| } |
| |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); |
| ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| assertNotEquals(null, groupId); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mContext.getOpPackageName(), |
| mContext.getAttributionTag()); |
| |
| // Put sub3 into slot 1 to make sub2 inactive. |
| mContextFixture.addCallingOrSelfPermission( |
| android.Manifest.permission.MODIFY_PHONE_STATE); |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("test3", 1); |
| mContextFixture.removeCallingOrSelfPermission( |
| android.Manifest.permission.MODIFY_PHONE_STATE); |
| // As sub2 is inactive, it will checks carrier privilege against access rules in the db. |
| doReturn(true).when(mSubscriptionManager).canManageSubscription( |
| eq(subInfoList.get(1)), anyString()); |
| |
| ParcelUuid newGroupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| assertNotEquals(null, newGroupId); |
| assertNotEquals(groupId, newGroupId); |
| } |
| |
| @Test |
| @SmallTest |
| public void testAddSubscriptionIntoGroupWithCarrierPrivilegePermission() throws Exception { |
| testInsertSim(); |
| // Adding a second profile and mark as embedded. |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 1); |
| ContentValues values = new ContentValues(); |
| values.put(SubscriptionManager.IS_EMBEDDED, 1); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); |
| mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); |
| |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| |
| // Create group for sub 1. |
| int[] subIdList = new int[] {1}; |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(1); |
| ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, "packageName1"); |
| |
| // Try to add sub 2 into group of sub 1. |
| // Should fail as it doesn't have carrier privilege on sub 2. |
| try { |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| new int[] {2}, groupId, "packageName1"); |
| fail("addSubscriptionsIntoGroup should fail with no permission on sub 2."); |
| } catch (SecurityException e) { |
| // Expected result. |
| } |
| |
| doReturn(false).when(mTelephonyManager).hasCarrierPrivileges(1); |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); |
| // Try to add sub 2 into group of sub 1. |
| // Should fail as it doesn't have carrier privilege on sub 1. |
| try { |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| new int[] {2}, groupId, "packageName2"); |
| fail("addSubscriptionsIntoGroup should fail with no permission on the group (sub 1)."); |
| } catch (SecurityException e) { |
| // Expected result. |
| } |
| |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(1); |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup(new int[] {2}, groupId, "packageName2"); |
| List<SubscriptionInfo> infoList = mSubscriptionControllerUT |
| .getSubscriptionsInGroup(groupId, "packageName2", "feature2"); |
| assertEquals(2, infoList.size()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testUpdateSubscriptionGroupWithCarrierPrivilegePermission() throws Exception { |
| testInsertSim(); |
| // Adding a second profile and mark as embedded. |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 1); |
| ContentValues values = new ContentValues(); |
| values.put(SubscriptionManager.IS_EMBEDDED, 1); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); |
| mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); |
| |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| |
| int[] subIdList = new int[] {1}; |
| |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(1); |
| doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); |
| |
| ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, "packageName1"); |
| assertNotEquals(null, groupId); |
| |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| new int[] {2}, groupId, "packageName1"); |
| List<SubscriptionInfo> infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupId, "packageName1", "feature1"); |
| assertEquals(2, infoList.size()); |
| assertEquals(1, infoList.get(0).getSubscriptionId()); |
| assertEquals(2, infoList.get(1).getSubscriptionId()); |
| |
| mSubscriptionControllerUT.removeSubscriptionsFromGroup( |
| new int[] {2}, groupId, "packageName1"); |
| infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupId, "packageName1", "feature1"); |
| assertEquals(1, infoList.size()); |
| assertEquals(1, infoList.get(0).getSubscriptionId()); |
| |
| // Make sub 1 inactive. |
| mSubscriptionControllerUT.clearSubInfoRecord(0); |
| |
| try { |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| new int[] {2}, groupId, "packageName2"); |
| fail("addSubscriptionsIntoGroup should fail with wrong callingPackage name"); |
| } catch (SecurityException e) { |
| // Expected result. |
| } |
| |
| // Adding and removing subscription should still work for packageName1, as it's the group |
| // owner who created the group earlier.. |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| new int[] {2}, groupId, "packageName1"); |
| infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupId, "packageName1", "feature1"); |
| assertEquals(2, infoList.size()); |
| assertEquals(1, infoList.get(0).getSubscriptionId()); |
| assertEquals(2, infoList.get(1).getSubscriptionId()); |
| |
| mSubscriptionControllerUT.removeSubscriptionsFromGroup( |
| new int[] {2}, groupId, "packageName1"); |
| infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupId, "packageName1", "feature1"); |
| assertEquals(1, infoList.size()); |
| assertEquals(1, infoList.get(0).getSubscriptionId()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testDisabledSubscriptionGroup() throws Exception { |
| registerMockTelephonyRegistry(); |
| |
| testInsertSim(); |
| // Adding a second profile and mark as embedded. |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 0); |
| |
| ContentValues values = new ContentValues(); |
| values.put(SubscriptionManager.IS_EMBEDDED, 1); |
| values.put(SubscriptionManager.IS_OPPORTUNISTIC, 1); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); |
| mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); |
| mSubscriptionControllerUT.notifySubscriptionInfoChanged(); |
| |
| verify(mTelephonyRegistryManager, times(1)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| |
| // Set sub 1 and 2 into same group. |
| int[] subIdList = new int[] {1, 2}; |
| ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| assertNotEquals(null, groupId); |
| |
| mSubscriptionControllerUT.notifySubscriptionInfoChanged(); |
| verify(mTelephonyRegistryManager, times(2)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| List<SubscriptionInfo> opptSubList = mSubscriptionControllerUT |
| .getOpportunisticSubscriptions(mCallingPackage, mCallingFeature); |
| assertEquals(1, opptSubList.size()); |
| assertEquals(2, opptSubList.get(0).getSubscriptionId()); |
| assertEquals(false, opptSubList.get(0).isGroupDisabled()); |
| |
| // Unplug SIM 1. This should trigger subscription controller disabling sub 2. |
| values = new ContentValues(); |
| values.put(SubscriptionManager.SIM_SLOT_INDEX, -1); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 1, null); |
| mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); |
| mSubscriptionControllerUT.notifySubscriptionInfoChanged(); |
| |
| verify(mTelephonyRegistryManager, times(3)) |
| .notifyOpportunisticSubscriptionInfoChanged(); |
| opptSubList = mSubscriptionControllerUT.getOpportunisticSubscriptions(mCallingPackage, |
| mCallingFeature); |
| assertEquals(1, opptSubList.size()); |
| assertEquals(2, opptSubList.get(0).getSubscriptionId()); |
| assertEquals(true, opptSubList.get(0).isGroupDisabled()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testSetSubscriptionGroup() throws Exception { |
| testInsertSim(); |
| // Adding a second profile and mark as embedded. |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 1); |
| ContentValues values = new ContentValues(); |
| values.put(SubscriptionManager.IS_EMBEDDED, 1); |
| mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, |
| SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); |
| mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); |
| |
| assertTrue(mSubscriptionControllerUT.isActiveSubId(1)); |
| assertTrue(mSubscriptionControllerUT.isActiveSubId(2)); |
| assertTrue(TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, 1, |
| mContext.getOpPackageName(), mContext.getAttributionTag(), |
| "getSubscriptionsInGroup")); |
| |
| int[] subIdList = new int[] {1}; |
| ParcelUuid groupUuid = mSubscriptionControllerUT.createSubscriptionGroup( |
| subIdList, mContext.getOpPackageName()); |
| assertNotEquals(null, groupUuid); |
| |
| // Sub 1 and sub 2 should be in same group. |
| List<SubscriptionInfo> infoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupUuid, mContext.getOpPackageName(), mContext.getAttributionTag()); |
| assertNotEquals(null, infoList); |
| assertEquals(1, infoList.size()); |
| assertEquals(1, infoList.get(0).getSubscriptionId()); |
| |
| subIdList = new int[] {2}; |
| |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| subIdList, groupUuid, mContext.getOpPackageName()); |
| infoList = mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, |
| mContext.getOpPackageName(), mContext.getAttributionTag()); |
| assertEquals(2, infoList.size()); |
| assertEquals(2, infoList.get(1).getSubscriptionId()); |
| |
| // Remove group of sub 1. |
| subIdList = new int[] {1}; |
| mSubscriptionControllerUT.removeSubscriptionsFromGroup( |
| subIdList, groupUuid, mContext.getOpPackageName()); |
| infoList = mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, |
| mContext.getOpPackageName(), mContext.getAttributionTag()); |
| assertEquals(1, infoList.size()); |
| assertEquals(2, infoList.get(0).getSubscriptionId()); |
| |
| // Adding sub 1 into a non-existing UUID, which should be granted. |
| groupUuid = new ParcelUuid(UUID.randomUUID()); |
| mSubscriptionControllerUT.addSubscriptionsIntoGroup( |
| subIdList, groupUuid, mContext.getOpPackageName()); |
| infoList = mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, |
| mContext.getOpPackageName(), mContext.getAttributionTag()); |
| assertEquals(1, infoList.size()); |
| assertEquals(1, infoList.get(0).getSubscriptionId()); |
| } |
| |
| private void registerMockTelephonyRegistry() { |
| mServiceManagerMockedServices.put("telephony.registry", mTelephonyRegisteryMock); |
| doReturn(mTelephonyRegisteryMock).when(mTelephonyRegisteryMock) |
| .queryLocalInterface(anyString()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testEnableDisableSubscriptionSanity() throws Exception { |
| testInsertSim(); |
| |
| // Non existing subId. |
| assertFalse(mSubscriptionControllerUT.isSubscriptionEnabled(2)); |
| |
| // Test invalid arguments. |
| try { |
| assertFalse(mSubscriptionControllerUT.isSubscriptionEnabled(-1)); |
| fail("Should throw IllegalArgumentException with invalid subId."); |
| } catch (IllegalArgumentException exception) { |
| // Expected. |
| } |
| |
| try { |
| mSubscriptionControllerUT.getEnabledSubscriptionId(3); |
| fail("Should throw IllegalArgumentException with invalid subId."); |
| } catch (IllegalArgumentException exception) { |
| // Expected. |
| } |
| } |
| |
| @Test |
| @SmallTest |
| public void testGetActiveSubIdList() throws Exception { |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("123", 1); // sub 1 |
| mSubscriptionControllerUT.addSubInfoRecord("456", 0); // sub 2 |
| |
| int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false); |
| // Make sure the return sub ids are sorted by slot index |
| assertTrue("active sub ids = " + subIds, Arrays.equals(subIds, new int[]{2, 1})); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoWithNoPermissions() throws Exception { |
| // If the calling package does not have the READ_PHONE_STATE permission or carrier |
| // privileges then getActiveSubscriptionInfo should throw a SecurityException; |
| testInsertSim(); |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| int subId = getFirstSubId(); |
| |
| try { |
| mSubscriptionControllerUT.getActiveSubscriptionInfo(subId, mCallingPackage, |
| mCallingFeature); |
| fail("getActiveSubscriptionInfo should fail when invoked with no permissions"); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoWithReadPhoneState() throws Exception { |
| // If the calling package only has the READ_PHONE_STATE permission then |
| // getActiveSubscriptionInfo should still return a result but the ICC ID should not be |
| // available via getIccId or getCardString. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| setIdentifierAccess(false); |
| int subId = getFirstSubId(); |
| |
| SubscriptionInfo subscriptionInfo = mSubscriptionControllerUT.getActiveSubscriptionInfo( |
| subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertEquals(UNAVAILABLE_ICCID, subscriptionInfo.getIccId()); |
| assertEquals(UNAVAILABLE_ICCID, subscriptionInfo.getCardString()); |
| assertEquals(UNAVAILABLE_NUMBER, subscriptionInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionWithReadPhoneNumbers() throws Exception { |
| // If the calling package has the READ_PHONE_NUMBERS permission the number should be |
| // available in the SubscriptionInfo. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS); |
| int subId = getFirstSubId(); |
| |
| SubscriptionInfo subscriptionInfo = mSubscriptionControllerUT.getActiveSubscriptionInfo( |
| subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertEquals(DISPLAY_NUMBER, subscriptionInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoWithCarrierPrivileges() throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo. |
| testInsertSim(); |
| setupIdentifierCarrierPrivilegesTest(); |
| int subId = getFirstSubId(); |
| |
| SubscriptionInfo subscriptionInfo = mSubscriptionControllerUT.getActiveSubscriptionInfo( |
| subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertTrue(subscriptionInfo.getIccId().length() > 0); |
| assertTrue(subscriptionInfo.getCardString().length() > 0); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionWithPrivilegedPermission() throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo. |
| testInsertSim(); |
| int subId = getFirstSubId(); |
| |
| SubscriptionInfo subscriptionInfo = mSubscriptionControllerUT.getActiveSubscriptionInfo( |
| subId, mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertTrue(subscriptionInfo.getIccId().length() > 0); |
| assertTrue(subscriptionInfo.getCardString().length() > 0); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoForSimSlotIndexWithNoPermission() throws Exception { |
| // If the calling package does not have the READ_PHONE_STATE permission or carrier |
| // privileges then getActiveSubscriptionInfoForSimSlotIndex should throw a |
| // SecurityException. |
| testInsertSim(); |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| |
| try { |
| mSubscriptionControllerUT.getActiveSubscriptionInfoForSimSlotIndex(0, mCallingPackage, |
| mCallingFeature); |
| fail("getActiveSubscriptionInfoForSimSlotIndex should fail when invoked with no " |
| + "permissions"); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoForSimSlotIndexWithReadPhoneState() throws Exception { |
| // If the calling package only has the READ_PHONE_STATE permission then |
| // getActiveSubscriptionInfoForSimlSlotIndex should still return the SubscriptionInfo but |
| // the ICC ID should not be available via getIccId or getCardString. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| setIdentifierAccess(false); |
| |
| SubscriptionInfo subscriptionInfo = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoForSimSlotIndex(0, |
| mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertEquals(UNAVAILABLE_ICCID, subscriptionInfo.getIccId()); |
| assertEquals(UNAVAILABLE_ICCID, subscriptionInfo.getCardString()); |
| assertEquals(UNAVAILABLE_NUMBER, subscriptionInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoForSimSlotIndexWithReadPhoneNumbers() |
| throws Exception { |
| // If the calling package has the READ_PHONE_NUMBERS permission the number should be |
| // available in the SubscriptionInfo. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS); |
| |
| SubscriptionInfo subscriptionInfo = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoForSimSlotIndex(0, |
| mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertEquals(DISPLAY_NUMBER, subscriptionInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoForSimSlotIndexWithCarrierPrivileges() |
| throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo. |
| testInsertSim(); |
| setupIdentifierCarrierPrivilegesTest(); |
| |
| SubscriptionInfo subscriptionInfo = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoForSimSlotIndex(0, |
| mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertTrue(subscriptionInfo.getIccId().length() > 0); |
| assertTrue(subscriptionInfo.getCardString().length() > 0); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoForSimSlotIndexWithPrivilegedPermission() |
| throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo. |
| testInsertSim(); |
| |
| SubscriptionInfo subscriptionInfo = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoForSimSlotIndex(0, |
| mCallingPackage, mCallingFeature); |
| |
| assertNotNull(subscriptionInfo); |
| assertTrue(subscriptionInfo.getIccId().length() > 0); |
| assertTrue(subscriptionInfo.getCardString().length() > 0); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithNoPermission() throws Exception { |
| // If the calling package does not have the READ_PHONE_STATE permission or carrier |
| // privileges then getActiveSubscriptionInfoList should return a list with 0 elements. |
| testInsertSim(); |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertNotNull(subInfoList); |
| assertTrue(subInfoList.size() == 0); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithReadPhoneState() throws Exception { |
| // If the calling package only has the READ_PHONE_STATE permission then |
| // getActiveSubscriptionInfoList should still return the list of SubscriptionInfo objects |
| // but the ICC ID should not be available via getIccId or getCardString. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| setIdentifierAccess(false); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| for (SubscriptionInfo info : subInfoList) { |
| assertEquals(UNAVAILABLE_ICCID, info.getIccId()); |
| assertEquals(UNAVAILABLE_ICCID, info.getCardString()); |
| assertEquals(UNAVAILABLE_NUMBER, info.getNumber()); |
| } |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithReadPhoneNumbers() throws Exception { |
| // If the calling package has the READ_PHONE_NUMBERS permission the number should be |
| // available in the SubscriptionInfo. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| SubscriptionInfo subInfo = subInfoList.get(0); |
| assertEquals(DISPLAY_NUMBER, subInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithCarrierPrivileges() throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo objects in the List. |
| testInsertSim(); |
| setupIdentifierCarrierPrivilegesTest(); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| for (SubscriptionInfo info : subInfoList) { |
| assertTrue(info.getIccId().length() > 0); |
| assertTrue(info.getCardString().length() > 0); |
| } |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithCarrierPrivilegesOnOneSubId() |
| throws Exception { |
| // If an app does not have the READ_PHONE_STATE permission but has carrier privileges on one |
| // out of multiple sub IDs then the SubscriptionInfo for that subId should be returned with |
| // the ICC ID and phone number. |
| testInsertSim(); |
| doReturn(2).when(mTelephonyManager).getPhoneCount(); |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 1); |
| int firstSubId = getFirstSubId(); |
| int secondSubId = getSubIdAtIndex(1); |
| mSubscriptionControllerUT.setDisplayNumber(DISPLAY_NUMBER, secondSubId); |
| setupIdentifierCarrierPrivilegesTest(); |
| mContextFixture.removeCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| setCarrierPrivilegesForSubId(false, firstSubId); |
| setCarrierPrivilegesForSubId(true, secondSubId); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertEquals(1, subInfoList.size()); |
| SubscriptionInfo subInfo = subInfoList.get(0); |
| assertEquals("test2", subInfo.getIccId()); |
| assertEquals(DISPLAY_NUMBER, subInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListCheckOrder() |
| throws Exception { |
| // If an app does not have the READ_PHONE_STATE permission but has carrier privileges on one |
| // out of multiple sub IDs then the SubscriptionInfo for that subId should be returned with |
| // the ICC ID and phone number. |
| testInsertSim(); |
| doReturn(2).when(mTelephonyManager).getPhoneCount(); |
| mSubscriptionControllerUT.addSubInfoRecord("test2", 1); |
| int firstSubId = getFirstSubId(); |
| int secondSubId = getSubIdAtIndex(1); |
| setupIdentifierCarrierPrivilegesTest(); |
| setCarrierPrivilegesForSubId(false, firstSubId); |
| setCarrierPrivilegesForSubId(true, secondSubId); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertEquals(2, subInfoList.size()); |
| assertTrue(subInfoList.get(0).getSubscriptionId() < subInfoList.get(1).getSubscriptionId()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithIdentifierAccessWithoutNumberAccess() |
| throws Exception { |
| // An app with access to device identifiers may not have access to the device phone number |
| // (ie an app that passes the device / profile owner check or an app that has been granted |
| // the device identifiers appop); this test verifies that an app with identifier access |
| // can read the ICC ID but does not receive the phone number. |
| testInsertSim(); |
| setupReadPhoneNumbersTest(); |
| setIdentifierAccess(true); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertEquals(1, subInfoList.size()); |
| SubscriptionInfo subInfo = subInfoList.get(0); |
| assertEquals("test", subInfo.getIccId()); |
| assertEquals(UNAVAILABLE_NUMBER, subInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetActiveSubscriptionInfoListWithPrivilegedPermission() throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo objects in the List. |
| testInsertSim(); |
| |
| List<SubscriptionInfo> subInfoList = |
| mSubscriptionControllerUT.getActiveSubscriptionInfoList(mCallingPackage, |
| mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| for (SubscriptionInfo info : subInfoList) { |
| assertTrue(info.getIccId().length() > 0); |
| assertTrue(info.getCardString().length() > 0); |
| } |
| } |
| |
| @Test |
| public void testGetSubscriptionsInGroupWithNoPermission() throws Exception { |
| // If the calling package does not have the READ_PHONE_STATE permission or carrier |
| // privileges then getSubscriptionsInGroup should throw a SecurityException when the |
| // READ_PHONE_STATE permission check is performed. |
| ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest(); |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| |
| try { |
| mSubscriptionControllerUT.getSubscriptionsInGroup(groupUuid, mCallingPackage, |
| mCallingFeature); |
| fail("getSubscriptionsInGroup should fail when invoked with no permissions"); |
| } catch (SecurityException expected) { |
| } |
| } |
| |
| @Test |
| public void testGetSubscriptionsInGroupWithReadPhoneState() throws Exception { |
| // If the calling package only has the READ_PHONE_STATE permission then |
| // getSubscriptionsInGroup should still return the list of SubscriptionInfo objects |
| // but the ICC ID should not be available via getIccId or getCardString. |
| ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest(); |
| setupReadPhoneNumbersTest(); |
| setIdentifierAccess(false); |
| |
| List<SubscriptionInfo> subInfoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupUuid, mCallingPackage, mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| for (SubscriptionInfo info : subInfoList) { |
| assertEquals(UNAVAILABLE_ICCID, info.getIccId()); |
| assertEquals(UNAVAILABLE_ICCID, info.getCardString()); |
| assertEquals(UNAVAILABLE_NUMBER, info.getNumber()); |
| } |
| } |
| |
| @Test |
| public void testGetSubscriptionInGroupWithReadPhoneNumbers() throws Exception { |
| // If the calling package has the READ_PHONE_NUMBERS permission the number should be |
| // available in the SubscriptionInfo. |
| ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest(); |
| setupReadPhoneNumbersTest(); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS); |
| |
| List<SubscriptionInfo> subInfoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupUuid, mCallingPackage, mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| SubscriptionInfo subInfo = subInfoList.get(0); |
| assertEquals(DISPLAY_NUMBER, subInfo.getNumber()); |
| } |
| |
| @Test |
| public void testGetSubscriptionsInGroupWithCarrierPrivileges() throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo objects in the List. |
| ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest(); |
| setupIdentifierCarrierPrivilegesTest(); |
| |
| List<SubscriptionInfo> subInfoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupUuid, mCallingPackage, mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| for (SubscriptionInfo info : subInfoList) { |
| assertTrue(info.getIccId().length() > 0); |
| assertTrue(info.getCardString().length() > 0); |
| } |
| } |
| |
| @Test |
| public void testGetSubscriptionsInGroupWithPrivilegedPermission() throws Exception { |
| // If the calling package has the READ_PRIVILEGED_PHONE_STATE permission or carrier |
| // privileges the ICC ID should be available in the SubscriptionInfo objects in the List. |
| ParcelUuid groupUuid = setupGetSubscriptionsInGroupTest(); |
| |
| List<SubscriptionInfo> subInfoList = mSubscriptionControllerUT.getSubscriptionsInGroup( |
| groupUuid, mCallingPackage, mCallingFeature); |
| |
| assertTrue(subInfoList.size() > 0); |
| for (SubscriptionInfo info : subInfoList) { |
| assertTrue(info.getIccId().length() > 0); |
| assertTrue(info.getCardString().length() > 0); |
| } |
| } |
| |
| private ParcelUuid setupGetSubscriptionsInGroupTest() throws Exception { |
| testInsertSim(); |
| int[] subIdList = new int[]{getFirstSubId()}; |
| ParcelUuid groupUuid = mSubscriptionControllerUT.createSubscriptionGroup(subIdList, |
| mCallingPackage); |
| assertNotNull(groupUuid); |
| return groupUuid; |
| } |
| |
| private void setupReadPhoneNumbersTest() throws Exception { |
| mSubscriptionControllerUT.setDisplayNumber(DISPLAY_NUMBER, getFirstSubId()); |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| setupMocksForTelephonyPermissions(Build.VERSION_CODES.R); |
| doReturn(AppOpsManager.MODE_DEFAULT).when(mAppOpsManager).noteOp( |
| eq(AppOpsManager.OPSTR_WRITE_SMS), anyInt(), anyString(), |
| nullable(String.class), nullable(String.class)); |
| } |
| |
| private void setupIdentifierCarrierPrivilegesTest() throws Exception { |
| mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); |
| mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE); |
| setupMocksForTelephonyPermissions(); |
| setIdentifierAccess(false); |
| setCarrierPrivileges(true); |
| } |
| |
| private int getFirstSubId() throws Exception { |
| return getSubIdAtIndex(0); |
| } |
| |
| private int getSubIdAtIndex(int index) throws Exception { |
| int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibileOnly*/false); |
| assertTrue(subIds != null && subIds.length > index); |
| return subIds[index]; |
| } |
| |
| @Test |
| public void testGetEnabledSubscriptionIdSingleSIM() { |
| // A single SIM device may have logical slot 0 mapped to physical slot 1 |
| // (i.e. logical slot -1 mapped to physical slot 0) |
| UiccSlotInfo slot0 = getFakeUiccSlotInfo(false, -1); |
| UiccSlotInfo slot1 = getFakeUiccSlotInfo(true, 0); |
| UiccSlotInfo [] uiccSlotInfos = {slot0, slot1}; |
| UiccSlot [] uiccSlots = {mUiccSlot, mUiccSlot}; |
| |
| doReturn(uiccSlotInfos).when(mTelephonyManager).getUiccSlotsInfo(); |
| doReturn(uiccSlots).when(mUiccController).getUiccSlots(); |
| assertEquals(2, UiccController.getInstance().getUiccSlots().length); |
| |
| ContentResolver resolver = mContext.getContentResolver(); |
| // logical 0 should find physical 1, has settings enabled subscription 0 |
| Settings.Global.putInt(resolver, Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT + 1, 0); |
| |
| int enabledSubscription = mSubscriptionControllerUT.getEnabledSubscriptionId(0); |
| assertEquals(0, enabledSubscription); |
| } |
| |
| @Test |
| public void testGetEnabledSubscriptionIdDualSIM() { |
| doReturn(SINGLE_SIM).when(mTelephonyManager).getSimCount(); |
| doReturn(SINGLE_SIM).when(mTelephonyManager).getPhoneCount(); |
| doReturn(SINGLE_SIM).when(mTelephonyManager).getActiveModemCount(); |
| // A dual SIM device may have logical slot 0 mapped to physical slot 0 |
| // (i.e. logical slot 1 mapped to physical slot 1) |
| UiccSlotInfo slot0 = getFakeUiccSlotInfo(true, 0); |
| UiccSlotInfo slot1 = getFakeUiccSlotInfo(true, 1); |
| UiccSlotInfo [] uiccSlotInfos = {slot0, slot1}; |
| UiccSlot [] uiccSlots = {mUiccSlot, mUiccSlot}; |
| |
| doReturn(2).when(mTelephonyManager).getPhoneCount(); |
| doReturn(2).when(mTelephonyManager).getActiveModemCount(); |
| doReturn(uiccSlotInfos).when(mTelephonyManager).getUiccSlotsInfo(); |
| doReturn(uiccSlots).when(mUiccController).getUiccSlots(); |
| assertEquals(2, UiccController.getInstance().getUiccSlots().length); |
| |
| ContentResolver resolver = mContext.getContentResolver(); |
| // logical 0 should find physical 0, has settings enabled subscription 0 |
| Settings.Global.putInt(resolver, Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT + 0, 0); |
| Settings.Global.putInt(resolver, Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT + 1, 1); |
| |
| int enabledSubscription = mSubscriptionControllerUT.getEnabledSubscriptionId(0); |
| int secondEabledSubscription = mSubscriptionControllerUT.getEnabledSubscriptionId(1); |
| assertEquals(0, enabledSubscription); |
| assertEquals(1, secondEabledSubscription); |
| } |
| |
| |
| private UiccSlotInfo getFakeUiccSlotInfo(boolean active, int logicalSlotIndex) { |
| return getFakeUiccSlotInfo(active, logicalSlotIndex, "fake card Id"); |
| } |
| |
| private UiccSlotInfo getFakeUiccSlotInfo(boolean active, int logicalSlotIndex, String cardId) { |
| return new UiccSlotInfo(active, false, cardId, |
| UiccSlotInfo.CARD_STATE_INFO_PRESENT, logicalSlotIndex, true, true); |
| } |
| |
| @Test |
| @SmallTest |
| public void testNameSourcePriority() throws Exception { |
| assertTrue(mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_USER_INPUT) |
| > mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_CARRIER)); |
| |
| assertTrue(mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_CARRIER) |
| > mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_SIM_SPN)); |
| |
| assertTrue(mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_SIM_SPN) |
| > mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_SIM_PNN)); |
| |
| assertTrue(mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_SIM_PNN) |
| > mSubscriptionControllerUT.getNameSourcePriority( |
| SubscriptionManager.NAME_SOURCE_CARRIER_ID)); |
| } |
| |
| @Test |
| @SmallTest |
| public void testGetAvailableSubscriptionList() throws Exception { |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("123", 1); // sub 1 |
| mSubscriptionControllerUT.addSubInfoRecord("456", 0); // sub 2 |
| |
| List<SubscriptionInfo> infoList = mSubscriptionControllerUT |
| .getAvailableSubscriptionInfoList(mCallingPackage, mCallingFeature); |
| assertEquals(2, infoList.size()); |
| assertEquals("456", infoList.get(0).getIccId()); |
| assertEquals("123", infoList.get(1).getIccId()); |
| |
| // Remove "123" from active sim list but have it inserted. |
| UiccSlot[] uiccSlots = {mUiccSlot}; |
| IccCardStatus.CardState cardState = CARDSTATE_PRESENT; |
| doReturn(uiccSlots).when(mUiccController).getUiccSlots(); |
| doReturn(cardState).when(mUiccSlot).getCardState(); |
| doReturn("123").when(mUiccSlot).getIccId(); |
| mSubscriptionControllerUT.clearSubInfoRecord(1); |
| |
| // Active sub list should return 1 now. |
| infoList = mSubscriptionControllerUT |
| .getActiveSubscriptionInfoList(mCallingPackage, mCallingFeature); |
| assertEquals(1, infoList.size()); |
| assertEquals("456", infoList.get(0).getIccId()); |
| |
| // Available sub list should still return two. |
| infoList = mSubscriptionControllerUT |
| .getAvailableSubscriptionInfoList(mCallingPackage, mCallingFeature); |
| assertEquals(2, infoList.size()); |
| assertEquals("123", infoList.get(0).getIccId()); |
| assertEquals("456", infoList.get(1).getIccId()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testGetAvailableSubscriptionList_withTrailingF() throws Exception { |
| // TODO b/123300875 slot index 1 is not expected to be valid |
| mSubscriptionControllerUT.addSubInfoRecord("123", 1); // sub 1 |
| mSubscriptionControllerUT.addSubInfoRecord("456", 0); // sub 2 |
| |
| // Remove "123" from active sim list but have it inserted. |
| UiccSlot[] uiccSlots = {mUiccSlot}; |
| IccCardStatus.CardState cardState = CARDSTATE_PRESENT; |
| doReturn(uiccSlots).when(mUiccController).getUiccSlots(); |
| doReturn(cardState).when(mUiccSlot).getCardState(); |
| // IccId ends with a 'F' which should be ignored and taking into account. |
| doReturn("123F").when(mUiccSlot).getIccId(); |
| mSubscriptionControllerUT.clearSubInfoRecord(1); |
| |
| // Active sub list should return 1 now. |
| List<SubscriptionInfo> infoList = mSubscriptionControllerUT |
| .getActiveSubscriptionInfoList(mCallingPackage, mCallingFeature); |
| assertEquals(1, infoList.size()); |
| assertEquals("456", infoList.get(0).getIccId()); |
| |
| // Available sub list should still return two. |
| infoList = mSubscriptionControllerUT |
| .getAvailableSubscriptionInfoList(mCallingPackage, mCallingFeature); |
| assertEquals(2, infoList.size()); |
| assertEquals("123", infoList.get(0).getIccId()); |
| assertEquals("456", infoList.get(1).getIccId()); |
| } |
| |
| @Test |
| @SmallTest |
| public void testSetPreferredDataSubscriptionId_phoneSwitcherNotInitialized() throws Exception { |
| replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, null); |
| |
| mSubscriptionControllerUT.setPreferredDataSubscriptionId(1, true, mSetOpptDataCallback); |
| verify(mSetOpptDataCallback).onComplete(SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION); |
| } |
| |
| @Test |
| @SmallTest |
| public void testGetPreferredDataSubscriptionId_phoneSwitcherNotInitialized() throws Exception { |
| replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, null); |
| |
| assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, |
| mSubscriptionControllerUT.getPreferredDataSubscriptionId()); |
| } |
| |
| @Test |
| public void testSetSubscriptionEnabled_disableActivePsim_cardIdWithTrailingF() { |
| String iccId = "123F"; |
| mSubscriptionControllerUT.addSubInfoRecord(iccId, 0); |
| mSubscriptionControllerUT.registerForUiccAppsEnabled(mHandler, 0, null, false); |
| UiccSlotInfo slot = getFakeUiccSlotInfo(true, 0, iccId + "FF"); |
| UiccSlotInfo[] uiccSlotInfos = {slot}; |
| doReturn(uiccSlotInfos).when(mTelephonyManager).getUiccSlotsInfo(); |
| |
| mSubscriptionControllerUT.setSubscriptionEnabled(false, 1); |
| verify(mHandler).sendMessageAtTime(any(), anyLong()); |
| assertFalse(mSubscriptionControllerUT.getActiveSubscriptionInfo( |
| 1, mContext.getOpPackageName(), null).areUiccApplicationsEnabled()); |
| } |
| } |