blob: ed2f6b19beb23f9a3dd758416a1813faad85b835 [file] [log] [blame]
Tyler Gunnc74b3e22017-11-07 15:03:24 -08001/*
2 * Copyright (C) 2017 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
17package com.android.server.telecom.tests;
18
Hall Liuc8a396b2017-12-27 18:23:28 -080019import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertTrue;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080021import static org.mockito.ArgumentMatchers.any;
22import static org.mockito.ArgumentMatchers.anyBoolean;
Tyler Gunnad972422017-11-13 13:36:35 -080023import static org.mockito.ArgumentMatchers.anyChar;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080024import static org.mockito.ArgumentMatchers.anyInt;
25import static org.mockito.ArgumentMatchers.eq;
Pengquan Meng606ff7f2017-12-20 16:13:04 -080026import static org.mockito.Mockito.doNothing;
27import static org.mockito.Mockito.doReturn;
Tyler Gunnad972422017-11-13 13:36:35 -080028import static org.mockito.Mockito.never;
29import static org.mockito.Mockito.verify;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080030import static org.mockito.Mockito.when;
31
32import android.content.ComponentName;
33import android.net.Uri;
34import android.os.SystemClock;
Pengquan Meng606ff7f2017-12-20 16:13:04 -080035import android.telecom.Connection;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080036import android.telecom.PhoneAccount;
37import android.telecom.PhoneAccountHandle;
Pengquan Meng606ff7f2017-12-20 16:13:04 -080038import android.telecom.VideoProfile;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080039import android.telephony.TelephonyManager;
40import android.test.suitebuilder.annotation.MediumTest;
41
Pengquan Meng606ff7f2017-12-20 16:13:04 -080042import android.test.suitebuilder.annotation.SmallTest;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080043import com.android.server.telecom.AsyncRingtonePlayer;
44import com.android.server.telecom.Call;
45import com.android.server.telecom.CallAudioManager;
46import com.android.server.telecom.CallState;
47import com.android.server.telecom.CallerInfoAsyncQueryFactory;
48import com.android.server.telecom.CallsManager;
49import com.android.server.telecom.ClockProxy;
Pengquan Meng606ff7f2017-12-20 16:13:04 -080050import com.android.server.telecom.ConnectionServiceFocusManager;
51import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
Pengquan Meng0e913fd2018-01-17 05:24:52 +000052import com.android.server.telecom.ConnectionServiceWrapper;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080053import com.android.server.telecom.ContactsAsyncHelper;
54import com.android.server.telecom.DefaultDialerCache;
55import com.android.server.telecom.EmergencyCallHelper;
56import com.android.server.telecom.HeadsetMediaButton;
57import com.android.server.telecom.HeadsetMediaButtonFactory;
58import com.android.server.telecom.InCallController;
59import com.android.server.telecom.InCallControllerFactory;
60import com.android.server.telecom.InCallTonePlayer;
61import com.android.server.telecom.InCallWakeLockController;
62import com.android.server.telecom.InCallWakeLockControllerFactory;
63import com.android.server.telecom.MissedCallNotifier;
64import com.android.server.telecom.PhoneAccountRegistrar;
65import com.android.server.telecom.PhoneNumberUtilsAdapter;
66import com.android.server.telecom.ProximitySensorManager;
67import com.android.server.telecom.ProximitySensorManagerFactory;
68import com.android.server.telecom.SystemStateProvider;
69import com.android.server.telecom.TelecomSystem;
70import com.android.server.telecom.Timeouts;
71import com.android.server.telecom.WiredHeadsetManager;
72import com.android.server.telecom.bluetooth.BluetoothRouteManager;
Hall Liu784a4962018-03-06 11:03:17 -080073import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080074
Hall Liuc8a396b2017-12-27 18:23:28 -080075import org.junit.Before;
76import org.junit.Test;
77import org.junit.runner.RunWith;
78import org.junit.runners.JUnit4;
Pengquan Meng606ff7f2017-12-20 16:13:04 -080079import org.mockito.ArgumentCaptor;
80import org.mockito.Matchers;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080081import org.mockito.Mock;
Tyler Gunnad972422017-11-13 13:36:35 -080082import org.mockito.Mockito;
Tyler Gunnc74b3e22017-11-07 15:03:24 -080083import org.mockito.MockitoAnnotations;
84
85import java.util.ArrayList;
86import java.util.Arrays;
87import java.util.Collections;
88import java.util.List;
89
Hall Liuc8a396b2017-12-27 18:23:28 -080090@RunWith(JUnit4.class)
Tyler Gunnc74b3e22017-11-07 15:03:24 -080091public class CallsManagerTest extends TelecomTestCase {
92 private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle(
93 ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1");
94 private static final PhoneAccountHandle SIM_2_HANDLE = new PhoneAccountHandle(
95 ComponentName.unflattenFromString("com.foo/.Blah"), "Sim2");
96 private static final PhoneAccountHandle SELF_MANAGED_HANDLE = new PhoneAccountHandle(
97 ComponentName.unflattenFromString("com.foo/.Self"), "Self");
98 private static final PhoneAccount SIM_1_ACCOUNT = new PhoneAccount.Builder(SIM_1_HANDLE, "Sim1")
99 .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
100 | PhoneAccount.CAPABILITY_CALL_PROVIDER)
101 .setIsEnabled(true)
102 .build();
103 private static final PhoneAccount SIM_2_ACCOUNT = new PhoneAccount.Builder(SIM_2_HANDLE, "Sim2")
104 .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
105 | PhoneAccount.CAPABILITY_CALL_PROVIDER
106 | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING)
107 .setIsEnabled(true)
108 .build();
109 private static final PhoneAccount SELF_MANAGED_ACCOUNT = new PhoneAccount.Builder(
110 SELF_MANAGED_HANDLE, "Self")
111 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
112 .setIsEnabled(true)
113 .build();
114 private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212");
115
116 private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
117 @Mock private ContactsAsyncHelper mContactsAsyncHelper;
118 @Mock private CallerInfoAsyncQueryFactory mCallerInfoAsyncQueryFactory;
119 @Mock private MissedCallNotifier mMissedCallNotifier;
120 @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
121 @Mock private HeadsetMediaButton mHeadsetMediaButton;
122 @Mock private HeadsetMediaButtonFactory mHeadsetMediaButtonFactory;
123 @Mock private ProximitySensorManager mProximitySensorManager;
124 @Mock private ProximitySensorManagerFactory mProximitySensorManagerFactory;
125 @Mock private InCallWakeLockController mInCallWakeLockController;
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800126 @Mock private ConnectionServiceFocusManagerFactory mConnSvrFocusManagerFactory;
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800127 @Mock private InCallWakeLockControllerFactory mInCallWakeLockControllerFactory;
128 @Mock private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
129 @Mock private BluetoothRouteManager mBluetoothRouteManager;
130 @Mock private WiredHeadsetManager mWiredHeadsetManager;
131 @Mock private SystemStateProvider mSystemStateProvider;
132 @Mock private DefaultDialerCache mDefaultDialerCache;
133 @Mock private Timeouts.Adapter mTimeoutsAdapter;
134 @Mock private AsyncRingtonePlayer mAsyncRingtonePlayer;
135 @Mock private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
136 @Mock private EmergencyCallHelper mEmergencyCallHelper;
137 @Mock private InCallTonePlayer.ToneGeneratorFactory mToneGeneratorFactory;
138 @Mock private ClockProxy mClockProxy;
139 @Mock private InCallControllerFactory mInCallControllerFactory;
140 @Mock private InCallController mInCallController;
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800141 @Mock private ConnectionServiceFocusManager mConnectionSvrFocusMgr;
Hall Liu784a4962018-03-06 11:03:17 -0800142 @Mock private BluetoothStateReceiver mBluetoothStateReceiver;
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800143
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800144 private CallsManager mCallsManager;
145
146 @Override
Hall Liuc8a396b2017-12-27 18:23:28 -0800147 @Before
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800148 public void setUp() throws Exception {
149 super.setUp();
150 MockitoAnnotations.initMocks(this);
151 when(mInCallWakeLockControllerFactory.create(any(), any())).thenReturn(
152 mInCallWakeLockController);
153 when(mHeadsetMediaButtonFactory.create(any(), any(), any())).thenReturn(
154 mHeadsetMediaButton);
155 when(mProximitySensorManagerFactory.create(any(), any())).thenReturn(
156 mProximitySensorManager);
157 when(mInCallControllerFactory.create(any(), any(), any(), any(), any(), any(),
158 any())).thenReturn(mInCallController);
159 when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
160 when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800161 when(mConnSvrFocusManagerFactory.create(any(), any())).thenReturn(mConnectionSvrFocusMgr);
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800162 mCallsManager = new CallsManager(
163 mComponentContextFixture.getTestDouble().getApplicationContext(),
164 mLock,
165 mContactsAsyncHelper,
166 mCallerInfoAsyncQueryFactory,
167 mMissedCallNotifier,
168 mPhoneAccountRegistrar,
169 mHeadsetMediaButtonFactory,
170 mProximitySensorManagerFactory,
171 mInCallWakeLockControllerFactory,
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800172 mConnSvrFocusManagerFactory,
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800173 mAudioServiceFactory,
174 mBluetoothRouteManager,
175 mWiredHeadsetManager,
176 mSystemStateProvider,
177 mDefaultDialerCache,
178 mTimeoutsAdapter,
179 mAsyncRingtonePlayer,
180 mPhoneNumberUtilsAdapter,
181 mEmergencyCallHelper,
182 mToneGeneratorFactory,
183 mClockProxy,
Hall Liu784a4962018-03-06 11:03:17 -0800184 mBluetoothStateReceiver,
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800185 mInCallControllerFactory);
186
187 when(mPhoneAccountRegistrar.getPhoneAccount(
188 eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT);
189 when(mPhoneAccountRegistrar.getPhoneAccount(
190 eq(SIM_1_HANDLE), any())).thenReturn(SIM_1_ACCOUNT);
191 when(mPhoneAccountRegistrar.getPhoneAccount(
192 eq(SIM_2_HANDLE), any())).thenReturn(SIM_2_ACCOUNT);
193 }
194
195 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800196 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800197 public void testConstructPossiblePhoneAccounts() throws Exception {
198 // Should be empty since the URI is null.
199 assertEquals(0, mCallsManager.constructPossiblePhoneAccounts(null, null, false).size());
200 }
201
202 /**
203 * Verify behavior for multisim devices where we want to ensure that the active sim is used for
204 * placing a new call.
205 * @throws Exception
206 */
207 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800208 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800209 public void testConstructPossiblePhoneAccountsMultiSimActive() throws Exception {
210 setupMsimAccounts();
211
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800212 Call ongoingCall = new Call(
213 "1", /* callId */
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800214 mComponentContextFixture.getTestDouble(),
215 mCallsManager,
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800216 mLock,
217 null /* ConnectionServiceRepository */,
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800218 mContactsAsyncHelper,
219 mCallerInfoAsyncQueryFactory,
220 mPhoneNumberUtilsAdapter,
221 TEST_ADDRESS,
222 null /* GatewayInfo */,
223 null /* connectionManagerPhoneAccountHandle */,
224 SIM_2_HANDLE,
225 Call.CALL_DIRECTION_INCOMING,
226 false /* shouldAttachToExistingConnection*/,
227 false /* isConference */,
228 mClockProxy);
229 ongoingCall.setState(CallState.ACTIVE, "just cuz");
230 mCallsManager.addCall(ongoingCall);
231
232 List<PhoneAccountHandle> phoneAccountHandles = mCallsManager.constructPossiblePhoneAccounts(
233 TEST_ADDRESS, null, false);
234 assertEquals(1, phoneAccountHandles.size());
235 assertEquals(SIM_2_HANDLE, phoneAccountHandles.get(0));
236 }
237
238 /**
239 * Verify behavior for multisim devices when there are no calls active; expect both accounts.
240 * @throws Exception
241 */
242 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800243 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800244 public void testConstructPossiblePhoneAccountsMultiSimIdle() throws Exception {
245 setupMsimAccounts();
246
247 List<PhoneAccountHandle> phoneAccountHandles = mCallsManager.constructPossiblePhoneAccounts(
248 TEST_ADDRESS, null, false);
249 assertEquals(2, phoneAccountHandles.size());
250 }
251
252 /**
253 * Tests finding the outgoing call phone account where the call is being placed on a
254 * self-managed ConnectionService.
255 * @throws Exception
256 */
257 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800258 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800259 public void testFindOutgoingCallPhoneAccountSelfManaged() throws Exception {
260 List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
261 SELF_MANAGED_HANDLE, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
262 assertEquals(1, accounts.size());
263 assertEquals(SELF_MANAGED_HANDLE, accounts.get(0));
264 }
265
266 /**
267 * Tests finding the outgoing calling account where the call has no associated phone account,
268 * but there is a user specified default which can be used.
269 * @throws Exception
270 */
271 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800272 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800273 public void testFindOutgoingCallAccountDefault() throws Exception {
274 when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
275 SIM_1_HANDLE);
276 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
277 any(), anyInt())).thenReturn(
278 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
279
280 List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
281 null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
282
283 // Should have found just the default.
284 assertEquals(1, accounts.size());
285 assertEquals(SIM_1_HANDLE, accounts.get(0));
286 }
287
288 /**
289 * Tests finding the outgoing calling account where the call has no associated phone account,
290 * but there is no user specified default which can be used.
291 * @throws Exception
292 */
293 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800294 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800295 public void testFindOutgoingCallAccountNoDefault() throws Exception {
296 when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
297 null);
298 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
299 any(), anyInt())).thenReturn(
300 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
301
302 List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
303 null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
304
305 assertEquals(2, accounts.size());
306 assertTrue(accounts.contains(SIM_1_HANDLE));
307 assertTrue(accounts.contains(SIM_2_HANDLE));
308 }
309
310 /**
311 * Tests that we will default to a video capable phone account if one is available for a video
312 * call.
313 * @throws Exception
314 */
315 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800316 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800317 public void testFindOutgoingCallAccountVideo() throws Exception {
318 when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
319 null);
320 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
321 any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING))).thenReturn(
322 new ArrayList<>(Arrays.asList(SIM_2_HANDLE)));
323
324 List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
325 null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, null /* userHandle */);
326
327 assertEquals(1, accounts.size());
328 assertTrue(accounts.contains(SIM_2_HANDLE));
329 }
330
331 /**
332 * Tests that we will default to a non-video capable phone account for a video call if no video
333 * capable phone accounts are available.
334 * @throws Exception
335 */
336 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800337 @Test
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800338 public void testFindOutgoingCallAccountVideoNotAvailable() throws Exception {
339 when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
340 null);
341 // When querying for video capable accounts, return nothing.
342 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
343 any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING))).thenReturn(
344 Collections.emptyList());
345 // When querying for non-video capable accounts, return one.
346 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
347 any(), eq(0 /* none specified */))).thenReturn(
348 new ArrayList<>(Arrays.asList(SIM_1_HANDLE)));
349 List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
350 null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, null /* userHandle */);
351
352 // Should have found one.
353 assertEquals(1, accounts.size());
354 assertTrue(accounts.contains(SIM_1_HANDLE));
355 }
356
Tyler Gunnb8ce2aa2017-11-15 13:10:13 -0800357 /**
358 * Tests that we will use the provided target phone account if it exists.
359 * @throws Exception
360 */
361 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800362 @Test
Tyler Gunnb8ce2aa2017-11-15 13:10:13 -0800363 public void testUseSpecifiedAccount() throws Exception {
364 when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
365 null);
366 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
367 any(), anyInt())).thenReturn(
368 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
369
370 List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
371 SIM_2_HANDLE, TEST_ADDRESS, false /* isVideo */, null /* userHandle */);
372
373 assertEquals(1, accounts.size());
374 assertTrue(accounts.contains(SIM_2_HANDLE));
375 }
376
Tyler Gunnad972422017-11-13 13:36:35 -0800377 /**
378 * Verifies that an active call will result in playing a DTMF tone when requested.
379 * @throws Exception
380 */
381 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800382 @Test
Tyler Gunnad972422017-11-13 13:36:35 -0800383 public void testPlayDtmfWhenActive() throws Exception {
384 Call callSpy = addSpyCall();
385 mCallsManager.playDtmfTone(callSpy, '1');
386 verify(callSpy).playDtmfTone(anyChar());
387 }
388
389 /**
390 * Verifies that DTMF requests are suppressed when a call is held.
391 * @throws Exception
392 */
393 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800394 @Test
Tyler Gunnad972422017-11-13 13:36:35 -0800395 public void testSuppessDtmfWhenHeld() throws Exception {
396 Call callSpy = addSpyCall();
397 callSpy.setState(CallState.ON_HOLD, "test");
398
399 mCallsManager.playDtmfTone(callSpy, '1');
400 verify(callSpy, never()).playDtmfTone(anyChar());
401 }
402
403 /**
404 * Verifies that DTMF requests are suppressed when a call is held.
405 * @throws Exception
406 */
407 @MediumTest
Hall Liuc8a396b2017-12-27 18:23:28 -0800408 @Test
Tyler Gunnad972422017-11-13 13:36:35 -0800409 public void testCancelDtmfWhenHeld() throws Exception {
410 Call callSpy = addSpyCall();
411 mCallsManager.playDtmfTone(callSpy, '1');
412 mCallsManager.markCallAsOnHold(callSpy);
413 verify(callSpy).stopDtmfTone();
414 }
415
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800416 @SmallTest
417 @Test
418 public void testUnholdCallWhenOngoingCallCanBeHeld() {
419 // GIVEN a CallsManager with ongoing call, and this call can be held
420 Call ongoingCall = addSpyCall();
421 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
Pengquan Meng2fc55272018-03-19 17:36:32 -0700422 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800423 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
424
425 // and a held call
426 Call heldCall = addSpyCall();
427
428 // WHEN unhold the held call
429 mCallsManager.unholdCall(heldCall);
430
431 // THEN the ongoing call is held, and the focus request for incoming call is sent
Pengquan Meng2fc55272018-03-19 17:36:32 -0700432 verify(ongoingCall).hold(any());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800433 verifyFocusRequestAndExecuteCallback(heldCall);
434
435 // and held call is unhold now
Pengquan Meng2fc55272018-03-19 17:36:32 -0700436 verify(heldCall).unhold(any());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800437 }
438
439 @SmallTest
440 @Test
441 public void testUnholdCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
442 ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
443 ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
444
445 // GIVEN a CallsManager with ongoing call, and this call can not be held
446 Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
447 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
Pengquan Meng2fc55272018-03-19 17:36:32 -0700448 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800449 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
450
451 // and a held call which has different ConnectionService
452 Call heldCall = addSpyCallWithConnectionService(connSvr2);
453
454 // WHEN unhold the held call
455 mCallsManager.unholdCall(heldCall);
456
457 // THEN the ongoing call is disconnected, and the focus request for incoming call is sent
Pengquan Meng2fc55272018-03-19 17:36:32 -0700458 verify(ongoingCall).disconnect(any());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800459 verifyFocusRequestAndExecuteCallback(heldCall);
460
461 // and held call is unhold now
Pengquan Meng2fc55272018-03-19 17:36:32 -0700462 verify(heldCall).unhold(any());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800463 }
464
Pengquan Meng2fc55272018-03-19 17:36:32 -0700465 @SmallTest
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800466 @Test
467 public void testUnholdCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
468 ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
469
470 // GIVEN a CallsManager with ongoing call, and this call can not be held
471 Call ongoingCall = addSpyCallWithConnectionService(connSvr);
472 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
Pengquan Meng2fc55272018-03-19 17:36:32 -0700473 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800474 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
475
476 // and a held call which has different ConnectionService
477 Call heldCall = addSpyCallWithConnectionService(connSvr);
478
479 // WHEN unhold the held call
480 mCallsManager.unholdCall(heldCall);
481
482 // THEN the ongoing call is held
Pengquan Meng2fc55272018-03-19 17:36:32 -0700483 verify(ongoingCall).hold(any());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800484 verifyFocusRequestAndExecuteCallback(heldCall);
485
486 // and held call is unhold now
Pengquan Meng2fc55272018-03-19 17:36:32 -0700487 verify(heldCall).unhold(any());
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800488 }
489
490 @SmallTest
491 @Test
492 public void testAnswerCallWhenOngoingCallCanBeHeld() {
493 // GIVEN a CallsManager with ongoing call, and this call can be held
494 Call ongoingCall = addSpyCall();
495 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
Pengquan Meng2fc55272018-03-19 17:36:32 -0700496 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800497 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
498
499 // WHEN answer an incoming call
500 Call incomingCall = addSpyCall();
501 mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
502
503 // THEN the ongoing call is held and the focus request for incoming call is sent
504 verify(ongoingCall).hold();
505 verifyFocusRequestAndExecuteCallback(incomingCall);
506
507 // and the incoming call is answered.
508 verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
509 }
510
511 @SmallTest
512 @Test
513 public void testAnswerCallWhenOngoingHasSameConnectionService() {
514 ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
515
516 // GIVEN a CallsManager with ongoing call, and this call can not be held
517 Call ongoingCall = addSpyCallWithConnectionService(connSvr);
518 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
519 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
520
521 // WHEN answer an incoming call
522 Call incomingCall = addSpyCallWithConnectionService(connSvr);
523 mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
524
525 // THEN nothing happened on the ongoing call and the focus request for incoming call is sent
526 verifyFocusRequestAndExecuteCallback(incomingCall);
527
528 // and the incoming call is answered.
529 verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
530 }
531
532 @SmallTest
533 @Test
Pengquan Meng2fc55272018-03-19 17:36:32 -0700534 public void testAnswerCallWhenOngoingHasDifferentConnectionService() {
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800535 ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
536 ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
537
538 // GIVEN a CallsManager with ongoing call, and this call can not be held
539 Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
540 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
Pengquan Meng2fc55272018-03-19 17:36:32 -0700541 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800542 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
543
544 // WHEN answer an incoming call
545 Call incomingCall = addSpyCallWithConnectionService(connSvr2);
546 mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
547
548 // THEN the ongoing call is disconnected and the focus request for incoming call is sent
549 verify(ongoingCall).disconnect();
550 verifyFocusRequestAndExecuteCallback(incomingCall);
551
552 // and the incoming call is answered.
553 verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
554 }
555
556 @SmallTest
557 @Test
Pengquan Meng2fc55272018-03-19 17:36:32 -0700558 public void testAnswerCallWhenMultipleHeldCallsExisted() {
559 ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
560 ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
561
562 // Given an ongoing call and held call with the ConnectionService connSvr1. The
563 // ConnectionService connSvr1 can handle one held call
564 Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
565 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
566 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
567 Call heldCall = addSpyCallWithConnectionService(connSvr1);
568 doReturn(CallState.ON_HOLD).when(heldCall).getState();
569
570 // and other held call has difference ConnectionService
571 Call heldCall2 = addSpyCallWithConnectionService(connSvr2);
572 doReturn(CallState.ON_HOLD).when(heldCall2).getState();
573
574 // WHEN answer an incoming call which ConnectionService is connSvr1
575 Call incomingCall = addSpyCallWithConnectionService(connSvr1);
576 mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
577
578 // THEN the previous held call is disconnected
579 verify(heldCall).disconnect();
580
581 // and the ongoing call is held
582 verify(ongoingCall).hold();
583
584 // and the heldCall2 is not disconnected
585 verify(heldCall2, never()).disconnect();
586
587 // and the focus request is sent
588 verifyFocusRequestAndExecuteCallback(incomingCall);
589
590 // and the incoming call is answered
591 verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
592 }
593
594 @SmallTest
595 @Test
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800596 public void testAnswerCallWhenNoOngoingCallExisted() {
597 // GIVEN a CallsManager with no ongoing call.
598
599 // WHEN answer an incoming call
600 Call incomingCall = addSpyCall();
601 mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
602
603 // THEN the focus request for incoming call is sent
604 verifyFocusRequestAndExecuteCallback(incomingCall);
605
606 // and the incoming call is answered.
607 verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
608 }
609
Pengquan Meng2fc55272018-03-19 17:36:32 -0700610 @SmallTest
611 @Test
612 public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
613 ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
614 ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);
615
616 // GIVEN a CallsManager with ongoing call, and this call can not be held
617 Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
618 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
619 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
620 doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();
621
622 // and a new self-managed call which has different ConnectionService
623 Call newCall = addSpyCallWithConnectionService(connSvr2);
624 doReturn(true).when(newCall).isSelfManaged();
625
626 // WHEN active the new call
627 mCallsManager.markCallAsActive(newCall);
628
629 // THEN the ongoing call is disconnected, and the focus request for the new call is sent
630 verify(ongoingCall).disconnect();
631 verifyFocusRequestAndExecuteCallback(newCall);
632
633 // and the new call is active
634 assertEquals(CallState.ACTIVE, newCall.getState());
635 }
636
637 @SmallTest
638 @Test
639 public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
640 ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
641
642 // GIVEN a CallsManager with ongoing call, and this call can not be held
643 Call ongoingCall = addSpyCallWithConnectionService(connSvr);
644 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
645 doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
646 when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);
647
648 // and a new self-managed call which has the same ConnectionService
649 Call newCall = addSpyCallWithConnectionService(connSvr);
650 doReturn(true).when(newCall).isSelfManaged();
651
652 // WHEN active the new call
653 mCallsManager.markCallAsActive(newCall);
654
655 // THEN the ongoing call isn't disconnected
656 verify(ongoingCall, never()).disconnect();
657 verifyFocusRequestAndExecuteCallback(newCall);
658
659 // and the new call is active
660 assertEquals(CallState.ACTIVE, newCall.getState());
661 }
662
663 @SmallTest
664 @Test
665 public void testSetActiveCallWhenOngoingCallCanBeHeld() {
666 // GIVEN a CallsManager with ongoing call, and this call can be held
667 Call ongoingCall = addSpyCall();
668 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
669 doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
670 doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();
671
672 // and a new self-managed call
673 Call newCall = addSpyCall();
674 doReturn(true).when(newCall).isSelfManaged();
675
676 // WHEN active the new call
677 mCallsManager.markCallAsActive(newCall);
678
679 // THEN the ongoing call is held
680 verify(ongoingCall).hold();
681 verifyFocusRequestAndExecuteCallback(newCall);
682
683 // and the new call is active
684 assertEquals(CallState.ACTIVE, newCall.getState());
685 }
686
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800687 private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) {
688 Call call = addSpyCall();
689 doReturn(connSvr).when(call).getConnectionService();
690 return call;
691 }
692
Tyler Gunnad972422017-11-13 13:36:35 -0800693 private Call addSpyCall() {
694 Call ongoingCall = new Call("1", /* callId */
695 mComponentContextFixture.getTestDouble(),
696 mCallsManager,
697 mLock, /* ConnectionServiceRepository */
698 null,
699 mContactsAsyncHelper,
700 mCallerInfoAsyncQueryFactory,
701 mPhoneNumberUtilsAdapter,
702 TEST_ADDRESS,
703 null /* GatewayInfo */,
704 null /* connectionManagerPhoneAccountHandle */,
705 SIM_2_HANDLE,
706 Call.CALL_DIRECTION_INCOMING,
707 false /* shouldAttachToExistingConnection*/,
708 false /* isConference */,
709 mClockProxy);
710 ongoingCall.setState(CallState.ACTIVE, "just cuz");
711 Call callSpy = Mockito.spy(ongoingCall);
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800712
713 // Mocks some methods to not call the real method.
714 doNothing().when(callSpy).unhold();
715 doNothing().when(callSpy).hold();
716 doNothing().when(callSpy).disconnect();
717 doNothing().when(callSpy).answer(Matchers.anyInt());
718 doNothing().when(callSpy).setStartWithSpeakerphoneOn(Matchers.anyBoolean());
719
Tyler Gunnad972422017-11-13 13:36:35 -0800720 mCallsManager.addCall(callSpy);
721 return callSpy;
722 }
723
Pengquan Meng606ff7f2017-12-20 16:13:04 -0800724 private void verifyFocusRequestAndExecuteCallback(Call call) {
725 ArgumentCaptor<CallsManager.RequestCallback> captor =
726 ArgumentCaptor.forClass(CallsManager.RequestCallback.class);
727 verify(mConnectionSvrFocusMgr).requestFocus(eq(call), captor.capture());
728 CallsManager.RequestCallback callback = captor.getValue();
729 callback.onRequestFocusDone(call);
730 }
731
Tyler Gunnc74b3e22017-11-07 15:03:24 -0800732 private void setupMsimAccounts() {
733 TelephonyManager mockTelephonyManager = mComponentContextFixture.getTelephonyManager();
734 when(mockTelephonyManager.getMultiSimConfiguration()).thenReturn(
735 TelephonyManager.MultiSimVariants.DSDS);
736 when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
737 any(), anyInt())).thenReturn(
738 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
739 when(mPhoneAccountRegistrar.getSimPhoneAccountsOfCurrentUser()).thenReturn(
740 new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
741 }
742}