Home | History | Annotate | Download | only in tests
      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.isNotNull;
     25 import static org.mockito.ArgumentMatchers.nullable;
     26 import static org.mockito.Matchers.any;
     27 import static org.mockito.Matchers.anyBoolean;
     28 import static org.mockito.Matchers.anyInt;
     29 import static org.mockito.Matchers.anyString;
     30 import static org.mockito.Matchers.eq;
     31 import static org.mockito.Matchers.isNull;
     32 import static org.mockito.Mockito.doAnswer;
     33 import static org.mockito.Mockito.doNothing;
     34 import static org.mockito.Mockito.doReturn;
     35 import static org.mockito.Mockito.mock;
     36 import static org.mockito.Mockito.reset;
     37 import static org.mockito.Mockito.spy;
     38 import static org.mockito.Mockito.timeout;
     39 import static org.mockito.Mockito.times;
     40 import static org.mockito.Mockito.verify;
     41 import static org.mockito.Mockito.when;
     42 
     43 import android.content.BroadcastReceiver;
     44 import android.content.ComponentName;
     45 import android.content.ContentResolver;
     46 import android.content.Context;
     47 import android.content.IContentProvider;
     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.Looper;
     56 import android.os.Process;
     57 import android.os.UserHandle;
     58 import android.provider.BlockedNumberContract;
     59 import android.telecom.Call;
     60 import android.telecom.ConnectionRequest;
     61 import android.telecom.DisconnectCause;
     62 import android.telecom.ParcelableCall;
     63 import android.telecom.PhoneAccount;
     64 import android.telecom.PhoneAccountHandle;
     65 import android.telecom.TelecomManager;
     66 import android.telecom.VideoProfile;
     67 
     68 import com.android.internal.telecom.IInCallAdapter;
     69 import com.android.server.telecom.AsyncRingtonePlayer;
     70 import com.android.server.telecom.BluetoothPhoneServiceImpl;
     71 import com.android.server.telecom.CallAudioManager;
     72 import com.android.server.telecom.CallerInfoLookupHelper;
     73 import com.android.server.telecom.CallsManager;
     74 import com.android.server.telecom.CallsManagerListenerBase;
     75 import com.android.server.telecom.ClockProxy;
     76 import com.android.server.telecom.ConnectionServiceFocusManager;
     77 import com.android.server.telecom.DefaultDialerCache;
     78 import com.android.server.telecom.HeadsetMediaButton;
     79 import com.android.server.telecom.HeadsetMediaButtonFactory;
     80 import com.android.server.telecom.InCallWakeLockController;
     81 import com.android.server.telecom.InCallWakeLockControllerFactory;
     82 import com.android.server.telecom.MissedCallNotifier;
     83 import com.android.server.telecom.PhoneAccountRegistrar;
     84 import com.android.server.telecom.PhoneNumberUtilsAdapter;
     85 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
     86 import com.android.server.telecom.ProximitySensorManager;
     87 import com.android.server.telecom.ProximitySensorManagerFactory;
     88 import com.android.server.telecom.TelecomSystem;
     89 import com.android.server.telecom.Timeouts;
     90 import com.android.server.telecom.components.UserCallIntentProcessor;
     91 import com.android.server.telecom.ui.IncomingCallNotifier;
     92 import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
     93 
     94 import com.google.common.base.Predicate;
     95 
     96 import org.mockito.ArgumentCaptor;
     97 import org.mockito.Mock;
     98 import org.mockito.invocation.InvocationOnMock;
     99 import org.mockito.stubbing.Answer;
    100 
    101 import java.util.ArrayList;
    102 import java.util.List;
    103 import java.util.concurrent.CountDownLatch;
    104 import java.util.concurrent.TimeUnit;
    105 
    106 /**
    107  * Implements mocks and functionality required to implement telecom system tests.
    108  */
    109 public class TelecomSystemTest extends TelecomTestCase {
    110 
    111     static final int TEST_POLL_INTERVAL = 10;  // milliseconds
    112     static final int TEST_TIMEOUT = 1000;  // milliseconds
    113 
    114     // Purposely keep the connect time (which is wall clock) and elapsed time (which is time since
    115     // boot) different to test that wall clock time operations and elapsed time operations perform
    116     // as they individually should.
    117     static final long TEST_CREATE_TIME = 100;
    118     static final long TEST_CREATE_ELAPSED_TIME = 200;
    119     static final long TEST_CONNECT_TIME = 1000;
    120     static final long TEST_CONNECT_ELAPSED_TIME = 2000;
    121     static final long TEST_DISCONNECT_TIME = 8000;
    122     static final long TEST_DISCONNECT_ELAPSED_TIME = 4000;
    123 
    124     public class HeadsetMediaButtonFactoryF implements HeadsetMediaButtonFactory  {
    125         @Override
    126         public HeadsetMediaButton create(Context context, CallsManager callsManager,
    127                 TelecomSystem.SyncRoot lock) {
    128             return mHeadsetMediaButton;
    129         }
    130     }
    131 
    132     public class ProximitySensorManagerFactoryF implements ProximitySensorManagerFactory {
    133         @Override
    134         public ProximitySensorManager create(Context context, CallsManager callsManager) {
    135             return mProximitySensorManager;
    136         }
    137     }
    138 
    139     public class InCallWakeLockControllerFactoryF implements InCallWakeLockControllerFactory {
    140         @Override
    141         public InCallWakeLockController create(Context context, CallsManager callsManager) {
    142             return mInCallWakeLockController;
    143         }
    144     }
    145 
    146     public static class MissedCallNotifierFakeImpl extends CallsManagerListenerBase
    147             implements MissedCallNotifier {
    148         List<CallInfo> missedCallsNotified = new ArrayList<>();
    149 
    150         @Override
    151         public void clearMissedCalls(UserHandle userHandle) {
    152 
    153         }
    154 
    155         @Override
    156         public void showMissedCallNotification(CallInfo call) {
    157             missedCallsNotified.add(call);
    158         }
    159 
    160         @Override
    161         public void reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper,
    162                 CallInfoFactory callInfoFactory) { }
    163 
    164         @Override
    165         public void reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper,
    166                 CallInfoFactory callInfoFactory, UserHandle userHandle) { }
    167 
    168         @Override
    169         public void setCurrentUserHandle(UserHandle userHandle) {
    170 
    171         }
    172     }
    173 
    174     MissedCallNotifierFakeImpl mMissedCallNotifier = new MissedCallNotifierFakeImpl();
    175     private class EmergencyNumberUtilsAdapter extends PhoneNumberUtilsAdapterImpl {
    176 
    177         @Override
    178         public boolean isLocalEmergencyNumber(Context context, String number) {
    179             return mIsEmergencyCall;
    180         }
    181 
    182         @Override
    183         public boolean isPotentialLocalEmergencyNumber(Context context, String number) {
    184             return mIsEmergencyCall;
    185         }
    186     }
    187 
    188     private class IncomingCallAddedListener extends CallsManagerListenerBase {
    189 
    190         private final CountDownLatch mCountDownLatch;
    191 
    192         public IncomingCallAddedListener(CountDownLatch latch) {
    193             mCountDownLatch = latch;
    194         }
    195 
    196         @Override
    197         public void onCallAdded(com.android.server.telecom.Call call) {
    198             mCountDownLatch.countDown();
    199         }
    200     }
    201 
    202     PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter = new EmergencyNumberUtilsAdapter();
    203 
    204     @Mock HeadsetMediaButton mHeadsetMediaButton;
    205     @Mock ProximitySensorManager mProximitySensorManager;
    206     @Mock InCallWakeLockController mInCallWakeLockController;
    207     @Mock BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
    208     @Mock AsyncRingtonePlayer mAsyncRingtonePlayer;
    209     @Mock IncomingCallNotifier mIncomingCallNotifier;
    210     @Mock ClockProxy mClockProxy;
    211 
    212     final ComponentName mInCallServiceComponentNameX =
    213             new ComponentName(
    214                     "incall-service-package-X",
    215                     "incall-service-class-X");
    216     final ComponentName mInCallServiceComponentNameY =
    217             new ComponentName(
    218                     "incall-service-package-Y",
    219                     "incall-service-class-Y");
    220 
    221     InCallServiceFixture mInCallServiceFixtureX;
    222     InCallServiceFixture mInCallServiceFixtureY;
    223 
    224     final ComponentName mConnectionServiceComponentNameA =
    225             new ComponentName(
    226                     "connection-service-package-A",
    227                     "connection-service-class-A");
    228     final ComponentName mConnectionServiceComponentNameB =
    229             new ComponentName(
    230                     "connection-service-package-B",
    231                     "connection-service-class-B");
    232 
    233     final PhoneAccount mPhoneAccountA0 =
    234             PhoneAccount.builder(
    235                     new PhoneAccountHandle(
    236                             mConnectionServiceComponentNameA,
    237                             "id A 0"),
    238                     "Phone account service A ID 0")
    239                     .addSupportedUriScheme("tel")
    240                     .setCapabilities(
    241                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
    242                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    243                                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
    244                     .build();
    245     final PhoneAccount mPhoneAccountA1 =
    246             PhoneAccount.builder(
    247                     new PhoneAccountHandle(
    248                             mConnectionServiceComponentNameA,
    249                             "id A 1"),
    250                     "Phone account service A ID 1")
    251                     .addSupportedUriScheme("tel")
    252                     .setCapabilities(
    253                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
    254                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    255                                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
    256                     .build();
    257     final PhoneAccount mPhoneAccountA2 =
    258             PhoneAccount.builder(
    259                     new PhoneAccountHandle(
    260                             mConnectionServiceComponentNameA,
    261                             "id A 2"),
    262                     "Phone account service A ID 2")
    263                     .addSupportedUriScheme("tel")
    264                     .setCapabilities(
    265                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
    266                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
    267                     .build();
    268     final PhoneAccount mPhoneAccountSelfManaged =
    269             PhoneAccount.builder(
    270                     new PhoneAccountHandle(
    271                             mConnectionServiceComponentNameA,
    272                             "id SM"),
    273                     "Phone account service A SM")
    274                     .addSupportedUriScheme("tel")
    275                     .setCapabilities(
    276                             PhoneAccount.CAPABILITY_SELF_MANAGED)
    277                     .build();
    278     final PhoneAccount mPhoneAccountB0 =
    279             PhoneAccount.builder(
    280                     new PhoneAccountHandle(
    281                             mConnectionServiceComponentNameB,
    282                             "id B 0"),
    283                     "Phone account service B ID 0")
    284                     .addSupportedUriScheme("tel")
    285                     .setCapabilities(
    286                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
    287                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    288                                     PhoneAccount.CAPABILITY_VIDEO_CALLING)
    289                     .build();
    290     final PhoneAccount mPhoneAccountE0 =
    291             PhoneAccount.builder(
    292                     new PhoneAccountHandle(
    293                             mConnectionServiceComponentNameA,
    294                             "id E 0"),
    295                     "Phone account service E ID 0")
    296                     .addSupportedUriScheme("tel")
    297                     .setCapabilities(
    298                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
    299                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    300                                     PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
    301                     .build();
    302 
    303     final PhoneAccount mPhoneAccountE1 =
    304             PhoneAccount.builder(
    305                     new PhoneAccountHandle(
    306                             mConnectionServiceComponentNameA,
    307                             "id E 1"),
    308                     "Phone account service E ID 1")
    309                     .addSupportedUriScheme("tel")
    310                     .setCapabilities(
    311                             PhoneAccount.CAPABILITY_CALL_PROVIDER |
    312                                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
    313                                     PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
    314                     .build();
    315 
    316     ConnectionServiceFixture mConnectionServiceFixtureA;
    317     ConnectionServiceFixture mConnectionServiceFixtureB;
    318     Timeouts.Adapter mTimeoutsAdapter;
    319 
    320     CallerInfoAsyncQueryFactoryFixture mCallerInfoAsyncQueryFactoryFixture;
    321 
    322     IAudioService mAudioService;
    323 
    324     TelecomSystem mTelecomSystem;
    325 
    326     Context mSpyContext;
    327 
    328     private int mNumOutgoingCallsMade;
    329 
    330     private boolean mIsEmergencyCall;
    331 
    332     class IdPair {
    333         final String mConnectionId;
    334         final String mCallId;
    335 
    336         public IdPair(String connectionId, String callId) {
    337             this.mConnectionId = connectionId;
    338             this.mCallId = callId;
    339         }
    340     }
    341 
    342     @Override
    343     public void setUp() throws Exception {
    344         super.setUp();
    345         mSpyContext = mComponentContextFixture.getTestDouble().getApplicationContext();
    346         doReturn(mSpyContext).when(mSpyContext).getApplicationContext();
    347         doNothing().when(mSpyContext).sendBroadcastAsUser(any(), any(), any());
    348 
    349         mNumOutgoingCallsMade = 0;
    350 
    351         mIsEmergencyCall = false;
    352 
    353         // First set up information about the In-Call services in the mock Context, since
    354         // Telecom will search for these as soon as it is instantiated
    355         setupInCallServices();
    356 
    357         // Next, create the TelecomSystem, our system under test
    358         setupTelecomSystem();
    359 
    360         // Finally, register the ConnectionServices with the PhoneAccountRegistrar of the
    361         // now-running TelecomSystem
    362         setupConnectionServices();
    363 
    364         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    365     }
    366 
    367     @Override
    368     public void tearDown() throws Exception {
    369         mTelecomSystem.getCallsManager().getCallAudioManager()
    370                 .getCallAudioRouteStateMachine().quitNow();
    371         mTelecomSystem.getCallsManager().getCallAudioManager()
    372                 .getCallAudioModeStateMachine().quitNow();
    373         mTelecomSystem = null;
    374         super.tearDown();
    375     }
    376 
    377     protected ParcelableCall makeConferenceCall() throws Exception {
    378         IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212",
    379                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
    380 
    381         IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213",
    382                 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
    383 
    384         IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter();
    385         inCallAdapter.conference(callId1.mCallId, callId2.mCallId);
    386         // Wait for wacky non-deterministic behavior
    387         Thread.sleep(200);
    388         ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId);
    389         ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId);
    390         // Check that the two calls end up with a parent in the end
    391         assertNotNull(call1.getParentCallId());
    392         assertNotNull(call2.getParentCallId());
    393         assertEquals(call1.getParentCallId(), call2.getParentCallId());
    394 
    395         // Check to make sure that the parent call made it to the in-call service
    396         String parentCallId = call1.getParentCallId();
    397         ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId);
    398         assertEquals(2, conferenceCall.getChildCallIds().size());
    399         assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId));
    400         assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId));
    401         return conferenceCall;
    402     }
    403 
    404     private void setupTelecomSystem() throws Exception {
    405         // Use actual implementations instead of mocking the interface out.
    406         HeadsetMediaButtonFactory headsetMediaButtonFactory =
    407                 spy(new HeadsetMediaButtonFactoryF());
    408         ProximitySensorManagerFactory proximitySensorManagerFactory =
    409                 spy(new ProximitySensorManagerFactoryF());
    410         InCallWakeLockControllerFactory inCallWakeLockControllerFactory =
    411                 spy(new InCallWakeLockControllerFactoryF());
    412         mAudioService = setupAudioService();
    413 
    414         mCallerInfoAsyncQueryFactoryFixture = new CallerInfoAsyncQueryFactoryFixture();
    415 
    416         mTimeoutsAdapter = mock(Timeouts.Adapter.class);
    417         when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class)))
    418                 .thenReturn(TEST_TIMEOUT / 5L);
    419         mIncomingCallNotifier = mock(IncomingCallNotifier.class);
    420         mClockProxy = mock(ClockProxy.class);
    421         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
    422         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
    423         mTelecomSystem = new TelecomSystem(
    424                 mComponentContextFixture.getTestDouble(),
    425                 new MissedCallNotifierImplFactory() {
    426                     @Override
    427                     public MissedCallNotifier makeMissedCallNotifierImpl(Context context,
    428                             PhoneAccountRegistrar phoneAccountRegistrar,
    429                             DefaultDialerCache defaultDialerCache) {
    430                         return mMissedCallNotifier;
    431                     }
    432                 },
    433                 mCallerInfoAsyncQueryFactoryFixture.getTestDouble(),
    434                 headsetMediaButtonFactory,
    435                 proximitySensorManagerFactory,
    436                 inCallWakeLockControllerFactory,
    437                 new CallAudioManager.AudioServiceFactory() {
    438                     @Override
    439                     public IAudioService getAudioService() {
    440                         return mAudioService;
    441                     }
    442                 },
    443                 new BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory() {
    444                     @Override
    445                     public BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl(Context context,
    446                             TelecomSystem.SyncRoot lock, CallsManager callsManager,
    447                             PhoneAccountRegistrar phoneAccountRegistrar) {
    448                         return mBluetoothPhoneServiceImpl;
    449                     }
    450                 },
    451                 new ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory() {
    452                     @Override
    453                     public ConnectionServiceFocusManager create(
    454                             ConnectionServiceFocusManager.CallsManagerRequester requester,
    455                             Looper looper) {
    456                         return new ConnectionServiceFocusManager(requester, looper);
    457                     }
    458                 },
    459                 mTimeoutsAdapter,
    460                 mAsyncRingtonePlayer,
    461                 mPhoneNumberUtilsAdapter,
    462                 mIncomingCallNotifier,
    463                 (streamType, volume) -> mock(ToneGenerator.class),
    464                 mClockProxy);
    465 
    466         mComponentContextFixture.setTelecomManager(new TelecomManager(
    467                 mComponentContextFixture.getTestDouble(),
    468                 mTelecomSystem.getTelecomServiceImpl().getBinder()));
    469 
    470         verify(headsetMediaButtonFactory).create(
    471                 eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
    472                 any(CallsManager.class),
    473                 any(TelecomSystem.SyncRoot.class));
    474         verify(proximitySensorManagerFactory).create(
    475                 eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
    476                 any(CallsManager.class));
    477         verify(inCallWakeLockControllerFactory).create(
    478                 eq(mComponentContextFixture.getTestDouble().getApplicationContext()),
    479                 any(CallsManager.class));
    480     }
    481 
    482     private void setupConnectionServices() throws Exception {
    483         mConnectionServiceFixtureA = new ConnectionServiceFixture(mContext);
    484         mConnectionServiceFixtureB = new ConnectionServiceFixture(mContext);
    485 
    486         mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameA,
    487                 mConnectionServiceFixtureA.getTestDouble());
    488         mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameB,
    489                 mConnectionServiceFixtureB.getTestDouble());
    490 
    491         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0);
    492         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1);
    493         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA2);
    494         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountSelfManaged);
    495         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0);
    496         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE0);
    497         mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE1);
    498 
    499         mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount(
    500                 mPhoneAccountA0.getAccountHandle(), Process.myUserHandle());
    501     }
    502 
    503     private void setupInCallServices() throws Exception {
    504         mComponentContextFixture.putResource(
    505                 com.android.server.telecom.R.string.ui_default_package,
    506                 mInCallServiceComponentNameX.getPackageName());
    507         mComponentContextFixture.putResource(
    508                 com.android.server.telecom.R.string.incall_default_class,
    509                 mInCallServiceComponentNameX.getClassName());
    510         mComponentContextFixture.putBooleanResource(
    511                 com.android.internal.R.bool.config_voice_capable, true);
    512 
    513         mInCallServiceFixtureX = new InCallServiceFixture();
    514         mInCallServiceFixtureY = new InCallServiceFixture();
    515 
    516         mComponentContextFixture.addInCallService(mInCallServiceComponentNameX,
    517                 mInCallServiceFixtureX.getTestDouble());
    518         mComponentContextFixture.addInCallService(mInCallServiceComponentNameY,
    519                 mInCallServiceFixtureY.getTestDouble());
    520     }
    521 
    522     /**
    523      * Helper method for setting up the fake audio service.
    524      * Calls to the fake audio service need to toggle the return
    525      * value of AudioManager#isMicrophoneMute.
    526      * @return mock of IAudioService
    527      */
    528     private IAudioService setupAudioService() {
    529         IAudioService audioService = mock(IAudioService.class);
    530 
    531         final AudioManager fakeAudioManager =
    532                 (AudioManager) mComponentContextFixture.getTestDouble()
    533                         .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
    534 
    535         try {
    536             doAnswer(new Answer() {
    537                 @Override
    538                 public Object answer(InvocationOnMock i) {
    539                     Object[] args = i.getArguments();
    540                     doReturn(args[0]).when(fakeAudioManager).isMicrophoneMute();
    541                     return null;
    542                 }
    543             }).when(audioService)
    544                     .setMicrophoneMute(any(Boolean.class), any(String.class), any(Integer.class));
    545 
    546         } catch (android.os.RemoteException e) {
    547             // Do nothing, leave the faked microphone state as-is
    548         }
    549         return audioService;
    550     }
    551 
    552     protected String startOutgoingPhoneCallWithNoPhoneAccount(String number,
    553             ConnectionServiceFixture connectionServiceFixture)
    554             throws Exception {
    555 
    556         return startOutgoingPhoneCallPendingCreateConnection(number, null,
    557                 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY);
    558     }
    559 
    560     protected IdPair outgoingCallPhoneAccountSelected(PhoneAccountHandle phoneAccountHandle,
    561             int startingNumConnections, int startingNumCalls,
    562             ConnectionServiceFixture connectionServiceFixture) throws Exception {
    563 
    564         IdPair ids = outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
    565                 phoneAccountHandle, connectionServiceFixture);
    566 
    567         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
    568         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
    569         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    570 
    571         connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
    572 
    573         connectionServiceFixture.sendSetActive(ids.mConnectionId);
    574         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
    575         assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    576 
    577         return ids;
    578     }
    579 
    580     protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
    581             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser)
    582             throws Exception {
    583 
    584         return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
    585                 initiatingUser, VideoProfile.STATE_AUDIO_ONLY);
    586     }
    587 
    588     protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle,
    589             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
    590             int videoState) throws Exception {
    591         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
    592         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
    593 
    594         startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle,
    595                 connectionServiceFixture, initiatingUser, videoState);
    596 
    597         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
    598                 .createConnectionComplete(anyString(), any());
    599 
    600         return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
    601                 phoneAccountHandle, connectionServiceFixture);
    602     }
    603 
    604     protected IdPair triggerEmergencyRedial(PhoneAccountHandle phoneAccountHandle,
    605             ConnectionServiceFixture connectionServiceFixture, IdPair emergencyIds)
    606             throws Exception {
    607         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
    608         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
    609 
    610         // Send the message to disconnect the Emergency call due to an error.
    611         // CreateConnectionProcessor should now try the second SIM account
    612         connectionServiceFixture.sendSetDisconnected(emergencyIds.mConnectionId,
    613                 DisconnectCause.ERROR);
    614         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    615         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(
    616                 emergencyIds.mCallId).getState());
    617         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(
    618                 emergencyIds.mCallId).getState());
    619 
    620         return redialingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
    621                 phoneAccountHandle, connectionServiceFixture);
    622     }
    623 
    624     protected IdPair startOutgoingEmergencyCall(String number,
    625             PhoneAccountHandle phoneAccountHandle,
    626             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
    627             int videoState) throws Exception {
    628         int startingNumConnections = connectionServiceFixture.mConnectionById.size();
    629         int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
    630 
    631         mIsEmergencyCall = true;
    632         // Call will not use the ordered broadcaster, since it is an Emergency Call
    633         startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle,
    634                 connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/);
    635 
    636         return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls,
    637                 phoneAccountHandle, connectionServiceFixture);
    638     }
    639 
    640     protected void startOutgoingPhoneCallWaitForBroadcaster(String number,
    641             PhoneAccountHandle phoneAccountHandle,
    642             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
    643             int videoState, boolean isEmergency) throws Exception {
    644         reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
    645                 mInCallServiceFixtureY.getTestDouble());
    646 
    647         assertEquals(mInCallServiceFixtureX.mCallById.size(),
    648                 mInCallServiceFixtureY.mCallById.size());
    649         assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
    650                 (mInCallServiceFixtureY.mInCallAdapter != null));
    651 
    652         mNumOutgoingCallsMade++;
    653 
    654         boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
    655 
    656         Intent actionCallIntent = new Intent();
    657         actionCallIntent.setData(Uri.parse("tel:" + number));
    658         actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
    659         if(isEmergency) {
    660             actionCallIntent.setAction(Intent.ACTION_CALL_EMERGENCY);
    661         } else {
    662             actionCallIntent.setAction(Intent.ACTION_CALL);
    663         }
    664         if (phoneAccountHandle != null) {
    665             actionCallIntent.putExtra(
    666                     TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
    667                     phoneAccountHandle);
    668         }
    669         if (videoState != VideoProfile.STATE_AUDIO_ONLY) {
    670             actionCallIntent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
    671         }
    672 
    673         final UserHandle userHandle = initiatingUser;
    674         Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext();
    675         new UserCallIntentProcessor(localAppContext, userHandle).processIntent(
    676                 actionCallIntent, null, true /* hasCallAppOp*/, false /* isLocal */);
    677         // UserCallIntentProcessor's mContext.sendBroadcastAsUser(...) will call to an empty method
    678         // as to not actually try to send an intent to PrimaryCallReceiver. We verify that it was
    679         // called correctly in order to continue.
    680         verify(localAppContext).sendBroadcastAsUser(actionCallIntent, UserHandle.SYSTEM);
    681         mTelecomSystem.getCallIntentProcessor().processIntent(actionCallIntent);
    682         // Wait for handler to start CallerInfo lookup.
    683         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    684         // Send the CallerInfo lookup reply.
    685         mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach(
    686                 CallerInfoAsyncQueryFactoryFixture.Request::reply);
    687 
    688         boolean isSelfManaged = phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle();
    689         if (!hasInCallAdapter && !isSelfManaged) {
    690             verify(mInCallServiceFixtureX.getTestDouble())
    691                     .setInCallAdapter(
    692                             any(IInCallAdapter.class));
    693             verify(mInCallServiceFixtureY.getTestDouble())
    694                     .setInCallAdapter(
    695                             any(IInCallAdapter.class));
    696         }
    697     }
    698 
    699     protected String startOutgoingPhoneCallPendingCreateConnection(String number,
    700             PhoneAccountHandle phoneAccountHandle,
    701             ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser,
    702             int videoState) throws Exception {
    703         startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle,
    704                 connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/);
    705 
    706         ArgumentCaptor<Intent> newOutgoingCallIntent =
    707                 ArgumentCaptor.forClass(Intent.class);
    708         ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver =
    709                 ArgumentCaptor.forClass(BroadcastReceiver.class);
    710 
    711         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
    712             verify(mComponentContextFixture.getTestDouble().getApplicationContext(),
    713                     times(mNumOutgoingCallsMade))
    714                     .sendOrderedBroadcastAsUser(
    715                             newOutgoingCallIntent.capture(),
    716                             any(UserHandle.class),
    717                             anyString(),
    718                             anyInt(),
    719                             newOutgoingCallReceiver.capture(),
    720                             nullable(Handler.class),
    721                             anyInt(),
    722                             anyString(),
    723                             nullable(Bundle.class));
    724             // Pass on the new outgoing call Intent
    725             // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive()
    726             newOutgoingCallReceiver.getValue().setPendingResult(
    727                     new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0));
    728             newOutgoingCallReceiver.getValue().setResultData(
    729                     newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER));
    730             newOutgoingCallReceiver.getValue().onReceive(mComponentContextFixture.getTestDouble(),
    731                     newOutgoingCallIntent.getValue());
    732         }
    733 
    734         return mInCallServiceFixtureX.mLatestCallId;
    735     }
    736 
    737     // When Telecom is redialing due to an error, we need to make sure the number of connections
    738     // increase, but not the number of Calls in the InCallService.
    739     protected IdPair redialingCallCreateConnectionComplete(int startingNumConnections,
    740             int startingNumCalls, PhoneAccountHandle phoneAccountHandle,
    741             ConnectionServiceFixture connectionServiceFixture) throws Exception {
    742 
    743         assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
    744 
    745         verify(connectionServiceFixture.getTestDouble())
    746                 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
    747                         eq(false)/*isIncoming*/, anyBoolean(), any());
    748         // Wait for handleCreateConnectionComplete
    749         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    750 
    751         // Make sure the number of registered InCallService Calls stays the same.
    752         assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size());
    753         assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size());
    754 
    755         assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
    756 
    757         return new IdPair(connectionServiceFixture.mLatestConnectionId,
    758                 mInCallServiceFixtureX.mLatestCallId);
    759     }
    760 
    761     protected IdPair outgoingCallCreateConnectionComplete(int startingNumConnections,
    762             int startingNumCalls, PhoneAccountHandle phoneAccountHandle,
    763             ConnectionServiceFixture connectionServiceFixture) throws Exception {
    764 
    765         // Wait for the focus tracker.
    766         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    767 
    768         verify(connectionServiceFixture.getTestDouble())
    769                 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class),
    770                         eq(false)/*isIncoming*/, anyBoolean(), any());
    771         // Wait for handleCreateConnectionComplete
    772         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    773         assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size());
    774 
    775         // Wait for the callback in ConnectionService#onAdapterAttached to execute.
    776         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    777 
    778         // Ensure callback to CS on successful creation happened.
    779         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
    780                 .createConnectionComplete(anyString(), any());
    781 
    782         if (phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle()) {
    783             assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size());
    784             assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size());
    785         } else {
    786             assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
    787             assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
    788         }
    789 
    790         assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
    791 
    792         return new IdPair(connectionServiceFixture.mLatestConnectionId,
    793                 mInCallServiceFixtureX.mLatestCallId);
    794     }
    795 
    796     protected IdPair startIncomingPhoneCall(
    797             String number,
    798             PhoneAccountHandle phoneAccountHandle,
    799             final ConnectionServiceFixture connectionServiceFixture) throws Exception {
    800         return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY,
    801                 connectionServiceFixture);
    802     }
    803 
    804     protected IdPair startIncomingPhoneCall(
    805             String number,
    806             PhoneAccountHandle phoneAccountHandle,
    807             int videoState,
    808             final ConnectionServiceFixture connectionServiceFixture) throws Exception {
    809         reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(),
    810                 mInCallServiceFixtureY.getTestDouble());
    811 
    812         assertEquals(mInCallServiceFixtureX.mCallById.size(),
    813                 mInCallServiceFixtureY.mCallById.size());
    814         assertEquals((mInCallServiceFixtureX.mInCallAdapter != null),
    815                 (mInCallServiceFixtureY.mInCallAdapter != null));
    816         final int startingNumConnections = connectionServiceFixture.mConnectionById.size();
    817         final int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
    818         boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null;
    819         connectionServiceFixture.mConnectionServiceDelegate.mVideoState = videoState;
    820         CountDownLatch incomingCallAddedLatch = new CountDownLatch(1);
    821         IncomingCallAddedListener callAddedListener =
    822                 new IncomingCallAddedListener(incomingCallAddedLatch);
    823         mTelecomSystem.getCallsManager().addListener(callAddedListener);
    824 
    825         Bundle extras = new Bundle();
    826         extras.putParcelable(
    827                 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
    828                 Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null));
    829         mTelecomSystem.getTelecomServiceImpl().getBinder()
    830                 .addNewIncomingCall(phoneAccountHandle, extras);
    831 
    832         verify(connectionServiceFixture.getTestDouble())
    833                 .createConnection(any(PhoneAccountHandle.class), anyString(),
    834                         any(ConnectionRequest.class), eq(true), eq(false), any());
    835 
    836         // Wait for the handler to start the CallerInfo lookup
    837         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
    838 
    839         // Ensure callback to CS on successful creation happened.
    840         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
    841                 .createConnectionComplete(anyString(), any());
    842 
    843         // Process the CallerInfo lookup reply
    844         mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach(
    845                 CallerInfoAsyncQueryFactoryFixture.Request::reply);
    846 
    847         //Wait for/Verify call blocking happened asynchronously
    848         incomingCallAddedLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
    849 
    850         IContentProvider blockedNumberProvider =
    851                 mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY);
    852         verify(blockedNumberProvider, timeout(TEST_TIMEOUT)).call(
    853                 anyString(),
    854                 eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
    855                 eq(number),
    856                 isNotNull(Bundle.class));
    857 
    858         // For the case of incoming calls, Telecom connecting the InCall services and adding the
    859         // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call
    860         // is added, future interactions as triggered by the ConnectionService, through the various
    861         // test fixtures, will be synchronous.
    862 
    863         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
    864             if (!hasInCallAdapter) {
    865                 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
    866                         .setInCallAdapter(any(IInCallAdapter.class));
    867                 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
    868                         .setInCallAdapter(any(IInCallAdapter.class));
    869 
    870                 // Give the InCallService time to respond
    871                 assertTrueWithTimeout(new Predicate<Void>() {
    872                     @Override
    873                     public boolean apply(Void v) {
    874                         return mInCallServiceFixtureX.mInCallAdapter != null;
    875                     }
    876                 });
    877 
    878                 assertTrueWithTimeout(new Predicate<Void>() {
    879                     @Override
    880                     public boolean apply(Void v) {
    881                         return mInCallServiceFixtureY.mInCallAdapter != null;
    882                     }
    883                 });
    884 
    885                 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
    886                         .addCall(any(ParcelableCall.class));
    887                 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
    888                         .addCall(any(ParcelableCall.class));
    889 
    890                 // Give the InCallService time to respond
    891             }
    892 
    893             assertTrueWithTimeout(new Predicate<Void>() {
    894                 @Override
    895                 public boolean apply(Void v) {
    896                     return startingNumConnections + 1 ==
    897                             connectionServiceFixture.mConnectionById.size();
    898                 }
    899             });
    900 
    901             mInCallServiceFixtureX.waitUntilNumCalls(startingNumCalls + 1);
    902             mInCallServiceFixtureY.waitUntilNumCalls(startingNumCalls + 1);
    903             assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
    904             assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
    905 
    906             assertEquals(mInCallServiceFixtureX.mLatestCallId,
    907                     mInCallServiceFixtureY.mLatestCallId);
    908         }
    909 
    910         return new IdPair(connectionServiceFixture.mLatestConnectionId,
    911                 mInCallServiceFixtureX.mLatestCallId);
    912     }
    913 
    914     protected IdPair startAndMakeActiveOutgoingCall(
    915             String number,
    916             PhoneAccountHandle phoneAccountHandle,
    917             ConnectionServiceFixture connectionServiceFixture) throws Exception {
    918         return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture,
    919                 VideoProfile.STATE_AUDIO_ONLY);
    920     }
    921 
    922     // A simple outgoing call, verifying that the appropriate connection service is contacted,
    923     // the proper lifecycle is followed, and both In-Call Services are updated correctly.
    924     protected IdPair startAndMakeActiveOutgoingCall(
    925             String number,
    926             PhoneAccountHandle phoneAccountHandle,
    927             ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception {
    928         IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture,
    929                 Process.myUserHandle(), videoState);
    930 
    931         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
    932         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
    933             assertEquals(Call.STATE_DIALING,
    934                     mInCallServiceFixtureX.getCall(ids.mCallId).getState());
    935             assertEquals(Call.STATE_DIALING,
    936                     mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    937         }
    938 
    939         connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
    940 
    941         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
    942         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
    943         connectionServiceFixture.sendSetActive(ids.mConnectionId);
    944         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
    945             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
    946             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    947         }
    948         return ids;
    949     }
    950 
    951     protected IdPair startAndMakeActiveIncomingCall(
    952             String number,
    953             PhoneAccountHandle phoneAccountHandle,
    954             ConnectionServiceFixture connectionServiceFixture) throws Exception {
    955         return startAndMakeActiveIncomingCall(number, phoneAccountHandle, connectionServiceFixture,
    956                 VideoProfile.STATE_AUDIO_ONLY);
    957     }
    958 
    959     // A simple incoming call, similar in scope to the previous test
    960     protected IdPair startAndMakeActiveIncomingCall(
    961             String number,
    962             PhoneAccountHandle phoneAccountHandle,
    963             ConnectionServiceFixture connectionServiceFixture,
    964             int videoState) throws Exception {
    965         IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);
    966 
    967         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
    968             assertEquals(Call.STATE_RINGING,
    969                     mInCallServiceFixtureX.getCall(ids.mCallId).getState());
    970             assertEquals(Call.STATE_RINGING,
    971                     mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    972 
    973             mInCallServiceFixtureX.mInCallAdapter
    974                     .answerCall(ids.mCallId, videoState);
    975 
    976             if (!VideoProfile.isVideo(videoState)) {
    977                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
    978                         .answer(eq(ids.mConnectionId), any());
    979             } else {
    980                 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
    981                         .answerVideo(eq(ids.mConnectionId), eq(videoState), any());
    982             }
    983         }
    984 
    985         when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
    986         when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
    987         connectionServiceFixture.sendSetActive(ids.mConnectionId);
    988 
    989         if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
    990             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
    991             assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    992         }
    993         return ids;
    994     }
    995 
    996     protected IdPair startAndMakeDialingEmergencyCall(
    997             String number,
    998             PhoneAccountHandle phoneAccountHandle,
    999             ConnectionServiceFixture connectionServiceFixture) throws Exception {
   1000         IdPair ids = startOutgoingEmergencyCall(number, phoneAccountHandle,
   1001                 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY);
   1002 
   1003         connectionServiceFixture.sendSetDialing(ids.mConnectionId);
   1004         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
   1005         assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
   1006 
   1007         return ids;
   1008     }
   1009 
   1010     protected static void assertTrueWithTimeout(Predicate<Void> predicate) {
   1011         int elapsed = 0;
   1012         while (elapsed < TEST_TIMEOUT) {
   1013             if (predicate.apply(null)) {
   1014                 return;
   1015             } else {
   1016                 try {
   1017                     Thread.sleep(TEST_POLL_INTERVAL);
   1018                     elapsed += TEST_POLL_INTERVAL;
   1019                 } catch (InterruptedException e) {
   1020                     fail(e.toString());
   1021                 }
   1022             }
   1023         }
   1024         fail("Timeout in assertTrueWithTimeout");
   1025     }
   1026 }
   1027