1 /* 2 * Copyright (C) 2016 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 package com.android.internal.telephony.imsphone; 17 18 import android.os.AsyncResult; 19 import android.os.Bundle; 20 import android.os.Handler; 21 import android.os.Looper; 22 import android.os.Message; 23 import android.telephony.DisconnectCause; 24 import android.telephony.PhoneNumberUtils; 25 import android.telephony.ServiceState; 26 import android.test.suitebuilder.annotation.MediumTest; 27 import android.test.suitebuilder.annotation.SmallTest; 28 29 import com.android.ims.ImsCallProfile; 30 import com.android.internal.telephony.Call; 31 import com.android.internal.telephony.Connection; 32 import com.android.internal.telephony.GsmCdmaCall; 33 import com.android.internal.telephony.PhoneConstants; 34 import com.android.internal.telephony.TelephonyTest; 35 36 import org.junit.After; 37 import org.junit.Assert; 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.mockito.Mock; 41 import org.mockito.invocation.InvocationOnMock; 42 import org.mockito.stubbing.Answer; 43 44 import java.lang.reflect.Field; 45 46 import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; 47 import static org.junit.Assert.assertEquals; 48 import static org.junit.Assert.assertFalse; 49 import static org.junit.Assert.assertNull; 50 import static org.junit.Assert.assertTrue; 51 import static org.mockito.Mockito.any; 52 import static org.mockito.Mockito.anyChar; 53 import static org.mockito.Mockito.doAnswer; 54 import static org.mockito.Mockito.doReturn; 55 import static org.mockito.Mockito.eq; 56 import static org.mockito.Mockito.times; 57 import static org.mockito.Mockito.verify; 58 59 public class ImsPhoneConnectionTest extends TelephonyTest { 60 private ImsPhoneConnection mConnectionUT; 61 private Bundle mBundle = new Bundle(); 62 @Mock 63 private ImsPhoneCall mForeGroundCall; 64 @Mock 65 private ImsPhoneCall mBackGroundCall; 66 @Mock 67 private ImsPhoneCall mRingGroundCall; 68 69 @Before 70 public void setUp() throws Exception { 71 super.setUp(getClass().getSimpleName()); 72 replaceInstance(Handler.class, "mLooper", mImsCT, Looper.getMainLooper()); 73 replaceInstance(ImsPhoneCallTracker.class, "mForegroundCall", mImsCT, mForeGroundCall); 74 replaceInstance(ImsPhoneCallTracker.class, "mBackgroundCall", mImsCT, mBackGroundCall); 75 replaceInstance(ImsPhoneCallTracker.class, "mRingingCall", mImsCT, mRingGroundCall); 76 replaceInstance(ImsPhoneCallTracker.class, "mPhone", mImsCT, mImsPhone); 77 78 mImsCallProfile.mCallExtras = mBundle; 79 doReturn(ImsPhoneCall.State.IDLE).when(mForeGroundCall).getState(); 80 } 81 82 @After 83 public void tearDown() throws Exception { 84 super.tearDown(); 85 } 86 87 @Test 88 @SmallTest 89 public void testImsConnectionSanity() { 90 logd("Testing initial state of MT ImsPhoneConnection"); 91 mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false); 92 93 assertEquals(ImsPhoneCall.State.IDLE, mConnectionUT.getState()); 94 assertEquals(PhoneConstants.PRESENTATION_UNKNOWN, mConnectionUT.getNumberPresentation()); 95 assertEquals(PhoneConstants.PRESENTATION_UNKNOWN, mConnectionUT.getCnapNamePresentation()); 96 assertEquals(Connection.PostDialState.NOT_STARTED, mConnectionUT.getPostDialState()); 97 assertEquals(0, mConnectionUT.getDisconnectTime()); 98 assertEquals(0, mConnectionUT.getHoldDurationMillis()); 99 assertNull(mConnectionUT.getOrigDialString()); 100 assertFalse(mConnectionUT.isMultiparty()); 101 assertFalse(mConnectionUT.isConferenceHost()); 102 verify(mForeGroundCall, times(1)).attach((Connection) any(), 103 eq(ImsPhoneCall.State.INCOMING)); 104 105 logd("Testing initial state of MO ImsPhoneConnection"); 106 mConnectionUT = new ImsPhoneConnection(mImsPhone, String.format("+1 (700).555-41NN%c1234", 107 PhoneNumberUtils.PAUSE), mImsCT, mForeGroundCall, false); 108 assertEquals(PhoneConstants.PRESENTATION_ALLOWED, mConnectionUT.getNumberPresentation()); 109 assertEquals(PhoneConstants.PRESENTATION_ALLOWED, mConnectionUT.getCnapNamePresentation()); 110 assertEquals("+1 (700).555-41NN,1234", mConnectionUT.getOrigDialString()); 111 verify(mForeGroundCall, times(1)).attachFake((Connection) any(), 112 eq(ImsPhoneCall.State.DIALING)); 113 } 114 115 @Test 116 @SmallTest 117 public void testImsUpdateStateForeGround() { 118 // MO Foreground Connection dailing -> active 119 mConnectionUT = new ImsPhoneConnection(mImsPhone, "+1 (700).555-41NN1234", mImsCT, 120 mForeGroundCall, false); 121 // initially in dialing state 122 doReturn(Call.State.DIALING).when(mForeGroundCall).getState(); 123 assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 124 // for Ringing/Dialing upadte postDialState 125 assertEquals(Connection.PostDialState.COMPLETE, mConnectionUT.getPostDialState()); 126 verify(mForeGroundCall, times(1)).update(eq(mConnectionUT), eq(mImsCall), 127 eq(Call.State.ACTIVE)); 128 } 129 130 @Test 131 @SmallTest 132 public void testImsUpdateStateBackGround() { 133 // MT background Connection dialing -> active 134 mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mBackGroundCall, false); 135 doReturn(Call.State.HOLDING).when(mBackGroundCall).getState(); 136 assertFalse(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 137 verify(mBackGroundCall, times(1)).detach(eq(mConnectionUT)); 138 verify(mForeGroundCall, times(1)).attach(eq(mConnectionUT)); 139 verify(mForeGroundCall, times(1)).update(eq(mConnectionUT), eq(mImsCall), 140 eq(Call.State.ACTIVE)); 141 assertEquals(Connection.PostDialState.NOT_STARTED, mConnectionUT.getPostDialState()); 142 } 143 144 @Test 145 @SmallTest 146 public void testImsUpdateStatePendingHold() { 147 mConnectionUT = new ImsPhoneConnection(mImsPhone, "+1 (700).555-41NN1234", mImsCT, 148 mForeGroundCall, false); 149 doReturn(true).when(mImsCall).isPendingHold(); 150 assertFalse(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 151 verify(mForeGroundCall, times(0)).update(eq(mConnectionUT), eq(mImsCall), 152 eq(Call.State.ACTIVE)); 153 assertEquals(Connection.PostDialState.NOT_STARTED, mConnectionUT.getPostDialState()); 154 } 155 156 @Test 157 @SmallTest 158 public void testUpdateAddressDisplay() { 159 mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false); 160 assertEquals(PhoneConstants.PRESENTATION_UNKNOWN, mConnectionUT.getNumberPresentation()); 161 assertEquals(PhoneConstants.PRESENTATION_UNKNOWN, mConnectionUT.getCnapNamePresentation()); 162 doReturn(ImsCallProfile.OIR_PRESENTATION_PAYPHONE).when(mImsCallProfile) 163 .getCallExtraInt(eq(ImsCallProfile.EXTRA_CNAP)); 164 doReturn(ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED).when(mImsCallProfile) 165 .getCallExtraInt(eq(ImsCallProfile.EXTRA_OIR)); 166 167 mConnectionUT.updateAddressDisplay(mImsCall); 168 assertEquals(ImsCallProfile.OIRToPresentation(ImsCallProfile.OIR_PRESENTATION_PAYPHONE), 169 mConnectionUT.getCnapNamePresentation()); 170 assertEquals(ImsCallProfile.OIRToPresentation( 171 ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED), 172 mConnectionUT.getNumberPresentation()); 173 } 174 175 @Test 176 @SmallTest 177 public void testConnectionDisconnect() { 178 //Mock we have an active connection 179 testImsUpdateStateForeGround(); 180 waitForMs(50); 181 mConnectionUT.onDisconnect(DisconnectCause.LOCAL); 182 assertEquals(DisconnectCause.LOCAL, mConnectionUT.getDisconnectCause()); 183 assertEquals(GsmCdmaCall.State.DISCONNECTED, mConnectionUT.getState()); 184 assertTrue(mConnectionUT.getDisconnectTime() <= System.currentTimeMillis()); 185 assertTrue(mConnectionUT.getDurationMillis() >= 50); 186 } 187 188 @Test 189 @SmallTest 190 public void testPostDialWait() { 191 mConnectionUT = new ImsPhoneConnection(mImsPhone, String.format("+1 (700).555-41NN%c1234", 192 PhoneNumberUtils.WAIT), mImsCT, mForeGroundCall, false); 193 doReturn(Call.State.DIALING).when(mForeGroundCall).getState(); 194 doAnswer(new Answer() { 195 @Override 196 public Void answer(InvocationOnMock invocation) throws Throwable { 197 Message msg = (Message) invocation.getArguments()[1]; 198 AsyncResult.forMessage(msg); 199 msg.sendToTarget(); 200 return null; 201 } 202 }).when(mImsCT).sendDtmf(anyChar(), (Message) any()); 203 // process post dial string during update 204 assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 205 assertEquals(Connection.PostDialState.WAIT, mConnectionUT.getPostDialState()); 206 mConnectionUT.proceedAfterWaitChar(); 207 waitForMs(50); 208 assertEquals(Connection.PostDialState.COMPLETE, mConnectionUT.getPostDialState()); 209 } 210 211 @Test 212 @MediumTest 213 public void testPostDialPause() { 214 mConnectionUT = new ImsPhoneConnection(mImsPhone, String.format("+1 (700).555-41NN%c1234", 215 PhoneNumberUtils.PAUSE), mImsCT, mForeGroundCall, false); 216 doReturn(Call.State.DIALING).when(mForeGroundCall).getState(); 217 doAnswer(new Answer() { 218 @Override 219 public Void answer(InvocationOnMock invocation) throws Throwable { 220 Message msg = (Message) invocation.getArguments()[1]; 221 AsyncResult.forMessage(msg); 222 msg.sendToTarget(); 223 return null; 224 } 225 }).when(mImsCT).sendDtmf(anyChar(), (Message) any()); 226 227 // process post dial string during update 228 assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 229 assertEquals(Connection.PostDialState.STARTED, mConnectionUT.getPostDialState()); 230 try { 231 Field field = ImsPhoneConnection.class.getDeclaredField("PAUSE_DELAY_MILLIS"); 232 field.setAccessible(true); 233 waitForMs((Integer) field.get(null) + 50); 234 } catch (Exception ex) { 235 Assert.fail("unexpected exception thrown" + ex.getMessage()); 236 } 237 assertEquals(Connection.PostDialState.COMPLETE, mConnectionUT.getPostDialState()); 238 } 239 240 @Test 241 @SmallTest 242 public void testSetWifi() { 243 mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false); 244 assertFalse(mConnectionUT.isWifi()); 245 // ImsCall.isWifiCall is tested elsewhere 246 doReturn(true).when(mImsCall).isWifiCall(); 247 mBundle.putString(ImsCallProfile.EXTRA_CALL_RAT_TYPE, 248 ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN + ""); 249 assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 250 assertTrue(mConnectionUT.isWifi()); 251 } 252 253 @Test 254 @SmallTest 255 public void testSetWifi2() { 256 mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false); 257 assertFalse(mConnectionUT.isWifi()); 258 // ImsCall.isWifiCall is tested elsewhere 259 doReturn(true).when(mImsCall).isWifiCall(); 260 // Tests to make sure that the EXTRA_CALL_RAT_TYPE_ALT string is set correctly for newer 261 // devices. 262 mBundle.putString(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT, 263 ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN + ""); 264 assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 265 assertTrue(mConnectionUT.isWifi()); 266 } 267 268 /** 269 * Test updates to address for incoming calls. 270 */ 271 @Test 272 @SmallTest 273 public void testAddressUpdate() { 274 String[] testAddressMappingSet[] = { 275 /* {"inputAddress", "updateAddress", "ExpectResult"} */ 276 {"12345", "12345", "12345"}, 277 {"12345", "67890", "67890"}, 278 {"12345*00000", "12345", "12345*00000"}, 279 {"12345*00000", "67890", "67890"}, 280 {"12345*00000", "12345*00000", "12345*00000"}, 281 {"12345;11111*00000", "12345", "12345"}, 282 {"12345*00000;11111", "12345", "12345*00000"}, 283 {"18412345*00000", "18412345", "18412345*00000"}, 284 {"+8112345*00000", "+8112345", "+8112345*00000"}, 285 {"12345*00000", "12346", "12346"}}; 286 for (String[] testAddress : testAddressMappingSet) { 287 mConnectionUT = new ImsPhoneConnection(mImsPhone, testAddress[0], mImsCT, 288 mForeGroundCall, false); 289 mConnectionUT.setIsIncoming(true); 290 doReturn(testAddress[1]).when(mImsCallProfile) 291 .getCallExtra(eq(ImsCallProfile.EXTRA_OI)); 292 mConnectionUT.updateAddressDisplay(mImsCall); 293 assertEquals(testAddress[2], mConnectionUT.getAddress()); 294 } 295 } 296 297 /** 298 * Ensure updates to the address for outgoing calls are ignored. 299 */ 300 @Test 301 @SmallTest 302 public void testSetAddressOnOutgoing() { 303 String inputAddress = "12345"; 304 String updateAddress = "6789"; 305 306 mConnectionUT = new ImsPhoneConnection(mImsPhone, inputAddress, mImsCT, mForeGroundCall, 307 false); 308 mConnectionUT.setIsIncoming(false); 309 doReturn(updateAddress).when(mImsCallProfile) 310 .getCallExtra(eq(ImsCallProfile.EXTRA_OI)); 311 mConnectionUT.updateAddressDisplay(mImsCall); 312 assertEquals(inputAddress, mConnectionUT.getAddress()); 313 } 314 } 315