1 /*
2  * Copyright (C) 2015 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.server.telecom.tests;
18 
19 
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24 import static org.mockito.ArgumentMatchers.nullable;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyBoolean;
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.Mockito.doAnswer;
31 import static org.mockito.Mockito.doNothing;
32 import static org.mockito.Mockito.doReturn;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.reset;
35 import static org.mockito.Mockito.spy;
36 import static org.mockito.Mockito.timeout;
37 import static org.mockito.Mockito.times;
38 import static org.mockito.Mockito.verify;
39 import static org.mockito.Mockito.when;
40 
41 import android.annotation.Nullable;
42 import android.app.AppOpsManager;
43 import android.bluetooth.BluetoothManager;
44 import android.content.BroadcastReceiver;
45 import android.content.ComponentName;
46 import android.content.ContentResolver;
47 import android.content.Context;
48 import android.content.Intent;
49 import android.media.AudioManager;
50 import android.media.IAudioService;
51 import android.media.ToneGenerator;
52 import android.net.Uri;
53 import android.os.Bundle;
54 import android.os.Handler;
55 import android.os.HandlerThread;
56 import android.os.Looper;
57 import android.os.Process;
58 import android.os.UserHandle;
59 import android.telecom.Call;
60 import android.telecom.ConnectionRequest;
61 import android.telecom.DisconnectCause;
62 import android.telecom.Log;
63 import android.telecom.ParcelableCall;
64 import android.telecom.PhoneAccount;
65 import android.telecom.PhoneAccountHandle;
66 import android.telecom.TelecomManager;
67 import android.telecom.VideoProfile;
68 import android.telephony.TelephonyManager;
69 import android.telephony.TelephonyRegistryManager;
70 
71 import com.android.internal.telecom.IInCallAdapter;
72 import com.android.server.telecom.AsyncRingtonePlayer;
73 import com.android.server.telecom.CallAudioCommunicationDeviceTracker;
74 import com.android.server.telecom.CallAudioManager;
75 import com.android.server.telecom.CallAudioModeStateMachine;
76 import com.android.server.telecom.CallAudioRouteStateMachine;
77 import com.android.server.telecom.CallerInfoLookupHelper;
78 import com.android.server.telecom.CallsManager;
79 import com.android.server.telecom.CallsManagerListenerBase;
80 import com.android.server.telecom.ClockProxy;
81 import com.android.server.telecom.ConnectionServiceFocusManager;
82 import com.android.server.telecom.ContactsAsyncHelper;
83 import com.android.server.telecom.DeviceIdleControllerAdapter;
84 import com.android.server.telecom.HeadsetMediaButton;
85 import com.android.server.telecom.HeadsetMediaButtonFactory;
86 import com.android.server.telecom.InCallWakeLockController;
87 import com.android.server.telecom.InCallWakeLockControllerFactory;
88 import com.android.server.telecom.MissedCallNotifier;
89 import com.android.server.telecom.PhoneAccountRegistrar;
90 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
91 import com.android.server.telecom.ProximitySensorManager;
92 import com.android.server.telecom.ProximitySensorManagerFactory;
93 import com.android.server.telecom.Ringer;
94 import com.android.server.telecom.RoleManagerAdapter;
95 import com.android.server.telecom.StatusBarNotifier;
96 import com.android.server.telecom.SystemStateHelper;
97 import com.android.server.telecom.TelecomSystem;
98 import com.android.server.telecom.Timeouts;
99 import com.android.server.telecom.WiredHeadsetManager;
100 import com.android.server.telecom.bluetooth.BluetoothRouteManager;
101 import com.android.server.telecom.callfiltering.BlockedNumbersAdapter;
102 import com.android.server.telecom.components.UserCallIntentProcessor;
103 import com.android.server.telecom.flags.FeatureFlags;
104 import com.android.server.telecom.ui.IncomingCallNotifier;
105 
106 import com.google.common.base.Predicate;
107 
108 import org.mockito.ArgumentCaptor;
109 import org.mockito.Mock;
110 import org.mockito.invocation.InvocationOnMock;
111 import org.mockito.stubbing.Answer;
112 
113 import java.io.File;
114 import java.util.ArrayList;
115 import java.util.Collections;
116 import java.util.LinkedList;
117 import java.util.List;
118 import java.util.concurrent.CountDownLatch;
119 import java.util.concurrent.Executor;
120 import java.util.concurrent.TimeUnit;
121 
122 /**
123  * Implements mocks and functionality required to implement telecom system tests.
124  */
125 public class TelecomSystemTest extends TelecomTestCase{
126 
127     private static final String CALLING_PACKAGE = TelecomSystemTest.class.getPackageName();
128     static final int TEST_POLL_INTERVAL = 10;  // milliseconds
129     static final int TEST_TIMEOUT = 1000;  // milliseconds
130 
131     // Purposely keep the connect time (which is wall clock) and elapsed time (which is time since
132     // boot) different to test that wall clock time operations and elapsed time operations perform
133     // as they individually should.
134     static final long TEST_CREATE_TIME = 100;
135     static final long TEST_CREATE_ELAPSED_TIME = 200;
136     static final long TEST_CONNECT_TIME = 1000;
137     static final long TEST_CONNECT_ELAPSED_TIME = 2000;
138     static final long TEST_DISCONNECT_TIME = 8000;
139     static final long TEST_DISCONNECT_ELAPSED_TIME = 4000;
140 
141     public class HeadsetMediaButtonFactoryF implements HeadsetMediaButtonFactory  {
142         @Override
create(Context context, CallsManager callsManager, TelecomSystem.SyncRoot lock)143         public HeadsetMediaButton create(Context context, CallsManager callsManager,
144                 TelecomSystem.SyncRoot lock) {
145             return mHeadsetMediaButton;
146         }
147     }
148 
149     public class ProximitySensorManagerFactoryF implements ProximitySensorManagerFactory {
150         @Override
create(Context context, CallsManager callsManager)151         public ProximitySensorManager create(Context context, CallsManager callsManager) {
152             return mProximitySensorManager;
153         }
154     }
155 
156     public class InCallWakeLockControllerFactoryF implements InCallWakeLockControllerFactory {
157         @Override
create(Context context, CallsManager callsManager)158         public InCallWakeLockController create(Context context, CallsManager callsManager) {
159             return mInCallWakeLockController;
160         }
161     }
162 
163     public static class MissedCallNotifierFakeImpl extends CallsManagerListenerBase
164             implements MissedCallNotifier {
165         List<CallInfo> missedCallsNotified = new ArrayList<>();
166 
167         @Override
clearMissedCalls(UserHandle userHandle)168         public void clearMissedCalls(UserHandle userHandle) {
169 
170         }
171 
172         @Override
showMissedCallNotification(CallInfo call, @Nullable Uri uri)173         public void showMissedCallNotification(CallInfo call, @Nullable Uri uri) {
174             missedCallsNotified.add(call);
175         }
176 
177         @Override
reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper, CallInfoFactory callInfoFactory)178         public void reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper,
179                 CallInfoFactory callInfoFactory) { }
180 
181         @Override
reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper, CallInfoFactory callInfoFactory, UserHandle userHandle)182         public void reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper,
183                 CallInfoFactory callInfoFactory, UserHandle userHandle) { }
184 
185         @Override
setCurrentUserHandle(UserHandle userHandle)186         public void setCurrentUserHandle(UserHandle userHandle) {
187 
188         }
189     }
190 
191     MissedCallNotifierFakeImpl mMissedCallNotifier = new MissedCallNotifierFakeImpl();
192 
193     private class IncomingCallAddedListener extends CallsManagerListenerBase {
194 
195         private final CountDownLatch mCountDownLatch;
196 
IncomingCallAddedListener(CountDownLatch latch)197         public IncomingCallAddedListener(CountDownLatch latch) {
198             mCountDownLatch = latch;
199         }
200 
201         @Override
onCallAdded(com.android.server.telecom.Call call)202         public void onCallAdded(com.android.server.telecom.Call call) {
203             mCountDownLatch.countDown();
204         }
205     }
206 
207     @Mock HeadsetMediaButton mHeadsetMediaButton;
208     @Mock ProximitySensorManager mProximitySensorManager;
209     @Mock InCallWakeLockController mInCallWakeLockController;
210     @Mock AsyncRingtonePlayer mAsyncRingtonePlayer;
211     @Mock IncomingCallNotifier mIncomingCallNotifier;
212     @Mock ClockProxy mClockProxy;
213     @Mock RoleManagerAdapter mRoleManagerAdapter;
214     @Mock ToneGenerator mToneGenerator;
215     @Mock DeviceIdleControllerAdapter mDeviceIdleControllerAdapter;
216 
217     @Mock Ringer.AccessibilityManagerAdapter mAccessibilityManagerAdapter;
218     @Mock
219     BlockedNumbersAdapter mBlockedNumbersAdapter;
220     @Mock
221     CallAudioCommunicationDeviceTracker mCommunicationDeviceTracker;
222     @Mock
223     FeatureFlags mFeatureFlags;
224     @Mock
225     com.android.internal.telephony.flags.FeatureFlags mTelephonyFlags;
226 
227     final ComponentName mInCallServiceComponentNameX =
228             new ComponentName(
229                     "incall-service-package-X",
230                     "incall-service-class-X");
231     private static final int SERVICE_X_UID = 1;
232     final ComponentName mInCallServiceComponentNameY =
233             new ComponentName(
234                     "incall-service-package-Y",
235                     "incall-service-class-Y");
236     private static final int SERVICE_Y_UID = 1;
237     InCallServiceFixture mInCallServiceFixtureX;
238     InCallServiceFixture mInCallServiceFixtureY;
239 
240     final ComponentName mConnectionServiceComponentNameA =
241             new ComponentName(
242                     "connection-service-package-A",
243                     "connection-service-class-A");
244     final ComponentName mConnectionServiceComponentNameB =
245             new ComponentName(
246                     "connection-service-package-B",
247                     "connection-service-class-B");
248 
249     final PhoneAccount mPhoneAccountA0 =
250             PhoneAccount.builder(
251                     new PhoneAccountHandle(
252                             mConnectionServiceComponentNameA,
253                             "id A 0"),
254                     "Phone account service A ID 0")
255                     .addSupportedUriScheme("tel")
256                     .setCapabilities(
257                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
258                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
259                                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
260                     .build();
261     final PhoneAccount mPhoneAccountA1 =
262             PhoneAccount.builder(
263                     new PhoneAccountHandle(
264                             mConnectionServiceComponentNameA,
265                             "id A 1"),
266                     "Phone account service A ID 1")
267                     .addSupportedUriScheme("tel")
268                     .setCapabilities(
269                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
270                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
271                                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
272                     .build();
273     final PhoneAccount mPhoneAccountA2 =
274             PhoneAccount.builder(
275                     new PhoneAccountHandle(
276                             mConnectionServiceComponentNameA,
277                             "id A 2"),
278                     "Phone account service A ID 2")
279                     .addSupportedUriScheme("tel")
280                     .setCapabilities(
281                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
282                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
283                     .build();
284     final PhoneAccount mPhoneAccountSelfManaged =
285             PhoneAccount.builder(
286                     new PhoneAccountHandle(
287                             mConnectionServiceComponentNameA,
288                             "id SM"),
289                     "Phone account service A SM")
290                     .addSupportedUriScheme("tel")
291                     .setCapabilities(
292                             PhoneAccount.CAPABILITY_SELF_MANAGED)
293                     .build();
294     final PhoneAccount mPhoneAccountB0 =
295             PhoneAccount.builder(
296                     new PhoneAccountHandle(
297                             mConnectionServiceComponentNameB,
298                             "id B 0"),
299                     "Phone account service B ID 0")
300                     .addSupportedUriScheme("tel")
301                     .setCapabilities(
302                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
303                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
304                                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
305                     .build();
306     final PhoneAccount mPhoneAccountE0 =
307             PhoneAccount.builder(
308                     new PhoneAccountHandle(
309                             mConnectionServiceComponentNameA,
310                             "id E 0"),
311                     "Phone account service E ID 0")
312                     .addSupportedUriScheme("tel")
313                     .setCapabilities(
314                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
315                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
316                                     PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
317                     .build();
318 
319     final PhoneAccount mPhoneAccountE1 =
320             PhoneAccount.builder(
321                     new PhoneAccountHandle(
322                             mConnectionServiceComponentNameA,
323                             "id E 1"),
324                     "Phone account service E ID 1")
325                     .addSupportedUriScheme("tel")
326                     .setCapabilities(
327                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
328                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
329                                     PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
330                     .build();
331 
332     final PhoneAccount mPhoneAccountMultiUser =
333             PhoneAccount.builder(
334                             new PhoneAccountHandle(
335                                     mConnectionServiceComponentNameA,
336                                     "id MU", UserHandle.of(12)),
337                             "Phone account service MU")
338                     .addSupportedUriScheme("tel")
339                     .setCapabilities(
340                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
341                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
342                                     PhoneAccount.CAPABILITY_VIDEO_CALLING |
343                                     PhoneAccount.CAPABILITY_MULTI_USER)
344                     .build();
345 
346     ConnectionServiceFixture mConnectionServiceFixtureA;
347     ConnectionServiceFixture mConnectionServiceFixtureB;
348     Timeouts.Adapter mTimeoutsAdapter;
349 
350     CallerInfoAsyncQueryFactoryFixture mCallerInfoAsyncQueryFactoryFixture;
351 
352     IAudioService mAudioService;
353 
354     TelecomSystem mTelecomSystem;
355 
356     Context mSpyContext;
357 
358     ConnectionServiceFocusManager mConnectionServiceFocusManager;
359 
360     private HandlerThread mHandlerThread;
361 
362     private int mNumOutgoingCallsMade;
363 
364     class IdPair {
365         final String mConnectionId;
366         final String mCallId;
367 
IdPair(String connectionId, String callId)368         public IdPair(String connectionId, String callId) {
369             this.mConnectionId = connectionId;
370             this.mCallId = callId;
371         }
372     }
373 
374     @Override
setUp()375     public void setUp() throws Exception {
376         super.setUp();
377         mSpyContext = mComponentContextFixture.getTestDouble().getApplicationContext();
378         doReturn(mSpyContext).when(mSpyContext).getApplicationContext();
379         doNothing().when(mSpyContext).sendBroadcastAsUser(any(), any(), any());
380 
381         doReturn(mock(AppOpsManager.class)).when(mSpyContext).getSystemService(AppOpsManager.class);
382         doReturn(mock(BluetoothManager.class)).when(mSpyContext).getSystemService(BluetoothManager.class);
383 
384         mHandlerThread = new HandlerThread("TelecomHandlerThread");
385         mHandlerThread.start();
386 
387         mNumOutgoingCallsMade = 0;
388 
389         doReturn(false).when(mComponentContextFixture.getTelephonyManager())
390                 .isEmergencyNumber(any());
391         doReturn(false).when(mComponentContextFixture.getTelephonyManager())
392                 .isPotentialEmergencyNumber(any());
393 
394         // First set up information about the In-Call services in the mock Context, since
395         // Telecom will search for these as soon as it is instantiated
396         setupInCallServices();
397 
398         // Next, create the TelecomSystem, our system under test
399         setupTelecomSystem();
400         // Need to reset testing tag here
401         Log.setTag(TESTING_TAG);
402 
403         // Finally, register the ConnectionServices with the PhoneAccountRegistrar of the
404         // now-running TelecomSystem
405         setupConnectionServices();
406 
407         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
408     }
409 
410     @Override
tearDown()411     public void tearDown() throws Exception {
412         if (mTelecomSystem != null && mTelecomSystem.getCallsManager() != null) {
413             mTelecomSystem.getCallsManager().waitOnHandlers();
414             LinkedList<HandlerThread> handlerThreads = mTelecomSystem.getCallsManager()
415                     .getGraphHandlerThreads();
416             for (HandlerThread handlerThread : handlerThreads) {
417                 handlerThread.quitSafely();
418             }
419             handlerThreads.clear();
420             mTelecomSystem.getCallsManager().getVoipCallMonitor().stopMonitor();
421         }
422         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
423         waitForHandlerAction(mHandlerThread.getThreadHandler(), TEST_TIMEOUT);
424         // Bring down the threads that are active.
425         mHandlerThread.quit();
426         try {
427             mHandlerThread.join();
428         } catch (InterruptedException e) {
429             // don't do anything
430         }
431 
432         if (mConnectionServiceFocusManager != null) {
433             mConnectionServiceFocusManager.getHandler().removeCallbacksAndMessages(null);
434             waitForHandlerAction(mConnectionServiceFocusManager.getHandler(), TEST_TIMEOUT);
435             mConnectionServiceFocusManager.getHandler().getLooper().quit();
436         }
437 
438         if (mConnectionServiceFixtureA != null) {
439             mConnectionServiceFixtureA.waitForHandlerToClear();
440         }
441 
442         if (mConnectionServiceFixtureA != null) {
443             mConnectionServiceFixtureB.waitForHandlerToClear();
444         }
445 
446         // Forcefully clean all sessions at the end of the test, which will also log any stale
447         // sessions for debugging.
448         Log.getSessionManager().cleanupStaleSessions(0);
449 
450         mTelecomSystem = null;
451         super.tearDown();
452     }
453 
makeConferenceCall( Intent callIntentExtras1, Intent callIntentExtras2)454     protected ParcelableCall makeConferenceCall(
455             Intent callIntentExtras1, Intent callIntentExtras2) throws Exception {
456         IdPair callId1 = startAndMakeActiveOutgoingCallWithExtras("650-555-1212",
457                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras1);
458 
459         IdPair callId2 = startAndMakeActiveOutgoingCallWithExtras("650-555-1213",
460                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, callIntentExtras2);
461 
462         IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
463         inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
464         // Wait for the handler in ConnectionService
465         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
466         ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
467         ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
468         // Check that the two calls end up with a parent in the end
469         assertNotNull(call1.getParentCallId());
470         assertNotNull(call2.getParentCallId());
471         assertEquals(call1.getParentCallId(), call2.getParentCallId());
472 
473         // Check to make sure that the parent call made it to the in-call service
474         String parentCallId = call1.getParentCallId();
475         ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
476         assertEquals(2, conferenceCall.getChildCallIds().size());
477         assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
478         assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
479         return conferenceCall;
480     }
481 
setupTelecomSystem()482     private void setupTelecomSystem() throws Exception {
483         // Remove any cached PhoneAccount xml
484         File phoneAccountFile =
485                 new File(mComponentContextFixture.getTestDouble()
486                         .getApplicationContext().getFilesDir(),
487                         PhoneAccountRegistrar.FILE_NAME);
488         if (phoneAccountFile.exists()) {
489             phoneAccountFile.delete();
490         }
491 
492         // Use actual implementations instead of mocking the interface out.
493         HeadsetMediaButtonFactory headsetMediaButtonFactory =
494                 spy(new HeadsetMediaButtonFactoryF());
495         ProximitySensorManagerFactory proximitySensorManagerFactory =
496                 spy(new ProximitySensorManagerFactoryF());
497         InCallWakeLockControllerFactory inCallWakeLockControllerFactory =
498                 spy(new InCallWakeLockControllerFactoryF());
499         mAudioService = setupAudioService();
500 
501         mCallerInfoAsyncQueryFactoryFixture = new CallerInfoAsyncQueryFactoryFixture();
502 
503         ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory mConnServFMFactory =
504                 requester -> {
505                     mConnectionServiceFocusManager = new ConnectionServiceFocusManager(requester);
506                     return mConnectionServiceFocusManager;
507                 };
508 
509         mTimeoutsAdapter = mock(Timeouts.Adapter.class);
510         when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class)))
511                 .thenReturn(TEST_TIMEOUT / 5L);
512         mIncomingCallNotifier = mock(IncomingCallNotifier.class);
513         mClockProxy = mock(ClockProxy.class);
514         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
515         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
516         when(mRoleManagerAdapter.getCallCompanionApps()).thenReturn(Collections.emptyList());
517         when(mRoleManagerAdapter.getDefaultCallScreeningApp(any(UserHandle.class)))
518                 .thenReturn(null);
519         when(mRoleManagerAdapter.getBTInCallService()).thenReturn(new String[] {"bt_pkg"});
520         when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(false);
521         mTelecomSystem = new TelecomSystem(
522                 mComponentContextFixture.getTestDouble(),
523                 (context, phoneAccountRegistrar, defaultDialerCache, mDeviceIdleControllerAdapter,
524                         mFeatureFlag)
525                         -> mMissedCallNotifier,
526                 mCallerInfoAsyncQueryFactoryFixture.getTestDouble(),
527                 headsetMediaButtonFactory,
528                 proximitySensorManagerFactory,
529                 inCallWakeLockControllerFactory,
530                 () -> mAudioService,
531                 mConnServFMFactory,
532                 mTimeoutsAdapter,
533                 mAsyncRingtonePlayer,
534                 new PhoneNumberUtilsAdapterImpl(),
535                 mIncomingCallNotifier,
536                 (streamType, volume) -> mToneGenerator,
537                 new CallAudioRouteStateMachine.Factory() {
538                     @Override
539                     public CallAudioRouteStateMachine create(
540                             Context context,
541                             CallsManager callsManager,
542                             BluetoothRouteManager bluetoothManager,
543                             WiredHeadsetManager wiredHeadsetManager,
544                             StatusBarNotifier statusBarNotifier,
545                             CallAudioManager.AudioServiceFactory audioServiceFactory,
546                             int earpieceControl,
547                             Executor asyncTaskExecutor,
548                             CallAudioCommunicationDeviceTracker communicationDeviceTracker,
549                             FeatureFlags featureFlags) {
550                         return new CallAudioRouteStateMachine(context,
551                                 callsManager,
552                                 bluetoothManager,
553                                 wiredHeadsetManager,
554                                 statusBarNotifier,
555                                 audioServiceFactory,
556                                 // Force enable an earpiece for the end-to-end tests
557                                 CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED,
558                                 mHandlerThread.getLooper(),
559                                 Runnable::run /* async tasks as now sync for testing! */,
560                                 communicationDeviceTracker,
561                                 featureFlags);
562                     }
563                 },
564                 new CallAudioModeStateMachine.Factory() {
565                     @Override
566                     public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper,
567                             AudioManager am, FeatureFlags featureFlags,
568                             CallAudioCommunicationDeviceTracker callAudioCommunicationDeviceTracker
569                     ) {
570                         return new CallAudioModeStateMachine(systemStateHelper, am,
571                                 mHandlerThread.getLooper(), featureFlags,
572                                 callAudioCommunicationDeviceTracker);
573                     }
574                 },
575                 mClockProxy,
576                 mRoleManagerAdapter,
577                 new ContactsAsyncHelper.Factory() {
578                     @Override
579                     public ContactsAsyncHelper create(
580                             ContactsAsyncHelper.ContentResolverAdapter adapter) {
581                         return new ContactsAsyncHelper(adapter, mHandlerThread.getLooper());
582                     }
583                 }, mDeviceIdleControllerAdapter, mAccessibilityManagerAdapter,
584                 Runnable::run,
585                 Runnable::run,
586                 mBlockedNumbersAdapter,
587                 mFeatureFlags,
588                 mTelephonyFlags);
589 
590         mComponentContextFixture.setTelecomManager(new TelecomManager(
591                 mComponentContextFixture.getTestDouble(),
592                 mTelecomSystem.getTelecomServiceImpl().getBinder()));
593 
594         verify(headsetMediaButtonFactory).create(
595                 eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
596                 any(CallsManager.class),
597                 any(TelecomSystem.SyncRoot.class));
598         verify(proximitySensorManagerFactory).create(
599                 eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
600                 any(CallsManager.class));
601         verify(inCallWakeLockControllerFactory).create(
602                 eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
603                 any(CallsManager.class));
604     }
605 
setupConnectionServices()606     private void setupConnectionServices() throws Exception {
607         mConnectionServiceFixtureA = new ConnectionServiceFixture(mContext);
608         mConnectionServiceFixtureB = new ConnectionServiceFixture(mContext);
609 
610         mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameA,
611                 mConnectionServiceFixtureA.getTestDouble());
612         mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameB,
613                 mConnectionServiceFixtureB.getTestDouble());
614 
615         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0);
616         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1);
617         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA2);
618         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountSelfManaged);
619         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0);
620         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE0);
621         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE1);
622         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountMultiUser);
623 
624         mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount(
625                 mPhoneAccountA0.getAccountHandle(), Process.myUserHandle());
626     }
627 
setupInCallServices()628     private void setupInCallServices() throws Exception {
629         mComponentContextFixture.putResource(
630                 com.android.internal.R.string.config_defaultDialer,
631                 mInCallServiceComponentNameX.getPackageName());
632         mComponentContextFixture.putResource(
633                 com.android.server.telecom.R.string.incall_default_class,
634                 mInCallServiceComponentNameX.getClassName());
635 
636         mInCallServiceFixtureX = new InCallServiceFixture();
637         mInCallServiceFixtureY = new InCallServiceFixture();
638 
639         mComponentContextFixture.addInCallService(mInCallServiceComponentNameX,
640                 mInCallServiceFixtureX.getTestDouble(), SERVICE_X_UID);
641         mComponentContextFixture.addInCallService(mInCallServiceComponentNameY,
642                 mInCallServiceFixtureY.getTestDouble(), SERVICE_Y_UID);
643     }
644 
645     /**
646      * Helper method for setting up the fake audio service.
647      * Calls to the fake audio service need to toggle the return
648      * value of AudioManager#isMicrophoneMute.
649      * @return mock of IAudioService
650      */
setupAudioService()651     private IAudioService setupAudioService() {
652         IAudioService audioService = mock(IAudioService.class);
653 
654         final AudioManager fakeAudioManager =
655                 (AudioManager) mComponentContextFixture.getTestDouble()
656                         .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
657 
658         try {
659             doAnswer(new Answer() {
660                 @Override
661                 public Object answer(InvocationOnMock i) {
662                     Object[] args = i.getArguments();
663                     doReturn(args[0]).when(fakeAudioManager).isMicrophoneMute();
664                     return null;
665                 }
666             }).when(audioService).setMicrophoneMute(any(Boolean.class), any(String.class),
667                     any(Integer.class), nullable(String.class));
668 
669         } catch (android.os.RemoteException e) {
670             // Do nothing, leave the faked microphone state as-is
671         }
672         return audioService;
673     }
674 
startOutgoingPhoneCallWithNoPhoneAccount(String number, ConnectionServiceFixture connectionServiceFixture)675     protected String startOutgoingPhoneCallWithNoPhoneAccount(String number,
676             ConnectionServiceFixture connectionServiceFixture)
677             throws Exception {
678 
679         startOutgoingPhoneCallWaitForBroadcaster(number, null,
680                 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY,
681                 false /*isEmergency*/, null);
682 
683         return mInCallServiceFixtureX.mLatestCallId;
684     }
685 
outgoingCallPhoneAccountSelected(PhoneAccountHandle phoneAccountHandle, int startingNumConnections, int startingNumCalls, ConnectionServiceFixture connectionServiceFixture)686     protected IdPair outgoingCallPhoneAccountSelected(PhoneAccountHandle phoneAccountHandle,
687             int startingNumConnections, int startingNumCalls,
688             ConnectionServiceFixture connectionServiceFixture) throws Exception {
689 
690         IdPair ids = outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
691                 phoneAccountHandle, connectionServiceFixture);
692 
693         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
694         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
695         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
696 
697         connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
698 
699         connectionServiceFixture.sendSetActive(ids.mConnectionId);
700         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
701         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
702 
703         return ids;
704     }
705 
startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser)706     protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
707             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser)
708             throws Exception {
709 
710         return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
711                 initiatingUser, VideoProfile.STATE_AUDIO_ONLY, null);
712     }
713 
startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState, Intent callIntentExtras)714     protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
715             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
716             int videoState, Intent callIntentExtras) throws Exception {
717         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
718         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
719 
720         startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle,
721                 connectionServiceFixture, initiatingUser, videoState, callIntentExtras);
722 
723         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
724                 .createConnectionComplete(anyString(), any());
725 
726         return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
727                 phoneAccountHandle, connectionServiceFixture);
728     }
729 
triggerEmergencyRedial(PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, IdPair emergencyIds)730     protected IdPair triggerEmergencyRedial(PhoneAccountHandle phoneAccountHandle,
731             ConnectionServiceFixture connectionServiceFixture, IdPair emergencyIds)
732             throws Exception {
733         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
734         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
735 
736         // Send the message to disconnect the Emergency call due to an error.
737         // CreateConnectionProcessor should now try the second SIM account
738         connectionServiceFixture.sendSetDisconnected(emergencyIds.mConnectionId,
739                 DisconnectCause.ERROR);
740         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
741         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(
742                 emergencyIds.mCallId).getState());
743         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(
744                 emergencyIds.mCallId).getState());
745 
746         return redialingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
747                 phoneAccountHandle, connectionServiceFixture);
748     }
749 
startOutgoingEmergencyCall(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState)750     protected IdPair startOutgoingEmergencyCall(String number,
751             PhoneAccountHandle phoneAccountHandle,
752             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
753             int videoState) throws Exception {
754         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
755         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
756 
757         doReturn(true).when(mComponentContextFixture.getTelephonyManager())
758                 .isEmergencyNumber(any());
759         doReturn(true).when(mComponentContextFixture.getTelephonyManager())
760                 .isPotentialEmergencyNumber(any());
761 
762         // Call will not use the ordered broadcaster, since it is an Emergency Call
763         startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle,
764                 connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/, null);
765 
766         return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
767                 phoneAccountHandle, connectionServiceFixture);
768     }
769 
startOutgoingPhoneCallWaitForBroadcaster(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState, boolean isEmergency, Intent actionCallIntent)770     protected void startOutgoingPhoneCallWaitForBroadcaster(String number,
771             PhoneAccountHandle phoneAccountHandle,
772             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
773             int videoState, boolean isEmergency, Intent actionCallIntent) throws Exception {
774         reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
775                 mInCallServiceFixtureY.getTestDouble());
776 
777         assertEquals(mInCallServiceFixtureX.mCallById.size(),
778                 mInCallServiceFixtureY.mCallById.size());
779         assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
780                 (mInCallServiceFixtureY.mInCallAdapter != null));
781 
782         mNumOutgoingCallsMade++;
783 
784         boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
785 
786         if (actionCallIntent == null) {
787             actionCallIntent = new Intent();
788         }
789         actionCallIntent.setData(Uri.parse("tel:" + number));
790         actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
791         if(isEmergency) {
792             actionCallIntent.setAction(Intent.ACTION_CALL_EMERGENCY);
793         } else {
794             actionCallIntent.setAction(Intent.ACTION_CALL);
795         }
796         if (phoneAccountHandle != null) {
797             actionCallIntent.putExtra(
798                     TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
799                     phoneAccountHandle);
800         }
801         if (videoState != VideoProfile.STATE_AUDIO_ONLY) {
802             actionCallIntent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
803         }
804 
805         final UserHandle userHandle = initiatingUser;
806         Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext();
807         new UserCallIntentProcessor(localAppContext, userHandle, mFeatureFlags).processIntent(
808                 actionCallIntent, null, false, true /* hasCallAppOp*/, false /* isLocal */);
809         // Wait for handler to start CallerInfo lookup.
810         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
811         // Send the CallerInfo lookup reply.
812         mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach(
813                 CallerInfoAsyncQueryFactoryFixture.Request::reply);
814         if (phoneAccountHandle != null) {
815             mTelecomSystem.getCallsManager().getLatestPostSelectionProcessingFuture().join();
816         }
817         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
818 
819         boolean isSelfManaged = phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle();
820         if (!hasInCallAdapter && !isSelfManaged) {
821             verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
822                     .setInCallAdapter(
823                             any(IInCallAdapter.class));
824             verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
825                     .setInCallAdapter(
826                             any(IInCallAdapter.class));
827         }
828     }
829 
startOutgoingPhoneCallPendingCreateConnection(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState, Intent callIntentExtras)830     protected String startOutgoingPhoneCallPendingCreateConnection(String number,
831             PhoneAccountHandle phoneAccountHandle,
832             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
833             int videoState, Intent callIntentExtras) throws Exception {
834         startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle,
835                 connectionServiceFixture, initiatingUser,
836                 videoState, false /*isEmergency*/, callIntentExtras);
837         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
838 
839         verifyAndProcessOutgoingCallBroadcast(phoneAccountHandle);
840         return mInCallServiceFixtureX.mLatestCallId;
841     }
842 
verifyAndProcessOutgoingCallBroadcast(PhoneAccountHandle phoneAccountHandle)843     protected void verifyAndProcessOutgoingCallBroadcast(PhoneAccountHandle phoneAccountHandle) {
844         ArgumentCaptor<Intent> newOutgoingCallIntent =
845                 ArgumentCaptor.forClass(Intent.class);
846         ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver =
847                 ArgumentCaptor.forClass(BroadcastReceiver.class);
848 
849         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
850             verify(mComponentContextFixture.getTestDouble().getApplicationContext(),
851                     times(mNumOutgoingCallsMade))
852                     .sendOrderedBroadcastAsUser(
853                             newOutgoingCallIntent.capture(),
854                             any(UserHandle.class),
855                             anyString(),
856                             anyInt(),
857                             any(Bundle.class),
858                             newOutgoingCallReceiver.capture(),
859                             nullable(Handler.class),
860                             anyInt(),
861                             anyString(),
862                             nullable(Bundle.class));
863             // Pass on the new outgoing call Intent
864             // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive()
865             newOutgoingCallReceiver.getValue().setPendingResult(
866                     new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0));
867             newOutgoingCallReceiver.getValue().setResultData(
868                     newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER));
869             newOutgoingCallReceiver.getValue().onReceive(mComponentContextFixture.getTestDouble(),
870                     newOutgoingCallIntent.getValue());
871         }
872 
873     }
874 
875     // When Telecom is redialing due to an error, we need to make sure the number of connections
876     // increase, but not the number of Calls in the InCallService.
redialingCallCreateConnectionComplete(int startingNumConnections, int startingNumCalls, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)877     protected IdPair redialingCallCreateConnectionComplete(int startingNumConnections,
878             int startingNumCalls, PhoneAccountHandle phoneAccountHandle,
879             ConnectionServiceFixture connectionServiceFixture) throws Exception {
880 
881         assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
882 
883         verify(connectionServiceFixture.getTestDouble())
884                 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
885                         eq(false)/*isIncoming*/, anyBoolean(), any());
886         // Wait for handleCreateConnectionComplete
887         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
888 
889         // Make sure the number of registered InCallService Calls stays the same.
890         assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size());
891         assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size());
892 
893         assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
894 
895         return new IdPair(connectionServiceFixture.mLatestConnectionId,
896                 mInCallServiceFixtureX.mLatestCallId);
897     }
898 
outgoingCallCreateConnectionComplete(int startingNumConnections, int startingNumCalls, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)899     protected IdPair outgoingCallCreateConnectionComplete(int startingNumConnections,
900             int startingNumCalls, PhoneAccountHandle phoneAccountHandle,
901             ConnectionServiceFixture connectionServiceFixture) throws Exception {
902 
903         // Wait for the focus tracker.
904         waitForHandlerAction(mTelecomSystem.getCallsManager()
905                 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
906 
907         verify(connectionServiceFixture.getTestDouble())
908                 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
909                         eq(false)/*isIncoming*/, anyBoolean(), any());
910         // Wait for handleCreateConnectionComplete
911         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
912         assertEquals(startingNumConnections + 1,
913                 connectionServiceFixture.mConnectionById.size());
914 
915         // Wait for the callback in ConnectionService#onAdapterAttached to execute.
916         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
917 
918         // Ensure callback to CS on successful creation happened.
919         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
920                 .createConnectionComplete(anyString(), any());
921 
922         if (phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle()) {
923             assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size());
924             assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size());
925         } else {
926             assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
927             assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
928         }
929 
930         assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
931 
932         return new IdPair(connectionServiceFixture.mLatestConnectionId,
933                 mInCallServiceFixtureX.mLatestCallId);
934     }
935 
startIncomingPhoneCall( String number, PhoneAccountHandle phoneAccountHandle, final ConnectionServiceFixture connectionServiceFixture)936     protected IdPair startIncomingPhoneCall(
937             String number,
938             PhoneAccountHandle phoneAccountHandle,
939             final ConnectionServiceFixture connectionServiceFixture) throws Exception {
940         return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
941                 connectionServiceFixture, null);
942     }
943 
startIncomingPhoneCallWithExtras( String number, PhoneAccountHandle phoneAccountHandle, final ConnectionServiceFixture connectionServiceFixture, Bundle extras)944     protected IdPair startIncomingPhoneCallWithExtras(
945             String number,
946             PhoneAccountHandle phoneAccountHandle,
947             final ConnectionServiceFixture connectionServiceFixture,
948             Bundle extras) throws Exception {
949         return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
950                 connectionServiceFixture, extras);
951     }
952 
startIncomingPhoneCall( String number, PhoneAccountHandle phoneAccountHandle, int videoState, final ConnectionServiceFixture connectionServiceFixture, Bundle extras)953     protected IdPair startIncomingPhoneCall(
954             String number,
955             PhoneAccountHandle phoneAccountHandle,
956             int videoState,
957             final ConnectionServiceFixture connectionServiceFixture,
958             Bundle extras) throws Exception {
959         reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
960                 mInCallServiceFixtureY.getTestDouble());
961 
962         assertEquals(mInCallServiceFixtureX.mCallById.size(),
963                 mInCallServiceFixtureY.mCallById.size());
964         assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
965                 (mInCallServiceFixtureY.mInCallAdapter != null));
966         final int startingNumConnections = connectionServiceFixture.mConnectionById.size();
967         final int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
968         boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
969         connectionServiceFixture.mConnectionServiceDelegate.mVideoState = videoState;
970         CountDownLatch incomingCallAddedLatch = new CountDownLatch(1);
971         IncomingCallAddedListener callAddedListener =
972                 new IncomingCallAddedListener(incomingCallAddedLatch);
973         mTelecomSystem.getCallsManager().addListener(callAddedListener);
974 
975         if (extras == null) {
976             extras = new Bundle();
977         }
978         extras.putParcelable(
979                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
980                 Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
981         mTelecomSystem.getTelecomServiceImpl().getBinder()
982                 .addNewIncomingCall(phoneAccountHandle, extras, CALLING_PACKAGE);
983 
984         verify(connectionServiceFixture.getTestDouble())
985                 .createConnection(any(PhoneAccountHandle.class), anyString(),
986                         any(ConnectionRequest.class), eq(true), eq(false), any());
987 
988         // Wait for the handler to start the CallerInfo lookup
989         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
990 
991         // Wait a few more times to address flakiness due to timing issues.
992         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
993         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
994 
995         // Ensure callback to CS on successful creation happened.
996 
997         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
998                 .createConnectionComplete(anyString(), any());
999 
1000         // Process the CallerInfo lookup reply
1001         mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach(
1002                 CallerInfoAsyncQueryFactoryFixture.Request::reply);
1003 
1004         //Wait for/Verify call blocking happened asynchronously
1005         incomingCallAddedLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
1006 
1007         // For the case of incoming calls, Telecom connecting the InCall services and adding the
1008         // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call
1009         // is added, future interactions as triggered by the ConnectionService, through the various
1010         // test fixtures, will be synchronous.
1011 
1012         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1013             if (!hasInCallAdapter) {
1014                 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
1015                         .setInCallAdapter(any(IInCallAdapter.class));
1016                 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
1017                         .setInCallAdapter(any(IInCallAdapter.class));
1018 
1019                 // Give the InCallService time to respond
1020                 assertTrueWithTimeout(new Predicate<Void>() {
1021                     @Override
1022                     public boolean apply(Void v) {
1023                         return mInCallServiceFixtureX.mInCallAdapter != null;
1024                     }
1025                 });
1026 
1027                 assertTrueWithTimeout(new Predicate<Void>() {
1028                     @Override
1029                     public boolean apply(Void v) {
1030                         return mInCallServiceFixtureY.mInCallAdapter != null;
1031                     }
1032                 });
1033 
1034                 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
1035                         .addCall(any(ParcelableCall.class));
1036                 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
1037                         .addCall(any(ParcelableCall.class));
1038 
1039                 // Give the InCallService time to respond
1040             }
1041 
1042             assertTrueWithTimeout(new Predicate<Void>() {
1043                 @Override
1044                 public boolean apply(Void v) {
1045                     return startingNumConnections + 1 ==
1046                             connectionServiceFixture.mConnectionById.size();
1047                 }
1048             });
1049 
1050             mInCallServiceFixtureX.waitUntilNumCalls(startingNumCalls + 1);
1051             mInCallServiceFixtureY.waitUntilNumCalls(startingNumCalls + 1);
1052             assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
1053             assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
1054 
1055             assertEquals(mInCallServiceFixtureX.mLatestCallId,
1056                     mInCallServiceFixtureY.mLatestCallId);
1057         }
1058 
1059         return new IdPair(connectionServiceFixture.mLatestConnectionId,
1060                 mInCallServiceFixtureX.mLatestCallId);
1061     }
1062 
startAndMakeActiveOutgoingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1063     protected IdPair startAndMakeActiveOutgoingCall(
1064             String number,
1065             PhoneAccountHandle phoneAccountHandle,
1066             ConnectionServiceFixture connectionServiceFixture) throws Exception {
1067         return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
1068                 VideoProfile.STATE_AUDIO_ONLY, null);
1069     }
1070 
startAndMakeActiveOutgoingCallWithExtras( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, Intent callIntentExtras)1071     protected IdPair startAndMakeActiveOutgoingCallWithExtras(
1072             String number,
1073             PhoneAccountHandle phoneAccountHandle,
1074             ConnectionServiceFixture connectionServiceFixture,
1075             Intent callIntentExtras) throws Exception {
1076         return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
1077                 VideoProfile.STATE_AUDIO_ONLY, callIntentExtras);
1078     }
1079 
1080     // A simple outgoing call, verifying that the appropriate connection service is contacted,
1081     // the proper lifecycle is followed, and both In-Call Services are updated correctly.
startAndMakeActiveOutgoingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, int videoState, Intent callIntentExtras)1082     protected IdPair startAndMakeActiveOutgoingCall(
1083             String number,
1084             PhoneAccountHandle phoneAccountHandle,
1085             ConnectionServiceFixture connectionServiceFixture, int videoState,
1086             Intent callIntentExtras) throws Exception {
1087         IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
1088                 Process.myUserHandle(), videoState, callIntentExtras);
1089 
1090         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
1091         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1092             assertEquals(Call.STATE_DIALING,
1093                     mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1094             assertEquals(Call.STATE_DIALING,
1095                     mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1096         }
1097 
1098         connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
1099 
1100         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
1101         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
1102         connectionServiceFixture.sendSetActive(ids.mConnectionId);
1103         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1104             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1105             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1106 
1107             if ((mInCallServiceFixtureX.getCall(ids.mCallId).getProperties() &
1108                     Call.Details.PROPERTY_IS_EXTERNAL_CALL) == 0) {
1109                 // Test the PhoneStateBroadcaster functionality if the call is not external.
1110                 verify(mContext.getSystemService(TelephonyRegistryManager.class),
1111                         timeout(TEST_TIMEOUT).atLeastOnce())
1112                         .notifyCallStateChangedForAllSubscriptions(
1113                                 eq(TelephonyManager.CALL_STATE_OFFHOOK),
1114                                 nullable(String.class));
1115             }
1116         }
1117         return ids;
1118     }
1119 
startAndMakeActiveIncomingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1120     protected IdPair startAndMakeActiveIncomingCall(
1121             String number,
1122             PhoneAccountHandle phoneAccountHandle,
1123             ConnectionServiceFixture connectionServiceFixture) throws Exception {
1124         return startAndMakeActiveIncomingCall(number, phoneAccountHandle, connectionServiceFixture,
1125                 VideoProfile.STATE_AUDIO_ONLY);
1126     }
1127 
1128     // A simple incoming call, similar in scope to the previous test
startAndMakeActiveIncomingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, int videoState)1129     protected IdPair startAndMakeActiveIncomingCall(
1130             String number,
1131             PhoneAccountHandle phoneAccountHandle,
1132             ConnectionServiceFixture connectionServiceFixture,
1133             int videoState) throws Exception {
1134         IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
1135 
1136         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1137             assertEquals(Call.STATE_RINGING,
1138                     mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1139             assertEquals(Call.STATE_RINGING,
1140                     mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1141 
1142             mInCallServiceFixtureX.mInCallAdapter
1143                     .answerCall(ids.mCallId, videoState);
1144             // Wait on the CS focus manager handler
1145             waitForHandlerAction(mTelecomSystem.getCallsManager()
1146                     .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
1147 
1148             if (!VideoProfile.isVideo(videoState)) {
1149                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
1150                         .answer(eq(ids.mConnectionId), any());
1151             } else {
1152                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
1153                         .answerVideo(eq(ids.mConnectionId), eq(videoState), any());
1154             }
1155         }
1156 
1157         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
1158         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
1159         connectionServiceFixture.sendSetActive(ids.mConnectionId);
1160 
1161         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1162             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1163             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1164 
1165             if ((mInCallServiceFixtureX.getCall(ids.mCallId).getProperties() &
1166                     Call.Details.PROPERTY_IS_EXTERNAL_CALL) == 0) {
1167                 // Test the PhoneStateBroadcaster functionality if the call is not external.
1168                 verify(mContext.getSystemService(TelephonyRegistryManager.class),
1169                         timeout(TEST_TIMEOUT).atLeastOnce())
1170                         .notifyCallStateChangedForAllSubscriptions(
1171                                 eq(TelephonyManager.CALL_STATE_OFFHOOK),
1172                                 nullable(String.class));
1173             }
1174         }
1175         return ids;
1176     }
1177 
startAndMakeDialingEmergencyCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1178     protected IdPair startAndMakeDialingEmergencyCall(
1179             String number,
1180             PhoneAccountHandle phoneAccountHandle,
1181             ConnectionServiceFixture connectionServiceFixture) throws Exception {
1182         IdPair ids = startOutgoingEmergencyCall(number, phoneAccountHandle,
1183                 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY);
1184 
1185         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
1186         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1187         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1188 
1189         return ids;
1190     }
1191 
startAndMakeDialingOutgoingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1192     protected IdPair startAndMakeDialingOutgoingCall(
1193             String number,
1194             PhoneAccountHandle phoneAccountHandle,
1195             ConnectionServiceFixture connectionServiceFixture) throws Exception {
1196         IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
1197                 Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY, null);
1198 
1199         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
1200         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1201             assertEquals(Call.STATE_DIALING,
1202                     mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1203             assertEquals(Call.STATE_DIALING,
1204                     mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1205         }
1206 
1207         return ids;
1208     }
1209 
startAndMakeRingingIncomingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1210     protected IdPair startAndMakeRingingIncomingCall(
1211             String number,
1212             PhoneAccountHandle phoneAccountHandle,
1213             ConnectionServiceFixture connectionServiceFixture) throws Exception {
1214         IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
1215 
1216         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
1217             assertEquals(Call.STATE_RINGING,
1218                     mInCallServiceFixtureX.getCall(ids.mCallId).getState());
1219             assertEquals(Call.STATE_RINGING,
1220                     mInCallServiceFixtureY.getCall(ids.mCallId).getState());
1221 
1222             mInCallServiceFixtureX.mInCallAdapter
1223                     .answerCall(ids.mCallId, VideoProfile.STATE_AUDIO_ONLY);
1224 
1225             waitForHandlerAction(mTelecomSystem.getCallsManager()
1226                     .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
1227 
1228             if (!VideoProfile.isVideo(VideoProfile.STATE_AUDIO_ONLY)) {
1229                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
1230                         .answer(eq(ids.mConnectionId), any());
1231             } else {
1232                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
1233                         .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_AUDIO_ONLY),
1234                                 any());
1235             }
1236         }
1237         return ids;
1238     }
1239 
assertTrueWithTimeout(Predicate<Void> predicate)1240     protected static void assertTrueWithTimeout(Predicate<Void> predicate) {
1241         int elapsed = 0;
1242         while (elapsed < TEST_TIMEOUT) {
1243             if (predicate.apply(null)) {
1244                 return;
1245             } else {
1246                 try {
1247                     Thread.sleep(TEST_POLL_INTERVAL);
1248                     elapsed += TEST_POLL_INTERVAL;
1249                 } catch (InterruptedException e) {
1250                     fail(e.toString());
1251                 }
1252             }
1253         }
1254         fail("Timeout in assertTrueWithTimeout");
1255     }
1256 }
1257