/*
 * Copyright (C) 2015 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 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.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.IContentProvider;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.provider.BlockedNumberContract;
import android.telecom.Call;
import android.telecom.CallAudioState;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.ParcelableCall;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;

import androidx.test.filters.FlakyTest;

import com.android.internal.telecom.IInCallAdapter;
import android.telecom.CallerInfo;

import com.google.common.base.Predicate;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

/**
 * Performs various basic call tests in Telecom.
 */
@RunWith(JUnit4.class)
public class BasicCallTests extends TelecomSystemTest {
    private static final String TEST_BUNDLE_KEY = "android.telecom.extra.TEST";
    private static final String TEST_EVENT = "android.telecom.event.TEST";

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
    }

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

    @LargeTest
    @Test
    public void testSingleOutgoingCallLocalDisconnect() throws Exception {
        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);

        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
        assertEquals(Call.STATE_DISCONNECTING,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTING,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
        assertEquals(TEST_CONNECT_TIME,
                mInCallServiceFixtureX.getCall(ids.mCallId).getConnectTimeMillis());
        assertEquals(TEST_CONNECT_TIME,
                mInCallServiceFixtureY.getCall(ids.mCallId).getConnectTimeMillis());
        assertEquals(TEST_CREATE_TIME,
                mInCallServiceFixtureX.getCall(ids.mCallId).getCreationTimeMillis());
        assertEquals(TEST_CREATE_TIME,
                mInCallServiceFixtureY.getCall(ids.mCallId).getCreationTimeMillis());

        verifyNoBlockChecks();
    }

    @LargeTest
    @Test
    public void testSingleOutgoingCallRemoteDisconnect() throws Exception {
        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
        verifyNoBlockChecks();
    }

    /**
     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
     * audio-only call.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testTelecomManagerAcceptRingingCall() throws Exception {
        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                mConnectionServiceFixtureA);

        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        // Use TelecomManager API to answer the ringing call.
        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
        telecomManager.acceptRingingCall();

        waitForHandlerAction(mTelecomSystem.getCallsManager()
                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);

        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .answer(eq(ids.mConnectionId), any());
        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);

        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
    }

    /**
     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
     * video call, which should be answered as video.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testTelecomManagerAcceptRingingVideoCall() throws Exception {
        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);

        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
        // answer using whatever video state the ringing call requests.
        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
        telecomManager.acceptRingingCall();

        // Answer video API should be called
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any());
        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);

        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
    }

    /**
     * Tests the {@link TelecomManager#acceptRingingCall(int)} API.  Tests answering a video call
     * as an audio call.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception {
        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);

        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        // Use TelecomManager API to answer the ringing call.
        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
        telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);

        waitForHandlerAction(mTelecomSystem.getCallsManager()
                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);

        // The generic answer method on the ConnectionService is used to answer audio-only calls.
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .answer(eq(ids.mConnectionId), any());
        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);

        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
    }

    /**
     * Tests the {@link TelecomManager#acceptRingingCall()} API.  Tests simple case of an incoming
     * video call, where an attempt is made to answer with an invalid video state.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception {
        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);

        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        // Use TelecomManager API to answer the ringing call; the default expected behavior is to
        // answer using whatever video state the ringing call requests.
        TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble()
                .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
        telecomManager.acceptRingingCall(999 /* invalid videostate */);

        waitForHandlerAction(mTelecomSystem.getCallsManager()
                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);

        // Answer video API should be called
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any());
        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
    }

    @LargeTest
    @Test
    public void testSingleIncomingCallLocalDisconnect() throws Exception {
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
        assertEquals(Call.STATE_DISCONNECTING,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTING,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);

        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    }

    @LargeTest
    @Test
    public void testSingleIncomingCallRemoteDisconnect() throws Exception {
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    }

    @LargeTest
    @Test
    public void testIncomingEmergencyCallback() throws Exception {
        // Make an outgoing emergency call
        String phoneNumber = "650-555-1212";
        IdPair ids = startAndMakeDialingEmergencyCall(phoneNumber,
                mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA);
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);

        // Incoming call should be marked as a potential emergency callback
        Bundle extras = new Bundle();
        extras.putParcelable(
                TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null));
        mTelecomSystem.getTelecomServiceImpl().getBinder()
                .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        ArgumentCaptor<ConnectionRequest> connectionRequestCaptor
            = ArgumentCaptor.forClass(ConnectionRequest.class);
        verify(mConnectionServiceFixtureA.getTestDouble())
                .createConnection(any(PhoneAccountHandle.class), anyString(),
                        connectionRequestCaptor.capture(), eq(true), eq(false), any());

        assertTrue(connectionRequestCaptor.getValue().getExtras().containsKey(
            android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS));
        assertTrue(connectionRequestCaptor.getValue().getExtras().getLong(
            android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS, 0) > 0);
        assertTrue(connectionRequestCaptor.getValue().getExtras().containsKey(
            TelecomManager.EXTRA_INCOMING_CALL_ADDRESS));
    }

    @LargeTest
    @Test
    public void testOutgoingCallAndSelectPhoneAccount() throws Exception {
        // Remove default PhoneAccount so that the Call moves into the correct
        // SELECT_PHONE_ACCOUNT state.
        mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount(
                null, Process.myUserHandle());
        int startingNumConnections = mConnectionServiceFixtureA.mConnectionById.size();
        int startingNumCalls = mInCallServiceFixtureX.mCallById.size();
        String callId = startOutgoingPhoneCallWithNoPhoneAccount("650-555-1212",
                mConnectionServiceFixtureA);
        mTelecomSystem.getCallsManager().getLatestPreAccountSelectionFuture().join();
        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
                mInCallServiceFixtureX.getCall(callId).getState());
        assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT,
                mInCallServiceFixtureY.getCall(callId).getState());
        mInCallServiceFixtureX.mInCallAdapter.phoneAccountSelected(callId,
                mPhoneAccountA0.getAccountHandle(), false);
        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        verifyAndProcessOutgoingCallBroadcast(mPhoneAccountA0.getAccountHandle());

        IdPair ids = outgoingCallPhoneAccountSelected(mPhoneAccountA0.getAccountHandle(),
                startingNumConnections, startingNumCalls, mConnectionServiceFixtureA);

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DISCONNECTED,
                mInCallServiceFixtureY.getCall(ids.mCallId).getState());
    }

    @FlakyTest
    @LargeTest
    @Test
    public void testIncomingCallFromContactWithSendToVoicemailIsRejected() throws Exception {
        Bundle extras = new Bundle();
        extras.putParcelable(
                TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null));
        mTelecomSystem.getTelecomServiceImpl().getBinder()
                .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        verify(mConnectionServiceFixtureA.getTestDouble())
                .createConnection(any(PhoneAccountHandle.class), anyString(),
                        any(ConnectionRequest.class), eq(true), eq(false), any());

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());

        CallerInfo sendToVoicemailCallerInfo = new CallerInfo();
        sendToVoicemailCallerInfo.shouldSendToVoicemail = true;
        sendToVoicemailCallerInfo.contactExists = true;
        mCallerInfoAsyncQueryFactoryFixture.setResponse(sendToVoicemailCallerInfo);
        for (CallerInfoAsyncQueryFactoryFixture.Request request :
                mCallerInfoAsyncQueryFactoryFixture.mRequests) {
            request.replyWithCallerInfo(sendToVoicemailCallerInfo);
        }

        assertTrueWithTimeout(new Predicate<Void>() {
            @Override
            public boolean apply(Void aVoid) {
                return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1;
            }
        });
        assertTrueWithTimeout(new Predicate<Void>() {
            @Override
            public boolean apply(Void aVoid) {
                return mMissedCallNotifier.missedCallsNotified.size() == 1;
            }
        });

        verify(mInCallServiceFixtureX.getTestDouble(), never())
                .setInCallAdapter(any(IInCallAdapter.class));
        verify(mInCallServiceFixtureY.getTestDouble(), never())
                .setInCallAdapter(any(IInCallAdapter.class));
    }

    @LargeTest
    @Test
    public void testIncomingCallCallerInfoLookupTimesOutIsAllowed() throws Exception {
        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
        Bundle extras = new Bundle();
        extras.putParcelable(
                TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null));
        mTelecomSystem.getTelecomServiceImpl().getBinder()
                .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        verify(mConnectionServiceFixtureA.getTestDouble())
                .createConnection(any(PhoneAccountHandle.class), anyString(),
                        any(ConnectionRequest.class), eq(true), eq(false), any());

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        // Never reply to the caller info lookup.
        assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());

        verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
                .setInCallAdapter(any(IInCallAdapter.class));
        verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
                .setInCallAdapter(any(IInCallAdapter.class));

        assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size());
        assertEquals(0, mMissedCallNotifier.missedCallsNotified.size());

        assertTrueWithTimeout(new Predicate<Void>() {
            @Override
            public boolean apply(Void v) {
                return mInCallServiceFixtureX.mInCallAdapter != null;
            }
        });

        verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
                .addCall(any(ParcelableCall.class));
        verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
                .addCall(any(ParcelableCall.class));

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
        disconnectCall(mInCallServiceFixtureX.mLatestCallId,
                mConnectionServiceFixtureA.mLatestConnectionId);
    }

    @LargeTest
    @Test
    @FlakyTest
    @Ignore("b/189904580")
    public void testIncomingCallFromBlockedNumberIsRejected() throws Exception {
        String phoneNumber = "650-555-1212";
        blockNumber(phoneNumber);

        Bundle extras = new Bundle();
        extras.putParcelable(
                TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null));
        mTelecomSystem.getTelecomServiceImpl().getBinder()
                .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras);

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        verify(mConnectionServiceFixtureA.getTestDouble())
                .createConnection(any(PhoneAccountHandle.class), anyString(),
                        any(ConnectionRequest.class), eq(true), eq(false), any());

        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);

        assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
        for (CallerInfoAsyncQueryFactoryFixture.Request request :
                mCallerInfoAsyncQueryFactoryFixture.mRequests) {
            request.reply();
        }

        assertTrueWithTimeout(new Predicate<Void>() {
            @Override
            public boolean apply(Void aVoid) {
                return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1;
            }
        });
        assertEquals(0, mMissedCallNotifier.missedCallsNotified.size());

        verify(mInCallServiceFixtureX.getTestDouble(), never())
                .setInCallAdapter(any(IInCallAdapter.class));
        verify(mInCallServiceFixtureY.getTestDouble(), never())
                .setInCallAdapter(any(IInCallAdapter.class));
    }

    @LargeTest
    @Test
    public void testIncomingCallBlockCheckTimesoutIsAllowed() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        String phoneNumber = "650-555-1212";
        blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() {
            @Override
            public Bundle answer(InvocationOnMock invocation) throws Throwable {
                latch.await(TEST_TIMEOUT * 2, TimeUnit.MILLISECONDS);
                Bundle bundle = new Bundle();
                bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true);
                return bundle;
            }
        });

        IdPair ids = startAndMakeActiveIncomingCall(
                phoneNumber, mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        latch.countDown();

        assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size());
        assertEquals(0, mMissedCallNotifier.missedCallsNotified.size());
        disconnectCall(ids.mCallId, ids.mConnectionId);
    }

    public void do_testDeadlockOnOutgoingCall() throws Exception {
        final IdPair ids = startOutgoingPhoneCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA,
                Process.myUserHandle());
        rapidFire(
                new Runnable() {
                    @Override
                    public void run() {
                        while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) {
                            mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply();
                        }
                    }
                },
                new Runnable() {
                    @Override
                    public void run() {
                        try {
                            mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
                        } catch (Exception e) {
                            Log.e(this, e, "");
                        }
                    }
                });
    }

    @LargeTest
    @Test
    public void testIncomingThenOutgoingCalls() throws Exception {
        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
        IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);

        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
    }

    @LargeTest
    @Test
    public void testOutgoingThenIncomingCalls() throws Exception {
        // TODO: We have to use the same PhoneAccount for both; see http://b/18461539
        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);
        verify(mConnectionServiceFixtureA.getTestDouble())
                .hold(eq(outgoing.mConnectionId), any());
        mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state =
                Connection.STATE_HOLDING;
        mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId);
        assertEquals(Call.STATE_HOLDING,
                mInCallServiceFixtureX.getCall(outgoing.mCallId).getState());
        assertEquals(Call.STATE_HOLDING,
                mInCallServiceFixtureY.getCall(outgoing.mCallId).getState());

        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId);
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId);
    }

    @LargeTest
    @Test
    public void testAudioManagerOperations() throws Exception {
        AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble()
                .getApplicationContext().getSystemService(Context.AUDIO_SERVICE);

        IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);

        verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt());
        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
                .setMode(AudioManager.MODE_IN_CALL);

        mInCallServiceFixtureX.mInCallAdapter.mute(true);
        verify(mAudioService, timeout(TEST_TIMEOUT))
                .setMicrophoneMute(eq(true), any(String.class), any(Integer.class));
        mInCallServiceFixtureX.mInCallAdapter.mute(false);
        verify(mAudioService, timeout(TEST_TIMEOUT))
                .setMicrophoneMute(eq(false), any(String.class), any(Integer.class));

        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null);
        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
        verify(audioManager, timeout(TEST_TIMEOUT))
                .setSpeakerphoneOn(true);
        mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null);
        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
        // setSpeakerPhoneOn(false) gets called once during the call initiation phase
        verify(audioManager, timeout(TEST_TIMEOUT).atLeast(1))
                .setSpeakerphoneOn(false);

        mConnectionServiceFixtureA.
                sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);

        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioModeStateMachine().getHandler(), TEST_TIMEOUT);
        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
        verify(audioManager, timeout(TEST_TIMEOUT))
                .abandonAudioFocusForCall();
        verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
                .setMode(AudioManager.MODE_NORMAL);
    }

    private void rapidFire(Runnable... tasks) {
        final CyclicBarrier barrier = new CyclicBarrier(tasks.length);
        final CountDownLatch latch = new CountDownLatch(tasks.length);
        for (int i = 0; i < tasks.length; i++) {
            final Runnable task = tasks[i];
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        barrier.await();
                        task.run();
                    } catch (InterruptedException | BrokenBarrierException e){
                        Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
                    } finally {
                        latch.countDown();
                    }
                }
            }).start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            Log.e(BasicCallTests.this, e, "Unexpectedly interrupted");
        }
    }

    @MediumTest
    @Test
    public void testBasicConferenceCall() throws Exception {
        makeConferenceCall();
    }

    @MediumTest
    @Test
    public void testAddCallToConference1() throws Exception {
        ParcelableCall conferenceCall = makeConferenceCall();
        IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference
        mInCallServiceFixtureX.getInCallAdapter().conference(
                conferenceCall.getId(), callId3.mCallId);
        Thread.sleep(200);

        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
        assertEquals(conferenceCall.getId(), call3.getParentCallId());
        assertEquals(3, updatedConference.getChildCallIds().size());
        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
    }

    @MediumTest
    @Test
    public void testAddCallToConference2() throws Exception {
        ParcelableCall conferenceCall = makeConferenceCall();
        IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        mInCallServiceFixtureX.getInCallAdapter()
                .conference(callId3.mCallId, conferenceCall.getId());
        Thread.sleep(200);

        ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId);
        ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId());
        assertEquals(conferenceCall.getId(), call3.getParentCallId());
        assertEquals(3, updatedConference.getChildCallIds().size());
        assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId));
    }

    /**
     * Tests the {@link Call#pullExternalCall()} API.  Verifies that if a call is not an external
     * call, no pull call request is made to the connection service.
     *
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testPullNonExternalCall() throws Exception {
        // TODO: Revisit this unit test once telecom support for filtering external calls from
        // InCall services is implemented.
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        // Attempt to pull the call and verify the API call makes it through
        mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
        Thread.sleep(TEST_TIMEOUT);
        verify(mConnectionServiceFixtureA.getTestDouble(), never())
                .pullExternalCall(eq(ids.mCallId), any());
    }

    /**
     * Tests the {@link Connection#sendConnectionEvent(String, Bundle)} API.
     *
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testSendConnectionEventNull() throws Exception {
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, null);
        verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
                .onConnectionEvent(ids.mCallId, TEST_EVENT, null);
    }

    /**
     * Tests the {@link Connection#sendConnectionEvent(String, Bundle)} API.
     *
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testSendConnectionEventNotNull() throws Exception {
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        Bundle testBundle = new Bundle();
        testBundle.putString(TEST_BUNDLE_KEY, "TEST");

        ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
        mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, testBundle);
        verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
                .onConnectionEvent(eq(ids.mCallId), eq(TEST_EVENT), bundleArgumentCaptor.capture());
        assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY));
    }

    /**
     * Tests the {@link Call#sendCallEvent(String, Bundle)} API.
     *
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testSendCallEventNull() throws Exception {
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 26, null);
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT), isNull(Bundle.class), any());
    }

    /**
     * Tests the {@link Call#sendCallEvent(String, Bundle)} API.
     *
     * @throws Exception
     */
    @MediumTest
    @Test
    public void testSendCallEventNonNull() throws Exception {
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        Bundle testBundle = new Bundle();
        testBundle.putString(TEST_BUNDLE_KEY, "TEST");

        ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);
        mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 26,
                testBundle);
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT),
                        bundleArgumentCaptor.capture(), any());
        assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY));
    }

    private void blockNumber(String phoneNumber) throws Exception {
        blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() {
            @Override
            public Bundle answer(InvocationOnMock invocation) throws Throwable {
                Bundle bundle = new Bundle();
                bundle.putInt(BlockedNumberContract.RES_BLOCK_STATUS,
                        BlockedNumberContract.STATUS_BLOCKED_IN_LIST);
                return bundle;
            }
        });
    }

    private void blockNumberWithAnswer(String phoneNumber, Answer answer) throws Exception {
        when(getBlockedNumberProvider().call(
                any(),
                anyString(),
                eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
                eq(phoneNumber),
                nullable(Bundle.class))).thenAnswer(answer);
    }

    private void verifyNoBlockChecks() {
        verifyZeroInteractions(getBlockedNumberProvider());
    }

    private IContentProvider getBlockedNumberProvider() {
        return mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY);
    }

    private void disconnectCall(String callId, String connectionId) throws Exception {
        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
        mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL);
        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState());
        assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState());
        assertEquals(TEST_CREATE_TIME,
                mInCallServiceFixtureX.getCall(callId).getCreationTimeMillis());
        assertEquals(TEST_CREATE_TIME,
                mInCallServiceFixtureY.getCall(callId).getCreationTimeMillis());
    }

    /**
     * Tests to make sure that the Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is set on a
     * Call that is based on a Connection with the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY
     * property set.
     */
    @MediumTest
    @Test
    public void testCdmaEnhancedPrivacyVoiceCall() throws Exception {
        mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
                Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY;

        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        assertTrue(Call.Details.hasProperty(
                mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(),
                Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY));
    }

    /**
     * Tests to make sure that Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY is dropped
     * when the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is removed from the Connection.
     */
    @MediumTest
    @Test
    public void testDropCdmaEnhancedPrivacyVoiceCall() throws Exception {
        mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
                Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY;

        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        mConnectionServiceFixtureA.mLatestConnection.setConnectionProperties(0);

        assertFalse(Call.Details.hasProperty(
                mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(),
                Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY));
    }

    /**
     * Tests the {@link Call#pullExternalCall()} API.  Ensures that an external call which is
     * pullable can be pulled.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testPullExternalCall() throws Exception {
        // TODO: Revisit this unit test once telecom support for filtering external calls from
        // InCall services is implemented.
        mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities =
                Connection.CAPABILITY_CAN_PULL_CALL;
        mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
                Connection.PROPERTY_IS_EXTERNAL_CALL;

        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        // Attempt to pull the call and verify the API call makes it through
        mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .pullExternalCall(eq(ids.mConnectionId), any());
    }

    /**
     * Tests the {@link Call#pullExternalCall()} API.  Verifies that if an external call is not
     * marked as pullable that the connection service does not get an API call to pull the external
     * call.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testPullNonPullableExternalCall() throws Exception {
        // TODO: Revisit this unit test once telecom support for filtering external calls from
        // InCall services is implemented.
        mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties =
                Connection.PROPERTY_IS_EXTERNAL_CALL;

        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        // Attempt to pull the call and verify the API call makes it through
        mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId);
        Thread.sleep(TEST_TIMEOUT);
        verify(mConnectionServiceFixtureA.getTestDouble(), never())
                .pullExternalCall(eq(ids.mConnectionId), any());
    }

    /**
     * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and
     * then subsequently selects a PhoneAccount which supports video calling.
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testOutgoingCallSelectPhoneAccountVideo() throws Exception {
        startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
                null, mConnectionServiceFixtureA,
                Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                .iterator().next();
        assert(call.isVideoCallingSupportedByPhoneAccount());
        assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());

        // Change the phone account to one which supports video calling.
        call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
        assert(call.isVideoCallingSupportedByPhoneAccount());
        assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
    }

    /**
     * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and
     * then subsequently selects a PhoneAccount which does not support video calling.
     * @throws Exception
     */
    @FlakyTest
    @LargeTest
    @Test
    public void testOutgoingCallSelectPhoneAccountNoVideo() throws Exception {
        startOutgoingPhoneCallPendingCreateConnection("650-555-1212",
                null, mConnectionServiceFixtureA,
                Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL);
        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
                .iterator().next();
        assert(call.isVideoCallingSupportedByPhoneAccount());
        assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());

        // Change the phone account to one which does not support video calling.
        call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
        assert(!call.isVideoCallingSupportedByPhoneAccount());
        assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
    }

    /**
     * Basic test to ensure that a self-managed ConnectionService can place a call.
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testSelfManagedOutgoing() throws Exception {
        PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", phoneAccountHandle,
                mConnectionServiceFixtureA);

        // The InCallService should not know about the call since its self-managed.
        assertNull(mInCallServiceFixtureX.getCall(ids.mCallId));
    }

    /**
     * Basic test to ensure that a self-managed ConnectionService can add an incoming call.
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testSelfManagedIncoming() throws Exception {
        PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle,
                mConnectionServiceFixtureA);

        // The InCallService should not know about the call since its self-managed.
        assertNull(mInCallServiceFixtureX.getCall(ids.mCallId));
    }

    /**
     * Basic test to ensure that when there are no calls, we permit outgoing calls by a self managed
     * CS.
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testIsOutgoingCallPermitted() throws Exception {
        assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
                .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle()));
    }

    /**
     * Ensure if there is a holdable call ongoing we'll be able to place another call.
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testIsOutgoingCallPermittedOngoingHoldable() throws Exception {
        // Start a regular call; the self-managed CS can make a call now since ongoing call can be
        // held
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
                .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle()));
    }

    /**
     * Ensure if there is an unholdable call we can't place another call.
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testIsOutgoingCallPermittedOngoingUnHoldable() throws Exception {
        // Start a regular call; the self-managed CS can't make a call now because the ongoing call
        // can't be held.
        mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 0;
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
                .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle()));
    }

    /**
     * Basic to verify audio route gets reset to baseline when emergency call placed while a
     * self-managed call is underway.
     * @throws Exception
     */
    @LargeTest
    @Test
    @FlakyTest
    public void testDisconnectSelfManaged() throws Exception {
        // Add a self-managed call.
        PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
        startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle,
                mConnectionServiceFixtureA);
        Connection connection = mConnectionServiceFixtureA.mLatestConnection;

        // Route self-managed call to speaker.
        connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
        waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
                TEST_TIMEOUT);

        // Place an emergency call.
        startAndMakeDialingEmergencyCall("650-555-1212", mPhoneAccountE0.getAccountHandle(),
                mConnectionServiceFixtureA);

        // Should have reverted back to earpiece.
        assertTrueWithTimeout(new Predicate<Void>() {
            @Override
            public boolean apply(Void aVoid) {
                return mInCallServiceFixtureX.mCallAudioState.getRoute()
                        == CallAudioState.ROUTE_EARPIECE;
            }
        });
    }

    /**
     * Tests the {@link Call#deflect} API.  Verifies that if a call is incoming,
     * and deflect API is called, then request is made to the connection service.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testDeflectCallWhenIncoming() throws Exception {
        Uri deflectAddress = Uri.parse("tel:650-555-1214");
        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                mConnectionServiceFixtureA);

        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
        // Attempt to deflect the call and verify the API call makes it through
        mInCallServiceFixtureX.mInCallAdapter.deflectCall(ids.mCallId, deflectAddress);
        verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                .deflect(eq(ids.mConnectionId), eq(deflectAddress), any());
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
    }

    /**
     * Tests the {@link Call#deflect} API.  Verifies that if a call is outgoing,
     * and deflect API is called, then request is not made to the connection service.
     * Ideally, deflect option should be displayed only if call is incoming/waiting.
     *
     * @throws Exception
     */
    @LargeTest
    @Test
    public void testDeflectCallWhenOutgoing() throws Exception {
        Uri deflectAddress = Uri.parse("tel:650-555-1214");
        IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
                mConnectionServiceFixtureA, Process.myUserHandle());
        // Attempt to deflect the call and verify the API call does not make it through
        mInCallServiceFixtureX.mInCallAdapter.deflectCall(ids.mCallId, deflectAddress);
        verify(mConnectionServiceFixtureA.getTestDouble(), never())
                .deflect(eq(ids.mConnectionId), eq(deflectAddress), any());
        mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId);
    }

    /**
     * Test to make sure to unmute automatically when making an emergency call and keep unmute
     * during the emergency call.
     * @throws Exception
     */
    @LargeTest
    @Test
    @FlakyTest
    public void testUnmuteDuringEmergencyCall() throws Exception {
        // Make an outgoing call and turn ON mute.
        IdPair outgoingCall = startAndMakeActiveOutgoingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(outgoingCall.mCallId)
                .getState());
        mInCallServiceFixtureX.mInCallAdapter.mute(true);
        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
        assertTrue(mTelecomSystem.getCallsManager().getAudioState().isMuted());

        // Make an emergency call.
        IdPair emergencyCall = startAndMakeDialingEmergencyCall("650-555-1213",
                mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(emergencyCall.mCallId)
                .getState());
        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
        // Should be unmute automatically.
        assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted());

        // Toggle mute during an emergency call.
        mTelecomSystem.getCallsManager().getCallAudioManager().toggleMute();
        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
        // Should keep unmute.
        assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted());

        ArgumentCaptor<Boolean> muteValueCaptor = ArgumentCaptor.forClass(Boolean.class);
        verify(mAudioService, times(2)).setMicrophoneMute(muteValueCaptor.capture(),
                any(String.class), any(Integer.class));
        List<Boolean> muteValues = muteValueCaptor.getAllValues();
        // Check mute status was changed twice with true and false.
        assertTrue(muteValues.get(0));
        assertFalse(muteValues.get(1));
    }
}
