/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.telecom.tests;

import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.fail;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyChar;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.telecom.CallerInfo;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Pair;
import android.widget.Toast;

import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallAudioModeStateMachine;
import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.CallDiagnosticServiceController;
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.EmergencyCallHelper;
import com.android.server.telecom.HeadsetMediaButton;
import com.android.server.telecom.HeadsetMediaButtonFactory;
import com.android.server.telecom.InCallController;
import com.android.server.telecom.InCallControllerFactory;
import com.android.server.telecom.InCallTonePlayer;
import com.android.server.telecom.InCallWakeLockController;
import com.android.server.telecom.InCallWakeLockControllerFactory;
import com.android.server.telecom.MissedCallNotifier;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
import com.android.server.telecom.RoleManagerAdapter;
import com.android.server.telecom.SystemStateHelper;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
import com.android.server.telecom.WiredHeadsetManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
import com.android.server.telecom.callfiltering.CallFilteringResult;
import com.android.server.telecom.ui.AudioProcessingNotification;
import com.android.server.telecom.ui.DisconnectedCallNotifier;
import com.android.server.telecom.ui.ToastFactory;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

@RunWith(JUnit4.class)
public class CallsManagerTest extends TelecomTestCase {
    private static final int TEST_TIMEOUT = 5000;  // milliseconds
    private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle(
            ComponentName.unflattenFromString("com.foo/.Blah"), "Sim1");
    private static final PhoneAccountHandle SIM_2_HANDLE = new PhoneAccountHandle(
            ComponentName.unflattenFromString("com.foo/.Blah"), "Sim2");
    private static final PhoneAccountHandle CONNECTION_MGR_1_HANDLE = new PhoneAccountHandle(
            ComponentName.unflattenFromString("com.bar/.Conn"), "Cm1");
    private static final PhoneAccountHandle CONNECTION_MGR_2_HANDLE = new PhoneAccountHandle(
            ComponentName.unflattenFromString("com.spa/.Conn"), "Cm2");
    private static final PhoneAccountHandle VOIP_1_HANDLE = new PhoneAccountHandle(
            ComponentName.unflattenFromString("com.voip/.Stuff"), "Voip1");
    private static final PhoneAccountHandle SELF_MANAGED_HANDLE = new PhoneAccountHandle(
            ComponentName.unflattenFromString("com.baz/.Self"), "Self");
    private static final PhoneAccount SIM_1_ACCOUNT = new PhoneAccount.Builder(SIM_1_HANDLE, "Sim1")
            .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
                    | PhoneAccount.CAPABILITY_CALL_PROVIDER
                    | PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)
            .setIsEnabled(true)
            .build();
    private static final PhoneAccount SIM_2_ACCOUNT = new PhoneAccount.Builder(SIM_2_HANDLE, "Sim2")
            .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
                    | PhoneAccount.CAPABILITY_CALL_PROVIDER
                    | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING)
            .setIsEnabled(true)
            .build();
    private static final PhoneAccount SELF_MANAGED_ACCOUNT = new PhoneAccount.Builder(
            SELF_MANAGED_HANDLE, "Self")
            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
            .setIsEnabled(true)
            .build();
    private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212");
    private static final Uri TEST_ADDRESS2 = Uri.parse("tel:555-1213");
    private static final Uri TEST_ADDRESS3 = Uri.parse("tel:555-1214");
    private static final Map<Uri, PhoneAccountHandle> CONTACT_PREFERRED_ACCOUNT = Map.of(
            TEST_ADDRESS2, SIM_1_HANDLE,
            TEST_ADDRESS3, SIM_2_HANDLE);

    private static int sCallId = 1;
    private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
    @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper;
    @Mock private MissedCallNotifier mMissedCallNotifier;
    @Mock private DisconnectedCallNotifier.Factory mDisconnectedCallNotifierFactory;
    @Mock private DisconnectedCallNotifier mDisconnectedCallNotifier;
    @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
    @Mock private HeadsetMediaButton mHeadsetMediaButton;
    @Mock private HeadsetMediaButtonFactory mHeadsetMediaButtonFactory;
    @Mock private ProximitySensorManager mProximitySensorManager;
    @Mock private ProximitySensorManagerFactory mProximitySensorManagerFactory;
    @Mock private InCallWakeLockController mInCallWakeLockController;
    @Mock private ConnectionServiceFocusManagerFactory mConnSvrFocusManagerFactory;
    @Mock private InCallWakeLockControllerFactory mInCallWakeLockControllerFactory;
    @Mock private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
    @Mock private BluetoothRouteManager mBluetoothRouteManager;
    @Mock private WiredHeadsetManager mWiredHeadsetManager;
    @Mock private SystemStateHelper mSystemStateHelper;
    @Mock private DefaultDialerCache mDefaultDialerCache;
    @Mock private Timeouts.Adapter mTimeoutsAdapter;
    @Mock private AsyncRingtonePlayer mAsyncRingtonePlayer;
    @Mock private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
    @Mock private EmergencyCallHelper mEmergencyCallHelper;
    @Mock private InCallTonePlayer.ToneGeneratorFactory mToneGeneratorFactory;
    @Mock private ClockProxy mClockProxy;
    @Mock private AudioProcessingNotification mAudioProcessingNotification;
    @Mock private InCallControllerFactory mInCallControllerFactory;
    @Mock private InCallController mInCallController;
    @Mock private ConnectionServiceFocusManager mConnectionSvrFocusMgr;
    @Mock private CallAudioRouteStateMachine mCallAudioRouteStateMachine;
    @Mock private CallAudioRouteStateMachine.Factory mCallAudioRouteStateMachineFactory;
    @Mock private CallAudioModeStateMachine mCallAudioModeStateMachine;
    @Mock private CallAudioModeStateMachine.Factory mCallAudioModeStateMachineFactory;
    @Mock private CallDiagnosticServiceController mCallDiagnosticServiceController;
    @Mock private BluetoothStateReceiver mBluetoothStateReceiver;
    @Mock private RoleManagerAdapter mRoleManagerAdapter;
    @Mock private ToastFactory mToastFactory;
    @Mock private Toast mToast;

    private CallsManager mCallsManager;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);
        when(mInCallWakeLockControllerFactory.create(any(), any())).thenReturn(
                mInCallWakeLockController);
        when(mHeadsetMediaButtonFactory.create(any(), any(), any())).thenReturn(
                mHeadsetMediaButton);
        when(mProximitySensorManagerFactory.create(any(), any())).thenReturn(
                mProximitySensorManager);
        when(mInCallControllerFactory.create(any(), any(), any(), any(), any(), any(),
                any())).thenReturn(mInCallController);
        when(mCallAudioRouteStateMachineFactory.create(any(), any(), any(), any(), any(), any(),
                anyInt())).thenReturn(mCallAudioRouteStateMachine);
        when(mCallAudioModeStateMachineFactory.create(any(), any()))
                .thenReturn(mCallAudioModeStateMachine);
        when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
        when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
        when(mConnSvrFocusManagerFactory.create(any())).thenReturn(mConnectionSvrFocusMgr);
        doNothing().when(mRoleManagerAdapter).setCurrentUserHandle(any());
        when(mDisconnectedCallNotifierFactory.create(any(Context.class),any(CallsManager.class)))
                .thenReturn(mDisconnectedCallNotifier);
        when(mTimeoutsAdapter.getCallDiagnosticServiceTimeoutMillis(any(ContentResolver.class)))
                .thenReturn(2000L);
        mCallsManager = new CallsManager(
                mComponentContextFixture.getTestDouble().getApplicationContext(),
                mLock,
                mCallerInfoLookupHelper,
                mMissedCallNotifier,
                mDisconnectedCallNotifierFactory,
                mPhoneAccountRegistrar,
                mHeadsetMediaButtonFactory,
                mProximitySensorManagerFactory,
                mInCallWakeLockControllerFactory,
                mConnSvrFocusManagerFactory,
                mAudioServiceFactory,
                mBluetoothRouteManager,
                mWiredHeadsetManager,
                mSystemStateHelper,
                mDefaultDialerCache,
                mTimeoutsAdapter,
                mAsyncRingtonePlayer,
                mPhoneNumberUtilsAdapter,
                mEmergencyCallHelper,
                mToneGeneratorFactory,
                mClockProxy,
                mAudioProcessingNotification,
                mBluetoothStateReceiver,
                mCallAudioRouteStateMachineFactory,
                mCallAudioModeStateMachineFactory,
                mInCallControllerFactory,
                mCallDiagnosticServiceController,
                mRoleManagerAdapter,
                mToastFactory);

        when(mPhoneAccountRegistrar.getPhoneAccount(
                eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT);
        when(mPhoneAccountRegistrar.getPhoneAccount(
                eq(SIM_1_HANDLE), any())).thenReturn(SIM_1_ACCOUNT);
        when(mPhoneAccountRegistrar.getPhoneAccount(
                eq(SIM_2_HANDLE), any())).thenReturn(SIM_2_ACCOUNT);
        when(mToastFactory.makeText(any(), anyInt(), anyInt())).thenReturn(mToast);
        when(mToastFactory.makeText(any(), any(), anyInt())).thenReturn(mToast);
    }

    @Override
    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @MediumTest
    @Test
    public void testConstructPossiblePhoneAccounts() throws Exception {
        // Should be empty since the URI is null.
        assertEquals(0, mCallsManager.constructPossiblePhoneAccounts(null, null, false, false).size());
    }

    /**
     * Verify behavior for multisim devices where we want to ensure that the active sim is used for
     * placing a new call.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testConstructPossiblePhoneAccountsMultiSimActive() throws Exception {
        setupMsimAccounts();

        Call ongoingCall = new Call(
                "1", /* callId */
                mContext,
                mCallsManager,
                mLock,
                null /* ConnectionServiceRepository */,
                mPhoneNumberUtilsAdapter,
                TEST_ADDRESS,
                null /* GatewayInfo */,
                null /* connectionManagerPhoneAccountHandle */,
                SIM_2_HANDLE,
                Call.CALL_DIRECTION_INCOMING,
                false /* shouldAttachToExistingConnection*/,
                false /* isConference */,
                mClockProxy,
                mToastFactory);
        ongoingCall.setState(CallState.ACTIVE, "just cuz");
        mCallsManager.addCall(ongoingCall);

        List<PhoneAccountHandle> phoneAccountHandles = mCallsManager.constructPossiblePhoneAccounts(
                TEST_ADDRESS, null, false, false);
        assertEquals(1, phoneAccountHandles.size());
        assertEquals(SIM_2_HANDLE, phoneAccountHandles.get(0));
    }

    /**
     * Verify behavior for multisim devices when there are no calls active; expect both accounts.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testConstructPossiblePhoneAccountsMultiSimIdle() throws Exception {
        setupMsimAccounts();

        List<PhoneAccountHandle> phoneAccountHandles = mCallsManager.constructPossiblePhoneAccounts(
                TEST_ADDRESS, null, false, false);
        assertEquals(2, phoneAccountHandles.size());
    }

    private void setupCallerInfoLookupHelper() {
        doAnswer(invocation -> {
            Uri handle = invocation.getArgument(0);
            CallerInfoLookupHelper.OnQueryCompleteListener listener = invocation.getArgument(1);
            CallerInfo info = new CallerInfo();
            if (CONTACT_PREFERRED_ACCOUNT.get(handle) != null) {
                PhoneAccountHandle pah = CONTACT_PREFERRED_ACCOUNT.get(handle);
                info.preferredPhoneAccountComponent = pah.getComponentName();
                info.preferredPhoneAccountId = pah.getId();
            }
            listener.onCallerInfoQueryComplete(handle, info);
            return null;
        }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class),
                any(CallerInfoLookupHelper.OnQueryCompleteListener.class));
    }
    /**
     * Tests finding the outgoing call phone account where the call is being placed on a
     * self-managed ConnectionService.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testFindOutgoingCallPhoneAccountSelfManaged() throws Exception {
        setupCallerInfoLookupHelper();
        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                SELF_MANAGED_HANDLE, TEST_ADDRESS, false /* isVideo */, false /* isEmergency */, null /* userHandle */)
                .get();
        assertEquals(1, accounts.size());
        assertEquals(SELF_MANAGED_HANDLE, accounts.get(0));
    }

    /**
     * Tests finding the outgoing calling account where the call has no associated phone account,
     * but there is a user specified default which can be used.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testFindOutgoingCallAccountDefault() throws Exception {
        setupCallerInfoLookupHelper();
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                SIM_1_HANDLE);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));

        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, false /* isEmergency */, null /* userHandle */)
                .get();

        // Should have found just the default.
        assertEquals(1, accounts.size());
        assertEquals(SIM_1_HANDLE, accounts.get(0));
    }

    /**
     * Tests finding the outgoing calling account where the call has no associated phone account,
     * but there is no user specified default which can be used.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testFindOutgoingCallAccountNoDefault() throws Exception {
        setupCallerInfoLookupHelper();
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                null);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));

        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                null /* phoneAcct */, TEST_ADDRESS, false /* isVideo */, false /* isEmergency */, null /* userHandle */)
                .get();

        assertEquals(2, accounts.size());
        assertTrue(accounts.contains(SIM_1_HANDLE));
        assertTrue(accounts.contains(SIM_2_HANDLE));
    }

    /**
     * Tests that we will default to a video capable phone account if one is available for a video
     * call.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testFindOutgoingCallAccountVideo() throws Exception {
        setupCallerInfoLookupHelper();
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                null);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_2_HANDLE)));

        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, false /* isEmergency */, null /* userHandle */)
                .get();

        assertEquals(1, accounts.size());
        assertTrue(accounts.contains(SIM_2_HANDLE));
    }

    /**
     * Tests that we will default to a non-video capable phone account for a video call if no video
     * capable phone accounts are available.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testFindOutgoingCallAccountVideoNotAvailable() throws Exception {
        setupCallerInfoLookupHelper();
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                null);
        // When querying for video capable accounts, return nothing.
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), eq(PhoneAccount.CAPABILITY_VIDEO_CALLING), anyInt())).thenReturn(
                Collections.emptyList());
        // When querying for non-video capable accounts, return one.
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), eq(0 /* none specified */), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE)));
        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                null /* phoneAcct */, TEST_ADDRESS, true /* isVideo */, false /* isEmergency */, null /* userHandle */)
                .get();

        // Should have found one.
        assertEquals(1, accounts.size());
        assertTrue(accounts.contains(SIM_1_HANDLE));
    }

    /**
     * Tests that we will use the provided target phone account if it exists.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testUseSpecifiedAccount() throws Exception {
        setupCallerInfoLookupHelper();
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                null);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));

        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                SIM_2_HANDLE, TEST_ADDRESS, false /* isVideo */, false /* isEmergency */, null /* userHandle */).get();

        assertEquals(1, accounts.size());
        assertTrue(accounts.contains(SIM_2_HANDLE));
    }

    /**
     * Tests that we will use the provided target phone account if it exists.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testUseContactSpecificAcct() throws Exception {
        setupCallerInfoLookupHelper();
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                null);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));

        List<PhoneAccountHandle> accounts = mCallsManager.findOutgoingCallPhoneAccount(
                null, TEST_ADDRESS2, false /* isVideo */, false /* isEmergency */, Process.myUserHandle()).get();

        assertEquals(1, accounts.size());
        assertTrue(accounts.contains(SIM_1_HANDLE));
    }

    /**
     * Verifies that an active call will result in playing a DTMF tone when requested.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testPlayDtmfWhenActive() throws Exception {
        Call callSpy = addSpyCall();
        mCallsManager.playDtmfTone(callSpy, '1');
        verify(callSpy).playDtmfTone(anyChar());
    }

    /**
     * Verifies that DTMF requests are suppressed when a call is held.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testSuppessDtmfWhenHeld() throws Exception {
        Call callSpy = addSpyCall();
        callSpy.setState(CallState.ON_HOLD, "test");

        mCallsManager.playDtmfTone(callSpy, '1');
        verify(callSpy, never()).playDtmfTone(anyChar());
    }

    /**
     * Verifies that DTMF requests are suppressed when a call is held.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testCancelDtmfWhenHeld() throws Exception {
        Call callSpy = addSpyCall();
        mCallsManager.playDtmfTone(callSpy, '1');
        mCallsManager.markCallAsOnHold(callSpy);
        verify(callSpy).stopDtmfTone();
    }

    @SmallTest
    @Test
    public void testUnholdCallWhenOngoingCallCanBeHeld() {
        // GIVEN a CallsManager with ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call
        Call heldCall = addSpyCall();

        // WHEN unhold the held call
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is held, and the focus request for incoming call is sent
        verify(ongoingCall).hold(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold(any());
    }

    @SmallTest
    @Test
    public void testUnholdCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call which has different ConnectionService
        Call heldCall = addSpyCall(VOIP_1_HANDLE, CallState.ON_HOLD);

        // WHEN unhold the held call
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is disconnected, and the focus request for incoming call is sent
        verify(ongoingCall).disconnect(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold(any());
    }

    @SmallTest
    @Test
    public void testUnholdCallWhenOngoingEmergCallCanNotBeHeldAndFromDifferentConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held, but it also an
        // emergency call.
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(true).when(ongoingCall).isEmergencyCall();
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call which has different ConnectionService
        Call heldCall = addSpyCall(VOIP_1_HANDLE, CallState.ON_HOLD);

        // WHEN unhold the held call
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call will not be disconnected (because its an emergency call)
        verify(ongoingCall, never()).disconnect(any());

        // and held call is not un-held
        verify(heldCall, never()).unhold(any());
    }

    @SmallTest
    @Test
    public void testUnholdCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call which has the same ConnectionService
        Call heldCall = addSpyCall(SIM_2_HANDLE, CallState.ON_HOLD);

        // WHEN unhold the held call
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is held
        verify(ongoingCall).hold(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold(any());
    }

    @SmallTest
    @Test
    public void testDuplicateAnswerCall() {
        Call incomingCall = addSpyCall(CallState.RINGING);
        doAnswer(invocation -> {
            doReturn(CallState.ANSWERED).when(incomingCall).getState();
            return null;
        }).when(incomingCall).answer(anyInt());
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
        verifyFocusRequestAndExecuteCallback(incomingCall);
        reset(mConnectionSvrFocusMgr);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);
        verifyFocusRequestAndExecuteCallback(incomingCall);

        verify(incomingCall, times(2)).answer(anyInt());
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenOngoingCallCanBeHeld() {
        // GIVEN a CallsManager with ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // WHEN answer an incoming call
        Call incomingCall = addSpyCall(CallState.RINGING);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the ongoing call is held and the focus request for incoming call is sent
        verify(ongoingCall).hold();
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered.
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenOngoingHasSameConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // WHEN answer an incoming call
        Call incomingCall = addSpyCall(VOIP_1_HANDLE, CallState.RINGING);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN nothing happened on the ongoing call and the focus request for incoming call is sent
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered.
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenOngoingHasDifferentConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // WHEN answer an incoming call
        Call incomingCall = addSpyCall(VOIP_1_HANDLE, CallState.RINGING);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the ongoing call is disconnected and the focus request for incoming call is sent
        verify(ongoingCall).disconnect();
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered.
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenOngoingHasDifferentConnectionServiceButIsEmerg() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(true).when(ongoingCall).isEmergencyCall();
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // WHEN answer an incoming call
        Call incomingCall = addSpyCall(VOIP_1_HANDLE, CallState.RINGING);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the ongoing call is not disconnected
        verify(ongoingCall, never()).disconnect();

        // and the incoming call is not answered, but is rejected instead.
        verify(incomingCall, never()).answer(VideoProfile.STATE_AUDIO_ONLY);
        verify(incomingCall).reject(eq(false), any(), any());
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenMultipleHeldCallsExisted() {
        // Given an ongoing call and held call with the ConnectionService connSvr1. The
        // ConnectionService connSvr1 can handle one held call
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        Call heldCall = addSpyCall(SIM_1_HANDLE, CallState.ON_HOLD);
        doReturn(CallState.ON_HOLD).when(heldCall).getState();

        // and other held call has difference ConnectionService
        Call heldCall2 = addSpyCall(VOIP_1_HANDLE, CallState.ON_HOLD);
        doReturn(CallState.ON_HOLD).when(heldCall2).getState();

        // WHEN answer an incoming call which ConnectionService is connSvr1
        Call incomingCall = addSpyCall(SIM_1_HANDLE, CallState.RINGING);
        doReturn(true).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the previous held call is disconnected
        verify(heldCall).disconnect();

        // and the ongoing call is held
        verify(ongoingCall).hold();

        // and the heldCall2 is not disconnected
        verify(heldCall2, never()).disconnect();

        // and the focus request is sent
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenNoOngoingCallExisted() {
        // GIVEN a CallsManager with no ongoing call.

        // WHEN answer an incoming call
        Call incomingCall = addSpyCall(CallState.RINGING);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the focus request for incoming call is sent
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered.
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerAlreadyActiveCall() {
        // GIVEN a CallsManager with no ongoing call.

        // WHEN answer an already active call
        Call incomingCall = addSpyCall(CallState.RINGING);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the focus request for incoming call is sent
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered.
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);

        // and the incoming call's state is now ANSWERED
        assertEquals(CallState.ANSWERED, incomingCall.getState());
    }

    @SmallTest
    @Test
    public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();

        // and a new self-managed call which has different ConnectionService
        Call newCall = addSpyCall(VOIP_1_HANDLE, CallState.ACTIVE);
        doReturn(true).when(newCall).isSelfManaged();

        // WHEN active the new call
        mCallsManager.markCallAsActive(newCall);

        // THEN the ongoing call is disconnected, and the focus request for the new call is sent
        verify(ongoingCall).disconnect();
        verifyFocusRequestAndExecuteCallback(newCall);

        // and the new call is active
        assertEquals(CallState.ACTIVE, newCall.getState());
    }

    @SmallTest
    @Test
    public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a new self-managed call which has the same ConnectionService
        Call newCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(true).when(newCall).isSelfManaged();

        // WHEN active the new call
        mCallsManager.markCallAsActive(newCall);

        // THEN the ongoing call isn't disconnected
        verify(ongoingCall, never()).disconnect();
        verifyFocusRequestAndExecuteCallback(newCall);

        // and the new call is active
        assertEquals(CallState.ACTIVE, newCall.getState());
    }

    @SmallTest
    @Test
    public void testSetActiveCallWhenOngoingCallCanBeHeld() {
        // GIVEN a CallsManager with ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();

        // and a new self-managed call
        Call newCall = addSpyCall();
        doReturn(true).when(newCall).isSelfManaged();

        // WHEN active the new call
        mCallsManager.markCallAsActive(newCall);

        // THEN the ongoing call is held
        verify(ongoingCall).hold();
        verifyFocusRequestAndExecuteCallback(newCall);

        // and the new call is active
        assertEquals(CallState.ACTIVE, newCall.getState());
    }

    @SmallTest
    @Test
    public void testDisconnectDialingCallOnIncoming() {
        // GIVEN a CallsManager with a self-managed call which is dialing, and this call can be held
        Call ongoingCall = addSpyCall(SELF_MANAGED_HANDLE, CallState.DIALING);
        ongoingCall.setState(CallState.DIALING, "test");
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(true).when(ongoingCall).isSelfManaged();
        doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();

        // and a new incoming managed call
        Call newCall = addSpyCall();
        doReturn(false).when(newCall).isRespondViaSmsCapable();
        newCall.setState(CallState.RINGING, "test");

        // WHEN answering the new call
        mCallsManager.answerCall(newCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the ongoing call is disconnected
        verify(ongoingCall).disconnect();

        // AND focus is requested for the new call
        ArgumentCaptor<CallsManager.RequestCallback> requestCaptor =
                ArgumentCaptor.forClass(CallsManager.RequestCallback.class);
        verify(mConnectionSvrFocusMgr).requestFocus(eq(newCall), requestCaptor.capture());
        // since we're mocking the focus manager, we'll just pretend it did its thing.
        requestCaptor.getValue().onRequestFocusDone(newCall);

        // and the new call is marked answered
        assertEquals(CallState.ANSWERED, newCall.getState());
    }

    @SmallTest
    @Test
    public void testNoFilteringOfSelfManagedCalls() {
        // GIVEN an incoming call which is self managed.
        Call incomingCall = addSpyCall(SELF_MANAGED_HANDLE, CallState.NEW);
        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(true).when(incomingCall).isSelfManaged();
        doReturn(true).when(incomingCall).setState(anyInt(), any());

        // WHEN the incoming call is successfully added.
        mCallsManager.onSuccessfulIncomingCall(incomingCall);

        // THEN the incoming call is not using call filtering
        verify(incomingCall).setIsUsingCallFiltering(eq(false));
    }

    @SmallTest
    @Test
    public void testAcceptIncomingCallWhenHeadsetMediaButtonShortPress() {
        // GIVEN an incoming call
        Call incomingCall = addSpyCall();
        doReturn(CallState.RINGING).when(incomingCall).getState();

        // WHEN media button short press
        mCallsManager.onMediaButton(HeadsetMediaButton.SHORT_PRESS);

        // THEN the incoming call is answered
        ArgumentCaptor<CallsManager.RequestCallback> captor = ArgumentCaptor.forClass(
                CallsManager.RequestCallback.class);
        verify(mConnectionSvrFocusMgr).requestFocus(eq(incomingCall), captor.capture());
        captor.getValue().onRequestFocusDone(incomingCall);
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testRejectIncomingCallWhenHeadsetMediaButtonLongPress() {
        // GIVEN an incoming call
        Call incomingCall = addSpyCall();
        doReturn(CallState.RINGING).when(incomingCall).getState();

        // WHEN media button long press
        mCallsManager.onMediaButton(HeadsetMediaButton.LONG_PRESS);

        // THEN the incoming call is rejected
        verify(incomingCall).reject(false, null);
    }

    @SmallTest
    @Test
    public void testHangupOngoingCallWhenHeadsetMediaButtonShortPress() {
        // GIVEN an ongoing call
        Call ongoingCall = addSpyCall();
        doReturn(CallState.ACTIVE).when(ongoingCall).getState();

        // WHEN media button short press
        mCallsManager.onMediaButton(HeadsetMediaButton.SHORT_PRESS);

        // THEN the active call is disconnected
        verify(ongoingCall).disconnect();
    }

    @SmallTest
    @Test
    public void testToggleMuteWhenHeadsetMediaButtonLongPressDuringOngoingCall() {
        // GIVEN an ongoing call
        Call ongoingCall = addSpyCall();
        doReturn(CallState.ACTIVE).when(ongoingCall).getState();

        // WHEN media button long press
        mCallsManager.onMediaButton(HeadsetMediaButton.LONG_PRESS);

        // THEN the microphone toggle mute
        verify(mCallAudioRouteStateMachine)
                .sendMessageWithSessionInfo(CallAudioRouteStateMachine.TOGGLE_MUTE);
    }

    @SmallTest
    @Test
    public void testSwapCallsWhenHeadsetMediaButtonShortPressDuringTwoCalls() {
        // GIVEN an ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(CallState.ACTIVE).when(ongoingCall).getState();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call
        Call heldCall = addSpyCall();
        doReturn(CallState.ON_HOLD).when(heldCall).getState();

        // WHEN media button short press
        mCallsManager.onMediaButton(HeadsetMediaButton.SHORT_PRESS);

        // THEN the ongoing call is held, and the focus request for heldCall call is sent
        verify(ongoingCall).hold(nullable(String.class));
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold(nullable(String.class));
    }

    @SmallTest
    @Test
    public void testHangupActiveCallWhenHeadsetMediaButtonLongPressDuringTwoCalls() {
        // GIVEN an ongoing call
        Call ongoingCall = addSpyCall();
        doReturn(CallState.ACTIVE).when(ongoingCall).getState();

        // and a held call
        Call heldCall = addSpyCall();
        doReturn(CallState.ON_HOLD).when(heldCall).getState();

        // WHEN media button long press
        mCallsManager.onMediaButton(HeadsetMediaButton.LONG_PRESS);

        // THEN the ongoing call is disconnected
        verify(ongoingCall).disconnect();
    }

    @SmallTest
    @Test
    public void testNoFilteringOfCallsWhenPhoneAccountRequestsSkipped() {
        // GIVEN an incoming call which is from a PhoneAccount that requested to skip filtering.
        Call incomingCall = addSpyCall(SIM_1_HANDLE, CallState.NEW);
        Bundle extras = new Bundle();
        extras.putBoolean(PhoneAccount.EXTRA_SKIP_CALL_FILTERING, true);
        PhoneAccount skipRequestedAccount = new PhoneAccount.Builder(SIM_2_HANDLE, "Skipper")
            .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
                | PhoneAccount.CAPABILITY_CALL_PROVIDER)
            .setExtras(extras)
            .setIsEnabled(true)
            .build();
        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(SIM_1_HANDLE))
            .thenReturn(skipRequestedAccount);
        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(incomingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(false).when(incomingCall).isSelfManaged();
        doReturn(true).when(incomingCall).setState(anyInt(), any());

        // WHEN the incoming call is successfully added.
        mCallsManager.onSuccessfulIncomingCall(incomingCall);

        // THEN the incoming call is not using call filtering
        verify(incomingCall).setIsUsingCallFiltering(eq(false));
    }

    @SmallTest
    @Test
    public void testIsInEmergencyCallNetwork() {
        // Setup a call which the network identified as an emergency call.
        Call ongoingCall = addSpyCall();
        ongoingCall.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);

        assertFalse(ongoingCall.isEmergencyCall());
        assertTrue(ongoingCall.isNetworkIdentifiedEmergencyCall());
        assertTrue(mCallsManager.isInEmergencyCall());
    }

    @SmallTest
    @Test
    public void testIsInEmergencyCallLocal() {
        // Setup a call which is considered emergency based on its phone number.
        Call ongoingCall = addSpyCall();
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        ongoingCall.setHandle(Uri.fromParts("tel", "5551212", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(ongoingCall.isEmergencyCall());
        assertFalse(ongoingCall.isNetworkIdentifiedEmergencyCall());
        assertTrue(mCallsManager.isInEmergencyCall());
    }

    @SmallTest
    @Test
    public void testIsInEmergencyCallLocalDisconnected() {
        // Setup a call which is considered emergency based on its phone number.
        Call ongoingCall = addSpyCall();
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        ongoingCall.setHandle(Uri.fromParts("tel", "5551212", null),
                TelecomManager.PRESENTATION_ALLOWED);

        // and then set it as disconnected.
        ongoingCall.setState(CallState.DISCONNECTED, "");
        assertTrue(ongoingCall.isEmergencyCall());
        assertFalse(ongoingCall.isNetworkIdentifiedEmergencyCall());
        assertFalse(mCallsManager.isInEmergencyCall());
    }


    @SmallTest
    @Test
    public void testBlockNonEmergencyCallDuringEmergencyCall() throws Exception {
        // Setup a call which the network identified as an emergency call.
        Call ongoingCall = addSpyCall();
        ongoingCall.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
        assertTrue(mCallsManager.isInEmergencyCall());

        Call newCall = addSpyCall(CallState.NEW);
        ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
        doReturn(SIM_2_HANDLE.getComponentName()).when(service).getComponentName();

        // Ensure contact info lookup succeeds
        doAnswer(invocation -> {
            Uri handle = invocation.getArgument(0);
            CallerInfo info = new CallerInfo();
            CompletableFuture<Pair<Uri, CallerInfo>> callerInfoFuture = new CompletableFuture<>();
            callerInfoFuture.complete(new Pair<>(handle, info));
            return callerInfoFuture;
        }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class));

        // Ensure we have candidate phone account handle info.
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                SIM_1_HANDLE);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
        mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(),
                SIM_2_HANDLE.getUserHandle(), service);

        CompletableFuture<Call> callFuture = mCallsManager.startOutgoingCall(
                newCall.getHandle(), newCall.getTargetPhoneAccount(), new Bundle(),
                UserHandle.CURRENT, new Intent(), "com.test.stuff");

        verify(service, timeout(TEST_TIMEOUT)).createConnectionFailed(any());
        Call result = callFuture.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
        assertNull(result);
    }

    @SmallTest
    @Test
    public void testHasEmergencyCallIncomingCallPermitted() {
        // Setup a call which is considered emergency based on its phone number.
        Call ongoingCall = addSpyCall();
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        ongoingCall.setHandle(Uri.fromParts("tel", "5551212", null),
                TelecomManager.PRESENTATION_ALLOWED);
        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(SELF_MANAGED_HANDLE))
                .thenReturn(SELF_MANAGED_ACCOUNT);
        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(SIM_1_HANDLE))
                .thenReturn(SIM_1_ACCOUNT);

        assertFalse(mCallsManager.isIncomingCallPermitted(null, SELF_MANAGED_HANDLE));
        assertFalse(mCallsManager.isIncomingCallPermitted(null, SIM_1_HANDLE));
    }

    @SmallTest
    @Test
    public void testMakeRoomForOutgoingCallAudioProcessingInProgress() {
        Call ongoingCall = addSpyCall(SIM_2_HANDLE, CallState.AUDIO_PROCESSING);

        Call newEmergencyCall = createCall(SIM_1_HANDLE, CallState.NEW);
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        newEmergencyCall.setHandle(Uri.fromParts("tel", "5551213", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(mCallsManager.makeRoomForOutgoingEmergencyCall(newEmergencyCall));
        verify(ongoingCall).disconnect(anyLong(), anyString());
    }

    @SmallTest
    @Test
    public void testMakeRoomForEmergencyDuringIncomingCall() {
        Call ongoingCall = addSpyCall(SIM_2_HANDLE, CallState.RINGING);

        Call newEmergencyCall = createCall(SIM_1_HANDLE, CallState.NEW);
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        newEmergencyCall.setHandle(Uri.fromParts("tel", "5551213", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(mCallsManager.makeRoomForOutgoingEmergencyCall(newEmergencyCall));
        verify(ongoingCall).reject(anyBoolean(), any(), any());
    }

    @SmallTest
    @Test
    public void testMakeRoomForEmergencyCallSimulatedRingingInProgress() {
        Call ongoingCall = addSpyCall(SIM_2_HANDLE, CallState.SIMULATED_RINGING);

        Call newEmergencyCall = createCall(SIM_1_HANDLE, CallState.NEW);
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        newEmergencyCall.setHandle(Uri.fromParts("tel", "5551213", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(mCallsManager.makeRoomForOutgoingEmergencyCall(newEmergencyCall));
        verify(ongoingCall).disconnect(anyString());
    }

    @SmallTest
    @Test
    public void testMakeRoomForEmergencyCallSimulatedRingingInProgressHasBeenActive() {
        Call ongoingCall = addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
        ongoingCall.setState(CallState.SIMULATED_RINGING, "");

        Call newEmergencyCall = createCall(SIM_1_HANDLE, CallState.NEW);
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        newEmergencyCall.setHandle(Uri.fromParts("tel", "5551213", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(mCallsManager.makeRoomForOutgoingEmergencyCall(newEmergencyCall));
        verify(ongoingCall).reject(anyBoolean(), any(), any());
    }

    @SmallTest
    @Test
    public void testMakeRoomForEmergencyCallDuringActiveAndRingingCallDisconnectRinging() {
        when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(SIM_1_HANDLE))
                .thenReturn(SIM_1_ACCOUNT);
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        Call ringingCall = addSpyCall(SIM_1_HANDLE, CallState.RINGING);

        Call newEmergencyCall = createCall(SIM_1_HANDLE, CallState.NEW);
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(true);
        newEmergencyCall.setHandle(Uri.fromParts("tel", "5551213", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(mCallsManager.makeRoomForOutgoingEmergencyCall(newEmergencyCall));
        verify(ringingCall).reject(anyBoolean(), any(), any());
    }

    @SmallTest
    @Test
    public void testMakeRoomForOutgoingCallConnecting() {
        Call ongoingCall = addSpyCall(SIM_2_HANDLE, CallState.CONNECTING);

        Call newCall = createCall(SIM_1_HANDLE, CallState.NEW);
        when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
                .thenReturn(false);
        newCall.setHandle(Uri.fromParts("tel", "5551213", null),
                TelecomManager.PRESENTATION_ALLOWED);

        assertTrue(mCallsManager.makeRoomForOutgoingCall(newCall));
        verify(ongoingCall).disconnect(anyLong(), anyString());
    }

    /**
     * Verifies that changes to a {@link PhoneAccount}'s
     * {@link PhoneAccount#CAPABILITY_VIDEO_CALLING} capability will be reflected on a call.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testPhoneAccountVideoAvailability() throws InterruptedException {
        Call ongoingCall = addSpyCall(); // adds to SIM_2_ACCT
        LinkedBlockingQueue<Integer> capabilitiesQueue = new LinkedBlockingQueue<>(1);
        ongoingCall.addListener(new Call.ListenerBase() {
            @Override
            public void onConnectionCapabilitiesChanged(Call call) {
                try {
                    capabilitiesQueue.put(call.getConnectionCapabilities());
                } catch (InterruptedException e) {
                    fail();
                }
            }
        });

        // Lets make the phone account video capable.
        PhoneAccount videoCapableAccount = new PhoneAccount.Builder(SIM_2_ACCOUNT)
                .setCapabilities(SIM_2_ACCOUNT.getCapabilities()
                        | PhoneAccount.CAPABILITY_VIDEO_CALLING)
                .build();
        mCallsManager.getPhoneAccountListener().onPhoneAccountChanged(mPhoneAccountRegistrar,
                videoCapableAccount);
        // Absorb first update; it'll be from when phone account changed initially (since we force
        // a capabilities update.
        int newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);

        // Lets pretend the ConnectionService made it video capable as well.
        ongoingCall.setConnectionCapabilities(
                Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
        newCapabilities = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
        assertTrue((newCapabilities & Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
                == Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
        assertTrue(ongoingCall.isVideoCallingSupportedByPhoneAccount());
    }

    /**
     * Verifies that adding and removing a call triggers external calls to have capabilities
     * recalculated.
     */
    @SmallTest
    @Test
    public void testExternalCallCapabilitiesUpdated() throws InterruptedException {
        Call externalCall = addSpyCall(SIM_2_HANDLE, null, CallState.ACTIVE,
                Connection.CAPABILITY_CAN_PULL_CALL, Connection.PROPERTY_IS_EXTERNAL_CALL);
        LinkedBlockingQueue<Integer> capabilitiesQueue = new LinkedBlockingQueue<>(1);
        externalCall.addListener(new Call.ListenerBase() {
            @Override
            public void onConnectionCapabilitiesChanged(Call call) {
                try {
                    capabilitiesQueue.put(call.getConnectionCapabilities());
                } catch (InterruptedException e) {
                    fail();
                }
            }
        });

        Call call = createSpyCall(SIM_2_HANDLE, CallState.DIALING);
        doReturn(true).when(call).isEmergencyCall();
        mCallsManager.addCall(call);
        Integer result = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
        assertNotNull(result);
        assertEquals(0, Connection.CAPABILITY_CAN_PULL_CALL & result);

        mCallsManager.removeCall(call);
        result = capabilitiesQueue.poll(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
        assertNotNull(result);
        assertEquals(Connection.CAPABILITY_CAN_PULL_CALL,
                Connection.CAPABILITY_CAN_PULL_CALL & result);
    }

    /**
     * Verifies that speakers is disabled when there's no video capabilities, even if a video call
     * tried to place.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testSpeakerDisabledWhenNoVideoCapabilities() throws Exception {
        Call outgoingCall = addSpyCall(CallState.NEW);
        when(mPhoneAccountRegistrar.getPhoneAccount(
                any(PhoneAccountHandle.class), any(UserHandle.class))).thenReturn(SIM_1_ACCOUNT);
        mCallsManager.placeOutgoingCall(outgoingCall, TEST_ADDRESS, null, true,
                VideoProfile.STATE_TX_ENABLED);
        assertFalse(outgoingCall.getStartWithSpeakerphoneOn());
    }

    /**
     * Verify that a parent call will inherit the connect time of its children.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testParentInheritsChildConnectTime() throws Exception {
        Call callSim1 = createCall(SIM_1_HANDLE, null, CallState.ACTIVE);
        Call callSim2 = createCall(SIM_1_HANDLE, null, CallState.ACTIVE);
        callSim1.setConnectTimeMillis(100);

        // Pretend it is a conference made later.
        callSim2.setConnectTimeMillis(0);

        // Make the first call a child of the second (pretend conference).
        callSim1.setChildOf(callSim2);

        assertEquals(100, callSim2.getConnectTimeMillis());

        // Add another later call.
        Call callSim3 = createCall(SIM_1_HANDLE, null, CallState.ACTIVE);
        callSim3.setConnectTimeMillis(200);
        callSim3.setChildOf(callSim2);

        // Later call shouldn't impact parent.
        assertEquals(100, callSim2.getConnectTimeMillis());
    }

    /**
     * Make sure that CallsManager handles a screening result that has both
     * silence and screen-further set to true as a request to screen further.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testHandleSilenceVsBackgroundScreeningOrdering() throws Exception {
        Call screenedCall = mock(Call.class);
        Bundle extra = new Bundle();
        when(screenedCall.getIntentExtras()).thenReturn(extra);
        String appName = "blah";
        CallFilteringResult result = new CallFilteringResult.Builder()
                .setShouldAllowCall(true)
                .setShouldReject(false)
                .setShouldSilence(true)
                .setShouldScreenViaAudio(true)
                .setShouldAddToCallLog(true)
                .setShouldShowNotification(true)
                .setCallScreeningAppName(appName)
                .build();
        mCallsManager.onCallFilteringComplete(screenedCall, result, false);

        verify(mConnectionSvrFocusMgr).requestFocus(eq(screenedCall),
                nullable(ConnectionServiceFocusManager.RequestFocusCallback.class));
        verify(screenedCall).setAudioProcessingRequestingApp(appName);
    }

    /**
     * Verify the behavior of the {@link CallsManager#areFromSameSource(Call, Call)} method.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testAreFromSameSource() throws Exception {
        Call callSim1 = createCall(SIM_1_HANDLE, null, CallState.ACTIVE);
        Call callSim2 = createCall(SIM_2_HANDLE, null, CallState.ACTIVE);
        Call callVoip1 = createCall(VOIP_1_HANDLE, null, CallState.ACTIVE);
        assertTrue(CallsManager.areFromSameSource(callSim1, callSim1));
        assertTrue(CallsManager.areFromSameSource(callSim1, callSim2));
        assertFalse(CallsManager.areFromSameSource(callSim1, callVoip1));
        assertFalse(CallsManager.areFromSameSource(callSim2, callVoip1));

        Call callSim1ConnectionMgr1 = createCall(SIM_1_HANDLE, CONNECTION_MGR_1_HANDLE,
                CallState.ACTIVE);
        Call callSim2ConnectionMgr2 = createCall(SIM_2_HANDLE, CONNECTION_MGR_2_HANDLE,
                CallState.ACTIVE);
        assertFalse(CallsManager.areFromSameSource(callSim1ConnectionMgr1, callVoip1));
        assertFalse(CallsManager.areFromSameSource(callSim2ConnectionMgr2, callVoip1));
        // Even though the connection manager differs, the underlying telephony CS is the same
        // so hold/swap will still work as expected.
        assertTrue(CallsManager.areFromSameSource(callSim1ConnectionMgr1, callSim2ConnectionMgr2));

        // Sometimes connection managers have been known to also have calls
        Call callConnectionMgr = createCall(CONNECTION_MGR_2_HANDLE, CONNECTION_MGR_2_HANDLE,
                CallState.ACTIVE);
        assertTrue(CallsManager.areFromSameSource(callSim2ConnectionMgr2, callConnectionMgr));
    }

    /**
     * This test verifies a race condition seen with the new outgoing call broadcast.
     * The scenario occurs when an incoming call is handled by an app which receives the
     * NewOutgoingCallBroadcast.  That app cancels the call by modifying the new outgoing call
     * broadcast.  Meanwhile, it places that same call again, expecting that Telecom will reuse the
     * same same.  HOWEVER, if the system delays passing of the new outgoing call broadcast back to
     * Telecom, the app will have placed a new outgoing call BEFORE telecom is aware that the call
     * was cancelled.
     * The consequence of this is that in CallsManager#startOutgoingCall, when we first get the
     * call to reuse, it will come back empty.  Meanwhile, by the time we get into the various
     * completable futures, the call WILL be in the list of calls which can be reused.  Since the
     * reusable call was not found earlier on, we end up aborting the new outgoing call.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testReuseCallConcurrency() throws Exception {
        // Ensure contact info lookup succeeds
        doAnswer(invocation -> {
            Uri handle = invocation.getArgument(0);
            CallerInfo info = new CallerInfo();
            CompletableFuture<Pair<Uri, CallerInfo>> callerInfoFuture = new CompletableFuture<>();
            callerInfoFuture.complete(new Pair<>(handle, info));
            return callerInfoFuture;
        }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class));

        // Ensure we have candidate phone account handle info.
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                SIM_1_HANDLE);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));

        // Let's add an existing call which is in connecting state; this emulates the case where
        // we have an outgoing call which we have not yet disconnected as a result of the new
        // outgoing call broadcast cancelling the call.
        Call outgoingCall = addSpyCall(CallState.CONNECTING);

        final CountDownLatch latch = new CountDownLatch(1);
        // Get the handler for the main looper, which is the same one the CallsManager will use.
        // We'll post a little something to block up the handler for now.  This prevents
        // startOutgoingCall from process it's completablefutures.
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(() -> {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // Now while the main handler is blocked up we'll start another outgoing call.
        CompletableFuture<Call> callFuture = mCallsManager.startOutgoingCall(
                outgoingCall.getHandle(), outgoingCall.getTargetPhoneAccount(), new Bundle(),
                UserHandle.CURRENT, new Intent(), "com.test.stuff");

        // And we'll add the initial outgoing call to the list of pending disconnects; this
        // emulates a scenario where the pending disconnect call came in AFTER this call began.
        mCallsManager.addToPendingCallsToDisconnect(outgoingCall);

        // And we'll unblock the handler; this will let all the startOutgoingCall futures to happen.
        latch.countDown();

        // Wait for the future to become the present.
        callFuture.join();

        // We should have gotten a call out of this; if we did not then it means the call was
        // aborted.
        assertNotNull(callFuture.get());

        // And the original call should be disconnected now.
        assertEquals(CallState.DISCONNECTED, outgoingCall.getState());
    }

    /**
     * Ensures that if we have two calls hosted by the same connection manager, but with
     * different target phone accounts, we can swap between them.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testSwapCallsWithSameConnectionMgr() throws Exception {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCall(SIM_1_HANDLE, CONNECTION_MGR_1_HANDLE, CallState.ACTIVE);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call which has the same connection manager, but a different target phone
        // account.  We have seen cases where a connection mgr adds its own calls and these can
        // be problematic for swapping.
        Call heldCall = addSpyCall(CONNECTION_MGR_1_HANDLE, CONNECTION_MGR_1_HANDLE,
                CallState.ON_HOLD);

        // WHEN unhold the held call
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is held
        verify(ongoingCall).hold(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold(any());
    }

    /**
     * Verifies we inform the InCallService on local disconnect.
     * @throws Exception
     */
    @SmallTest
    @Test
    public void testRequestDisconnect() throws Exception {
        CallsManager.CallsManagerListener listener = mock(CallsManager.CallsManagerListener.class);
        mCallsManager.addListener(listener);

        Call ongoingCall = addSpyCall(CallState.ACTIVE);
        mCallsManager.addCall(ongoingCall);

        mCallsManager.disconnectCall(ongoingCall);
        // Seems odd, but ultimately the call state is still active even though it is locally
        // disconnecting.
        verify(listener).onCallStateChanged(eq(ongoingCall), eq(CallState.ACTIVE),
                eq(CallState.ACTIVE));
    }

    /**
     * Verifies where a call diagnostic service is NOT in use that we don't try to relay to the
     * CallDiagnosticService and that we get a synchronous disconnect.
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testDisconnectCallSynchronous() throws Exception {
        Call callSpy = addSpyCall();
        callSpy.setIsSimCall(true);
        when(mCallDiagnosticServiceController.isConnected()).thenReturn(false);
        mCallsManager.markCallAsDisconnected(callSpy, new DisconnectCause(DisconnectCause.ERROR));

        verify(mCallDiagnosticServiceController, never()).onCallDisconnected(any(Call.class),
                any(DisconnectCause.class));
        verify(callSpy).setDisconnectCause(any(DisconnectCause.class));
    }

    @MediumTest
    @Test
    public void testDisconnectCallAsynchronous() throws Exception {
        Call callSpy = addSpyCall();
        callSpy.setIsSimCall(true);
        when(mCallDiagnosticServiceController.isConnected()).thenReturn(true);
        when(mCallDiagnosticServiceController.onCallDisconnected(any(Call.class),
                any(DisconnectCause.class))).thenReturn(true);
        mCallsManager.markCallAsDisconnected(callSpy, new DisconnectCause(DisconnectCause.ERROR));

        verify(mCallDiagnosticServiceController).onCallDisconnected(any(Call.class),
                any(DisconnectCause.class));
        verify(callSpy, never()).setDisconnectCause(any(DisconnectCause.class));
    }
    
    /**
     * Verifies that if call state goes from DIALING to DISCONNECTED, and a call diagnostic service
     * IS in use, it would call onCallDisconnected of the CallDiagnosticService
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testDisconnectDialingCall() throws Exception {
        Call callSpy = addSpyCall(CallState.DIALING);
        callSpy.setIsSimCall(true);
        when(mCallDiagnosticServiceController.isConnected()).thenReturn(true);
        when(mCallDiagnosticServiceController.onCallDisconnected(any(Call.class),
                any(DisconnectCause.class))).thenReturn(true);
        mCallsManager.markCallAsDisconnected(callSpy, new DisconnectCause(DisconnectCause.ERROR));

        verify(mCallDiagnosticServiceController).onCallDisconnected(any(Call.class),
                any(DisconnectCause.class));
        verify(callSpy, never()).setDisconnectCause(any(DisconnectCause.class));
    }

    @Test
    public void testIsInSelfManagedCallOnlyManaged() {
        Call managedCall = createCall(SIM_1_HANDLE, CallState.ACTIVE);
        managedCall.setIsSelfManaged(false);
        mCallsManager.addCall(managedCall);

        // Certainly nothing from the self managed handle.
        assertFalse(mCallsManager.isInSelfManagedCall(
                SELF_MANAGED_HANDLE.getComponentName().getPackageName(),
                SELF_MANAGED_HANDLE.getUserHandle()));
        // And nothing in a random other package.
        assertFalse(mCallsManager.isInSelfManagedCall(
                "com.foo",
                SELF_MANAGED_HANDLE.getUserHandle()));
        // And this method is only checking self managed not managed.
        assertFalse(mCallsManager.isInSelfManagedCall(
                SIM_1_HANDLE.getComponentName().getPackageName(),
                SELF_MANAGED_HANDLE.getUserHandle()));
    }

    @Test
    public void testIsInSelfManagedCallOnlySelfManaged() {
        Call selfManagedCall = createCall(SELF_MANAGED_HANDLE, CallState.ACTIVE);
        selfManagedCall.setIsSelfManaged(true);
        mCallsManager.addCall(selfManagedCall);

        assertTrue(mCallsManager.isInSelfManagedCall(
                SELF_MANAGED_HANDLE.getComponentName().getPackageName(),
                SELF_MANAGED_HANDLE.getUserHandle()));
        assertFalse(mCallsManager.isInSelfManagedCall(
                "com.foo",
                SELF_MANAGED_HANDLE.getUserHandle()));
        assertFalse(mCallsManager.isInSelfManagedCall(
                SIM_1_HANDLE.getComponentName().getPackageName(),
                SELF_MANAGED_HANDLE.getUserHandle()));

        Call managedCall = createCall(SIM_1_HANDLE, CallState.ACTIVE);
        managedCall.setIsSelfManaged(false);
        mCallsManager.addCall(managedCall);

        // Still not including managed
        assertFalse(mCallsManager.isInSelfManagedCall(
                SIM_1_HANDLE.getComponentName().getPackageName(),
                SELF_MANAGED_HANDLE.getUserHandle()));

        // Also shouldn't be something in another user's version of the same package.
        assertFalse(mCallsManager.isInSelfManagedCall(
                SELF_MANAGED_HANDLE.getComponentName().getPackageName(),
                new UserHandle(90210)));
    }

    private Call addSpyCall() {
        return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
    }

    private Call addSpyCall(int initialState) {
        return addSpyCall(SIM_2_HANDLE, initialState);
    }

    private Call addSpyCall(PhoneAccountHandle targetPhoneAccount, int initialState) {
        return addSpyCall(targetPhoneAccount, null, initialState, 0 /*caps*/, 0 /*props*/);
    }

    private Call addSpyCall(PhoneAccountHandle targetPhoneAccount,
            PhoneAccountHandle connectionMgrAcct, int initialState) {
        return addSpyCall(targetPhoneAccount, connectionMgrAcct, initialState, 0 /*caps*/,
                0 /*props*/);
    }

    private Call addSpyCall(PhoneAccountHandle targetPhoneAccount,
            PhoneAccountHandle connectionMgrAcct, int initialState,
            int connectionCapabilities, int connectionProperties) {
        Call ongoingCall = createCall(targetPhoneAccount, connectionMgrAcct, initialState);
        ongoingCall.setConnectionProperties(connectionProperties);
        ongoingCall.setConnectionCapabilities(connectionCapabilities);
        Call callSpy = Mockito.spy(ongoingCall);

        // Mocks some methods to not call the real method.
        doNothing().when(callSpy).unhold();
        doNothing().when(callSpy).hold();
        doNothing().when(callSpy).answer(Matchers.anyInt());
        doNothing().when(callSpy).setStartWithSpeakerphoneOn(Matchers.anyBoolean());

        mCallsManager.addCall(callSpy);
        return callSpy;
    }

    private Call createSpyCall(PhoneAccountHandle handle, int initialState) {
        Call ongoingCall = createCall(handle, initialState);
        Call callSpy = Mockito.spy(ongoingCall);

        // Mocks some methods to not call the real method.
        doNothing().when(callSpy).unhold();
        doNothing().when(callSpy).hold();
        doNothing().when(callSpy).disconnect();
        doNothing().when(callSpy).answer(Matchers.anyInt());
        doNothing().when(callSpy).setStartWithSpeakerphoneOn(Matchers.anyBoolean());

        return callSpy;
    }

    private Call createCall(PhoneAccountHandle targetPhoneAccount, int initialState) {
        return createCall(targetPhoneAccount, null /* connectionManager */, initialState);
    }

    private Call createCall(PhoneAccountHandle targetPhoneAccount,
            PhoneAccountHandle connectionManagerAccount, int initialState) {
        Call ongoingCall = new Call(String.format("TC@%d", sCallId++), /* callId */
                mContext,
                mCallsManager,
                mLock, /* ConnectionServiceRepository */
                null,
                mPhoneNumberUtilsAdapter,
                TEST_ADDRESS,
                null /* GatewayInfo */,
                connectionManagerAccount,
                targetPhoneAccount,
                Call.CALL_DIRECTION_INCOMING,
                false /* shouldAttachToExistingConnection*/,
                false /* isConference */,
                mClockProxy,
                mToastFactory);
        ongoingCall.setState(initialState, "just cuz");
        return ongoingCall;
    }

    private void verifyFocusRequestAndExecuteCallback(Call call) {
        ArgumentCaptor<CallsManager.RequestCallback> captor =
                ArgumentCaptor.forClass(CallsManager.RequestCallback.class);
        verify(mConnectionSvrFocusMgr).requestFocus(eq(call), captor.capture());
        CallsManager.RequestCallback callback = captor.getValue();
        callback.onRequestFocusDone(call);
    }

    private void setupMsimAccounts() {
        TelephonyManager mockTelephonyManager = mComponentContextFixture.getTelephonyManager();
        when(mockTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims()).thenReturn(1);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
        when(mPhoneAccountRegistrar.getSimPhoneAccountsOfCurrentUser()).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
    }
}
