1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED; 20 import static android.telephony.TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyBoolean; 25 import static org.mockito.ArgumentMatchers.anyInt; 26 import static org.mockito.ArgumentMatchers.anyLong; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.clearInvocations; 29 import static org.mockito.Mockito.doReturn; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.times; 32 import static org.mockito.Mockito.verify; 33 34 import android.content.Intent; 35 import android.os.AsyncResult; 36 import android.os.Handler; 37 import android.os.Message; 38 import android.telephony.PhoneCapability; 39 import android.test.suitebuilder.annotation.SmallTest; 40 import android.testing.AndroidTestingRunner; 41 import android.testing.TestableLooper; 42 43 import org.junit.After; 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.ArgumentCaptor; 48 import org.mockito.Mock; 49 50 @RunWith(AndroidTestingRunner.class) 51 @TestableLooper.RunWithLooper 52 public class PhoneConfigurationManagerTest extends TelephonyTest { 53 @Mock 54 Handler mHandler; 55 @Mock 56 CommandsInterface mMockCi0; 57 @Mock 58 CommandsInterface mMockCi1; 59 @Mock 60 private Phone mPhone1; // mPhone as phone 0 is already defined in TelephonyTest. 61 @Mock 62 PhoneConfigurationManager.MockableInterface mMi; 63 64 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 1; 65 PhoneConfigurationManager mPcm; 66 67 @Before setUp()68 public void setUp() throws Exception { 69 super.setUp(getClass().getSimpleName()); 70 mPhone.mCi = mMockCi0; 71 mCT.mCi = mMockCi0; 72 mPhone1.mCi = mMockCi1; 73 } 74 75 @After tearDown()76 public void tearDown() throws Exception { 77 // Restore system properties. 78 super.tearDown(); 79 } 80 setRebootRequiredForConfigSwitch(boolean rebootRequired)81 private void setRebootRequiredForConfigSwitch(boolean rebootRequired) { 82 doReturn(rebootRequired).when(mMi).isRebootRequiredForModemConfigChange(); 83 } 84 init(int numOfSim)85 private void init(int numOfSim) throws Exception { 86 doReturn(numOfSim).when(mTelephonyManager).getActiveModemCount(); 87 replaceInstance(PhoneConfigurationManager.class, "sInstance", null, null); 88 mPcm = PhoneConfigurationManager.init(mContext); 89 replaceInstance(PhoneConfigurationManager.class, "mMi", mPcm, mMi); 90 processAllMessages(); 91 } 92 93 /** 94 * Test that a single phone case results in our phone being active and the RIL called 95 */ 96 @Test 97 @SmallTest testGetPhoneCount()98 public void testGetPhoneCount() throws Exception { 99 init(1); 100 doReturn(1).when(mTelephonyManager).getActiveModemCount(); 101 assertEquals(1, mPcm.getPhoneCount()); 102 doReturn(2).when(mTelephonyManager).getActiveModemCount(); 103 assertEquals(2, mPcm.getPhoneCount()); 104 } 105 106 @Test 107 @SmallTest testEnablePhone()108 public void testEnablePhone() throws Exception { 109 init(1); 110 // Phone is null. No crash. 111 mPcm.enablePhone(null, true, null); 112 113 Message message = new Message(); 114 mPcm.enablePhone(mPhone, false, message); 115 verify(mMockCi0).enableModem(eq(false), eq(message)); 116 } 117 118 @Test 119 @SmallTest testGetDsdsCapability()120 public void testGetDsdsCapability() throws Exception { 121 init(1); 122 assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability()); 123 124 ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); 125 verify(mMockRadioConfig).getPhoneCapability(captor.capture()); 126 Message msg = captor.getValue(); 127 AsyncResult.forMessage(msg, PhoneCapability.DEFAULT_DSDS_CAPABILITY, null); 128 msg.sendToTarget(); 129 processAllMessages(); 130 131 // Not static capability should indicate DSDS capable. 132 assertEquals(PhoneCapability.DEFAULT_DSDS_CAPABILITY, mPcm.getStaticPhoneCapability()); 133 } 134 135 @Test 136 @SmallTest testSwitchMultiSimConfig_notDsdsCapable_shouldFail()137 public void testSwitchMultiSimConfig_notDsdsCapable_shouldFail() throws Exception { 138 init(1); 139 assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability()); 140 141 // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported. 142 mPcm.switchMultiSimConfig(2); 143 verify(mMockRadioConfig, never()).setModemsConfig(anyInt(), any()); 144 } 145 146 @Test 147 @SmallTest testSwitchMultiSimConfig_dsdsCapable_noRebootRequired()148 public void testSwitchMultiSimConfig_dsdsCapable_noRebootRequired() throws Exception { 149 init(1); 150 verify(mMockCi0, times(1)).registerForAvailable(any(), anyInt(), any()); 151 152 // Register for multi SIM config change. 153 mPcm.registerForMultiSimConfigChange(mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 154 verify(mHandler, never()).sendMessageAtTime(any(), anyLong()); 155 156 // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported. 157 mPcm.switchMultiSimConfig(2); 158 verify(mMockRadioConfig, never()).setModemsConfig(anyInt(), any()); 159 160 // Send static capability back to indicate DSDS is supported. 161 clearInvocations(mMockRadioConfig); 162 testGetDsdsCapability(); 163 // testGetDsdsCapability leads to another call to registerForAvailable() 164 verify(mMockCi0, times(2)).registerForAvailable(any(), anyInt(), any()); 165 166 // Try to switch to DSDS. 167 setRebootRequiredForConfigSwitch(false); 168 mPhones = new Phone[]{mPhone, mPhone1}; 169 replaceInstance(PhoneFactory.class, "sPhones", null, mPhones); 170 mPcm.switchMultiSimConfig(2); 171 ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); 172 verify(mMockRadioConfig).setModemsConfig(eq(2), captor.capture()); 173 174 // Send message back to indicate switch success. 175 Message message = captor.getValue(); 176 AsyncResult.forMessage(message, null, null); 177 message.sendToTarget(); 178 processAllMessages(); 179 180 // Verify set system property being called. 181 verify(mMi).setMultiSimProperties(2); 182 verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(2)); 183 184 // Capture and verify registration notification. 185 verify(mHandler).sendMessageAtTime(captor.capture(), anyLong()); 186 message = captor.getValue(); 187 assertEquals(EVENT_MULTI_SIM_CONFIG_CHANGED, message.what); 188 assertEquals(2, ((AsyncResult) message.obj).result); 189 190 // Capture and verify broadcast. 191 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 192 verify(mContext).sendBroadcast(intentCaptor.capture()); 193 Intent intent = intentCaptor.getValue(); 194 assertEquals(ACTION_MULTI_SIM_CONFIG_CHANGED, intent.getAction()); 195 assertEquals(2, intent.getIntExtra( 196 EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 0)); 197 198 // Verify registerForAvailable() and onSlotActiveStatusChange() are called for the second 199 // phone, and not for the first phone (registerForAvailable() was already called twice 200 // earlier so verify that the count is still at 2) 201 verify(mMockCi0, times(2)).registerForAvailable(any(), anyInt(), any()); 202 verify(mMockCi0, never()).onSlotActiveStatusChange(anyBoolean()); 203 verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any()); 204 verify(mMockCi1, times(1)).onSlotActiveStatusChange(anyBoolean()); 205 } 206 207 @Test 208 @SmallTest testSwitchMultiSimConfig_multiSimToSingleSim()209 public void testSwitchMultiSimConfig_multiSimToSingleSim() throws Exception { 210 mPhones = new Phone[]{mPhone, mPhone1}; 211 replaceInstance(PhoneFactory.class, "sPhones", null, mPhones); 212 init(2); 213 verify(mMockCi0, times(1)).registerForAvailable(any(), anyInt(), any()); 214 verify(mMockCi1, times(1)).registerForAvailable(any(), anyInt(), any()); 215 216 // Register for multi SIM config change. 217 mPcm.registerForMultiSimConfigChange(mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 218 verify(mHandler, never()).sendMessageAtTime(any(), anyLong()); 219 220 // Switch to single sim. 221 setRebootRequiredForConfigSwitch(false); 222 mPcm.switchMultiSimConfig(1); 223 ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); 224 verify(mMockRadioConfig).setModemsConfig(eq(1), captor.capture()); 225 226 // Send message back to indicate switch success. 227 Message message = captor.getValue(); 228 AsyncResult.forMessage(message, null, null); 229 message.sendToTarget(); 230 processAllMessages(); 231 232 // Verify set system property being called. 233 verify(mMi).setMultiSimProperties(1); 234 verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(1)); 235 236 // Capture and verify registration notification. 237 verify(mHandler).sendMessageAtTime(captor.capture(), anyLong()); 238 message = captor.getValue(); 239 assertEquals(EVENT_MULTI_SIM_CONFIG_CHANGED, message.what); 240 assertEquals(1, ((AsyncResult) message.obj).result); 241 242 // Capture and verify broadcast. 243 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 244 verify(mContext).sendBroadcast(intentCaptor.capture()); 245 Intent intent = intentCaptor.getValue(); 246 assertEquals(ACTION_MULTI_SIM_CONFIG_CHANGED, intent.getAction()); 247 assertEquals(1, intent.getIntExtra( 248 EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 0)); 249 250 // Verify clearSubInfoRecord() and onSlotActiveStatusChange() are called for second phone, 251 // and not for the first one 252 verify(mSubscriptionController).clearSubInfoRecord(1); 253 verify(mMockCi1).onSlotActiveStatusChange(anyBoolean()); 254 verify(mSubscriptionController, never()).clearSubInfoRecord(0); 255 verify(mMockCi0, never()).onSlotActiveStatusChange(anyBoolean()); 256 257 // Verify onPhoneRemoved() gets called on MultiSimSettingController phone 258 verify(mMultiSimSettingController).onPhoneRemoved(); 259 } 260 } 261