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 */ 16package com.android.internal.telephony.imsphone; 17 18import android.os.AsyncResult; 19import android.os.Bundle; 20import android.os.Handler; 21import android.os.Looper; 22import android.os.Message; 23import android.telephony.DisconnectCause; 24import android.telephony.PhoneNumberUtils; 25import android.telephony.ServiceState; 26import android.test.suitebuilder.annotation.MediumTest; 27import android.test.suitebuilder.annotation.SmallTest; 28 29import com.android.ims.ImsCallProfile; 30import com.android.internal.telephony.Call; 31import com.android.internal.telephony.Connection; 32import com.android.internal.telephony.GsmCdmaCall; 33import com.android.internal.telephony.PhoneConstants; 34import com.android.internal.telephony.TelephonyTest; 35 36import org.junit.After; 37import org.junit.Assert; 38import org.junit.Before; 39import org.junit.Test; 40import org.mockito.Mock; 41import org.mockito.invocation.InvocationOnMock; 42import org.mockito.stubbing.Answer; 43 44import java.lang.reflect.Field; 45 46import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; 47import static org.junit.Assert.assertEquals; 48import static org.junit.Assert.assertFalse; 49import static org.junit.Assert.assertNull; 50import static org.junit.Assert.assertTrue; 51import static org.mockito.Mockito.any; 52import static org.mockito.Mockito.anyChar; 53import static org.mockito.Mockito.doAnswer; 54import static org.mockito.Mockito.doReturn; 55import static org.mockito.Mockito.eq; 56import static org.mockito.Mockito.times; 57import static org.mockito.Mockito.verify; 58 59public 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 assertTrue(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 //keep using the wifi state from extra, not update 252 assertFalse(mConnectionUT.updateWifiState()); 253 } 254 255 @Test 256 @SmallTest 257 public void testSetWifi2() { 258 mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false); 259 assertFalse(mConnectionUT.isWifi()); 260 // ImsCall.isWifiCall is tested elsewhere 261 doReturn(true).when(mImsCall).isWifiCall(); 262 // Tests to make sure that the EXTRA_CALL_RAT_TYPE_ALT string is set correctly for newer 263 // devices. 264 mBundle.putString(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT, 265 ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN + ""); 266 assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE)); 267 assertTrue(mConnectionUT.isWifi()); 268 //keep using the wifi state from extra, not update 269 assertFalse(mConnectionUT.updateWifiState()); 270 } 271} 272