blob: 4d10b0a71f74451f06a240e5df14269f60668fb6 [file] [log] [blame]
/*
* 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());
}
}