/*
 * 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 android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.telecom.Connection;
import android.telecom.GatewayInfo;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.server.telecom.BluetoothAdapterProxy;
import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.TelecomSystem;

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.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.LinkedList;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyChar;
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.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;

@RunWith(JUnit4.class)
public class BluetoothPhoneServiceTest extends TelecomTestCase {

    private static final int TEST_DTMF_TONE = 0;
    private static final String TEST_ACCOUNT_ADDRESS = "//foo.com/";
    private static final int TEST_ACCOUNT_INDEX = 0;

    // match up with BluetoothPhoneServiceImpl
    private static final int CALL_STATE_ACTIVE = 0;
    private static final int CALL_STATE_HELD = 1;
    private static final int CALL_STATE_DIALING = 2;
    private static final int CALL_STATE_ALERTING = 3;
    private static final int CALL_STATE_INCOMING = 4;
    private static final int CALL_STATE_WAITING = 5;
    private static final int CALL_STATE_IDLE = 6;
    private static final int CALL_STATE_DISCONNECTED = 7;
    // Terminate all held or set UDUB("busy") to a waiting call
    private static final int CHLD_TYPE_RELEASEHELD = 0;
    // Terminate all active calls and accepts a waiting/held call
    private static final int CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD = 1;
    // Hold all active calls and accepts a waiting/held call
    private static final int CHLD_TYPE_HOLDACTIVE_ACCEPTHELD = 2;
    // Add all held calls to a conference
    private static final int CHLD_TYPE_ADDHELDTOCONF = 3;

    private BluetoothPhoneServiceImpl mBluetoothPhoneService;
    private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {
    };

    @Mock CallsManager mMockCallsManager;
    @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
    @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);
        mContext = mComponentContextFixture.getTestDouble().getApplicationContext();

        // Ensure initialization does not actually try to access any of the CallsManager fields.
        // This also works to return null if it is not overwritten later in the test.
        doNothing().when(mMockCallsManager).addListener(any(
                CallsManager.CallsManagerListener.class));
        doReturn(null).when(mMockCallsManager).getActiveCall();
        doReturn(null).when(mMockCallsManager).getRingingCall();
        doReturn(null).when(mMockCallsManager).getHeldCall();
        doReturn(null).when(mMockCallsManager).getOutgoingCall();
        doReturn(0).when(mMockCallsManager).getNumHeldCalls();
        doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
        mBluetoothPhoneService = new BluetoothPhoneServiceImpl(mContext, mLock, mMockCallsManager,
                mock(BluetoothAdapterProxy.class), mMockPhoneAccountRegistrar);

        // Bring in test Bluetooth Headset
        mBluetoothPhoneService.setBluetoothHeadset(mMockBluetoothHeadset);
    }

    @Override
    @After
    public void tearDown() throws Exception {

        mBluetoothPhoneService = null;
        super.tearDown();
    }

    @SmallTest
    @Test
    public void testHeadsetAnswerCall() throws Exception {
        Call mockCall = createRingingCall();

        boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall();

        verify(mMockCallsManager).answerCall(eq(mockCall), any(int.class));
        assertEquals(callAnswered, true);
    }

    @SmallTest
    @Test
    public void testHeadsetAnswerCallNull() throws Exception {
        when(mMockCallsManager.getRingingCall()).thenReturn(null);

        boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall();

        verify(mMockCallsManager,never()).answerCall(any(Call.class), any(int.class));
        assertEquals(callAnswered, false);
    }

    @SmallTest
    @Test
    public void testHeadsetHangupCall() throws Exception {
        Call mockCall = createForegroundCall();

        boolean callHungup = mBluetoothPhoneService.mBinder.hangupCall();

        verify(mMockCallsManager).disconnectCall(eq(mockCall));
        assertEquals(callHungup, true);
    }

    @SmallTest
    @Test
    public void testHeadsetHangupCallNull() throws Exception {
        when(mMockCallsManager.getForegroundCall()).thenReturn(null);

        boolean callHungup = mBluetoothPhoneService.mBinder.hangupCall();

        verify(mMockCallsManager,never()).disconnectCall(any(Call.class));
        assertEquals(callHungup, false);
    }

    @SmallTest
    @Test
    public void testHeadsetSendDTMF() throws Exception {
        Call mockCall = createForegroundCall();

        boolean sentDtmf = mBluetoothPhoneService.mBinder.sendDtmf(TEST_DTMF_TONE);

        verify(mMockCallsManager).playDtmfTone(eq(mockCall), eq((char) TEST_DTMF_TONE));
        verify(mMockCallsManager).stopDtmfTone(eq(mockCall));
        assertEquals(sentDtmf, true);
    }

    @SmallTest
    @Test
    public void testHeadsetSendDTMFNull() throws Exception {
        when(mMockCallsManager.getForegroundCall()).thenReturn(null);

        boolean sentDtmf = mBluetoothPhoneService.mBinder.sendDtmf(TEST_DTMF_TONE);

        verify(mMockCallsManager,never()).playDtmfTone(any(Call.class), anyChar());
        verify(mMockCallsManager,never()).stopDtmfTone(any(Call.class));
        assertEquals(sentDtmf, false);
    }

    @SmallTest
    @Test
    public void testGetNetworkOperator() throws Exception {
        Call mockCall = createForegroundCall();
        PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX);
        when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
                nullable(PhoneAccountHandle.class))).thenReturn(fakePhoneAccount);

        String networkOperator = mBluetoothPhoneService.mBinder.getNetworkOperator();

        assertEquals(networkOperator, "label0");
    }

    @SmallTest
    @Test
    public void testGetNetworkOperatorNoPhoneAccount() throws Exception {
        when(mMockCallsManager.getForegroundCall()).thenReturn(null);

        String networkOperator = mBluetoothPhoneService.mBinder.getNetworkOperator();

        assertEquals(networkOperator, "label1");
    }

    @SmallTest
    @Test
    public void testGetSubscriberNumber() throws Exception {
        Call mockCall = createForegroundCall();
        PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX);
        when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
                nullable(PhoneAccountHandle.class))).thenReturn(fakePhoneAccount);

        String subscriberNumber = mBluetoothPhoneService.mBinder.getSubscriberNumber();

        assertEquals(subscriberNumber, TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX);
    }

    @SmallTest
    @Test
    public void testGetSubscriberNumberFallbackToTelephony() throws Exception {
        Call mockCall = createForegroundCall();
        String fakeNumber = "8675309";
        when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser(
                nullable(PhoneAccountHandle.class))).thenReturn(null);
        when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked(
                nullable(PhoneAccountHandle.class))).thenReturn(null);
        when(TelephonyManager.from(mContext).getLine1Number()).thenReturn(fakeNumber);

        String subscriberNumber = mBluetoothPhoneService.mBinder.getSubscriberNumber();

        assertEquals(subscriberNumber, fakeNumber);
    }

    @MediumTest
    @Test
    public void testListCurrentCallsOneCall() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        Call activeCall = createActiveCall();
        when(activeCall.getState()).thenReturn(CallState.ACTIVE);
        calls.add(activeCall);
        when(activeCall.isConference()).thenReturn(false);
        when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
        when(mMockCallsManager.getCalls()).thenReturn(calls);

        mBluetoothPhoneService.mBinder.listCurrentCalls();

        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(0), eq(0), eq(false),
                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown));
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
    }

    @MediumTest
    @Test
    public void testConferenceInProgressCDMA() throws Exception {
        // If two calls are being conferenced and updateHeadsetWithCallState runs while this is
        // still occuring, it will look like there is an active and held call still while we are
        // transitioning into a conference.
        // Call has been put into a CDMA "conference" with one call on hold.
        ArrayList<Call> calls = new ArrayList<>();
        Call parentCall = createActiveCall();
        final Call confCall1 = mock(Call.class);
        final Call confCall2 = createHeldCall();
        calls.add(parentCall);
        calls.add(confCall1);
        calls.add(confCall2);
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        when(confCall1.getState()).thenReturn(CallState.ACTIVE);
        when(confCall2.getState()).thenReturn(CallState.ACTIVE);
        when(confCall1.isIncoming()).thenReturn(false);
        when(confCall2.isIncoming()).thenReturn(true);
        when(confCall1.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));
        when(confCall2.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0001")));
        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1);
        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
            add(confCall1);
            add(confCall2);
        }});
        //Add links from child calls to parent
        when(confCall1.getParentCall()).thenReturn(parentCall);
        when(confCall2.getParentCall()).thenReturn(parentCall);

        mBluetoothPhoneService.mBinder.queryPhoneState();
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true);
        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
        when(mMockCallsManager.getHeldCall()).thenReturn(null);
        // Spurious call to onIsConferencedChanged.
        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
        // Make sure the call has only occurred collectively 2 times (not on the third)
        verify(mMockBluetoothHeadset, times(2)).phoneStateChanged(any(int.class),
                any(int.class), any(int.class), nullable(String.class), any(int.class));
    }

    @MediumTest
    @Test
    public void testListCurrentCallsCdmaHold() throws Exception {
        // Call has been put into a CDMA "conference" with one call on hold.
        ArrayList<Call> calls = new ArrayList<>();
        Call parentCall = createActiveCall();
        final Call foregroundCall = mock(Call.class);
        final Call heldCall = createHeldCall();
        calls.add(parentCall);
        calls.add(foregroundCall);
        calls.add(heldCall);
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        when(foregroundCall.getState()).thenReturn(CallState.ACTIVE);
        when(heldCall.getState()).thenReturn(CallState.ACTIVE);
        when(foregroundCall.isIncoming()).thenReturn(false);
        when(heldCall.isIncoming()).thenReturn(true);
        when(foregroundCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));
        when(heldCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0001")));
        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentCall.getConferenceLevelActiveCall()).thenReturn(foregroundCall);
        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
            add(foregroundCall);
            add(heldCall);
        }});
        //Add links from child calls to parent
        when(foregroundCall.getParentCall()).thenReturn(parentCall);
        when(heldCall.getParentCall()).thenReturn(parentCall);

        mBluetoothPhoneService.mBinder.listCurrentCalls();

        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0),
                eq(false), eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
        verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_HELD), eq(0),
                eq(false), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown));
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
    }

    @MediumTest
    @Test
    public void testListCurrentCallsCdmaConference() throws Exception {
        // Call is in a true CDMA conference
        ArrayList<Call> calls = new ArrayList<>();
        Call parentCall = createActiveCall();
        final Call confCall1 = mock(Call.class);
        final Call confCall2 = createHeldCall();
        calls.add(parentCall);
        calls.add(confCall1);
        calls.add(confCall2);
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        when(confCall1.getState()).thenReturn(CallState.ACTIVE);
        when(confCall2.getState()).thenReturn(CallState.ACTIVE);
        when(confCall1.isIncoming()).thenReturn(false);
        when(confCall2.isIncoming()).thenReturn(true);
        when(confCall1.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));
        when(confCall2.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0001")));
        removeCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true);
        when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1);
        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
            add(confCall1);
            add(confCall2);
        }});
        //Add links from child calls to parent
        when(confCall1.getParentCall()).thenReturn(parentCall);
        when(confCall2.getParentCall()).thenReturn(parentCall);

        mBluetoothPhoneService.mBinder.listCurrentCalls();

        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0),
                eq(true), eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
        verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_ACTIVE), eq(0),
                eq(true), eq("5550001"), eq(PhoneNumberUtils.TOA_Unknown));
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
    }

    @MediumTest
    @Test
    public void testWaitingCallClccResponse() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        // This test does not define a value for getForegroundCall(), so this ringing call will
        // be treated as if it is a waiting call when listCurrentCalls() is invoked.
        Call waitingCall = createRingingCall();
        calls.add(waitingCall);
        when(waitingCall.isIncoming()).thenReturn(true);
        when(waitingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));
        when(waitingCall.getState()).thenReturn(CallState.RINGING);
        when(waitingCall.isConference()).thenReturn(false);

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_WAITING, 0, false,
                "5550000", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
        verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(),
                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
    }

    @MediumTest
    @Test
    public void testNewCallClccResponse() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        Call newCall = createForegroundCall();
        calls.add(newCall);
        when(newCall.getState()).thenReturn(CallState.NEW);
        when(newCall.isConference()).thenReturn(false);

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
        verify(mMockBluetoothHeadset, times(1)).clccResponse(anyInt(),
                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
    }

    @MediumTest
    @Test
    public void testRingingCallClccResponse() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        Call ringingCall = createForegroundCall();
        calls.add(ringingCall);
        when(ringingCall.getState()).thenReturn(CallState.RINGING);
        when(ringingCall.isIncoming()).thenReturn(true);
        when(ringingCall.isConference()).thenReturn(false);
        when(ringingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false,
                "5550000", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
        verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(),
                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
    }

    @MediumTest
    @Test
    public void testCallClccCache() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        Call ringingCall = createForegroundCall();
        calls.add(ringingCall);
        when(ringingCall.getState()).thenReturn(CallState.RINGING);
        when(ringingCall.isIncoming()).thenReturn(true);
        when(ringingCall.isConference()).thenReturn(false);
        when(ringingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:5550000")));

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false,
                "5550000", PhoneNumberUtils.TOA_Unknown);

        // Test Caching of old call indicies in clcc
        when(ringingCall.getState()).thenReturn(CallState.ACTIVE);
        Call newHoldingCall = createHeldCall();
        calls.add(0, newHoldingCall);
        when(newHoldingCall.getState()).thenReturn(CallState.ON_HOLD);
        when(newHoldingCall.isIncoming()).thenReturn(true);
        when(newHoldingCall.isConference()).thenReturn(false);
        when(newHoldingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0001")));

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_ACTIVE, 0, false,
                "5550000", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false,
                "5550001", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset, times(2)).clccResponse(0, 0, 0, 0, false, null, 0);
    }

    @MediumTest
    @Test
    public void testAlertingCallClccResponse() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        Call dialingCall = createForegroundCall();
        calls.add(dialingCall);
        when(dialingCall.getState()).thenReturn(CallState.DIALING);
        when(dialingCall.isIncoming()).thenReturn(false);
        when(dialingCall.isConference()).thenReturn(false);
        when(dialingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false,
                "5550000", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
        verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(),
                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
    }

    @MediumTest
    @Test
    public void testHoldingCallClccResponse() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        when(mMockCallsManager.getCalls()).thenReturn(calls);
        Call dialingCall = createForegroundCall();
        calls.add(dialingCall);
        when(dialingCall.getState()).thenReturn(CallState.DIALING);
        when(dialingCall.isIncoming()).thenReturn(false);
        when(dialingCall.isConference()).thenReturn(false);
        when(dialingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0000")));
        Call holdingCall = createHeldCall();
        calls.add(holdingCall);
        when(holdingCall.getState()).thenReturn(CallState.ON_HOLD);
        when(holdingCall.isIncoming()).thenReturn(true);
        when(holdingCall.isConference()).thenReturn(false);
        when(holdingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null,
                Uri.parse("tel:555-0001")));

        mBluetoothPhoneService.mBinder.listCurrentCalls();
        verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false,
                "5550000", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false,
                "5550001", PhoneNumberUtils.TOA_Unknown);
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
        verify(mMockBluetoothHeadset, times(3)).clccResponse(anyInt(),
                anyInt(), anyInt(), anyInt(), anyBoolean(), nullable(String.class), anyInt());
    }

    @MediumTest
    @Test
    public void testListCurrentCallsImsConference() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        Call parentCall = createActiveCall();
        calls.add(parentCall);
        addCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.getState()).thenReturn(CallState.ACTIVE);
        when(parentCall.isIncoming()).thenReturn(true);
        when(mMockCallsManager.getCalls()).thenReturn(calls);

        mBluetoothPhoneService.mBinder.listCurrentCalls();

        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(1), eq(CALL_STATE_ACTIVE), eq(0),
                eq(true), (String) isNull(), eq(-1));
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
    }

    @MediumTest
    @Test
    public void testListCurrentCallsHeldImsCepConference() throws Exception {
        ArrayList<Call> calls = new ArrayList<>();
        Call parentCall = createHeldCall();
        Call childCall1 = createActiveCall();
        Call childCall2 = createActiveCall();
        calls.add(parentCall);
        calls.add(childCall1);
        calls.add(childCall2);
        addCallCapability(parentCall, Connection.CAPABILITY_MANAGE_CONFERENCE);
        when(childCall1.getParentCall()).thenReturn(parentCall);
        when(childCall2.getParentCall()).thenReturn(parentCall);

        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.getState()).thenReturn(CallState.ON_HOLD);
        when(childCall1.getState()).thenReturn(CallState.ACTIVE);
        when(childCall2.getState()).thenReturn(CallState.ACTIVE);

        when(parentCall.isIncoming()).thenReturn(true);
        when(mMockCallsManager.getCalls()).thenReturn(calls);

        mBluetoothPhoneService.mBinder.listCurrentCalls();

        verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_HELD), eq(0),
                eq(true), (String) isNull(), eq(-1));
        verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(0), eq(CALL_STATE_HELD), eq(0),
                eq(true), (String) isNull(), eq(-1));
        verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0);
    }

    @MediumTest
    @Test
    public void testQueryPhoneState() throws Exception {
        Call ringingCall = createRingingCall();
        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000"));

        mBluetoothPhoneService.mBinder.queryPhoneState();

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
    }

    @MediumTest
    @Test
    public void testCDMAConferenceQueryState() throws Exception {
        Call parentConfCall = createActiveCall();
        final Call confCall1 = mock(Call.class);
        final Call confCall2 = mock(Call.class);
        when(parentConfCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
        addCallCapability(parentConfCall, Connection.CAPABILITY_SWAP_CONFERENCE);
        removeCallCapability(parentConfCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentConfCall.wasConferencePreviouslyMerged()).thenReturn(true);
        when(parentConfCall.isConference()).thenReturn(true);
        when(parentConfCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
            add(confCall1);
            add(confCall2);
        }});

        mBluetoothPhoneService.mBinder.queryPhoneState();
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
    }

    @MediumTest
    @Test
    public void testProcessChldTypeReleaseHeldRinging() throws Exception {
        Call ringingCall = createRingingCall();

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_RELEASEHELD);

        verify(mMockCallsManager).rejectCall(eq(ringingCall), eq(false), nullable(String.class));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldTypeReleaseHeldHold() throws Exception {
        Call onHoldCall = createHeldCall();

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_RELEASEHELD);

        verify(mMockCallsManager).disconnectCall(eq(onHoldCall));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldReleaseActiveRinging() throws Exception {
        Call activeCall = createActiveCall();
        Call ringingCall = createRingingCall();

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
                CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);

        verify(mMockCallsManager).disconnectCall(eq(activeCall));
        verify(mMockCallsManager).answerCall(eq(ringingCall), any(int.class));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldReleaseActiveHold() throws Exception {
        Call activeCall = createActiveCall();
        Call heldCall = createHeldCall();

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
                CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD);

        verify(mMockCallsManager).disconnectCall(eq(activeCall));
        verify(mMockCallsManager).unholdCall(eq(heldCall));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldHoldActiveRinging() throws Exception {
        Call ringingCall = createRingingCall();

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);

        verify(mMockCallsManager).answerCall(eq(ringingCall), any(int.class));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldHoldActiveUnhold() throws Exception {
        Call heldCall = createHeldCall();

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);

        verify(mMockCallsManager).unholdCall(eq(heldCall));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldHoldActiveHold() throws Exception {
        Call activeCall = createActiveCall();
        addCallCapability(activeCall, Connection.CAPABILITY_HOLD);

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);

        verify(mMockCallsManager).holdCall(eq(activeCall));
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldAddHeldToConfHolding() throws Exception {
        Call activeCall = createActiveCall();
        addCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_ADDHELDTOCONF);

        verify(activeCall).mergeConference();
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldAddHeldToConf() throws Exception {
        Call activeCall = createActiveCall();
        removeCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE);
        Call conferenceableCall = mock(Call.class);
        ArrayList<Call> conferenceableCalls = new ArrayList<>();
        conferenceableCalls.add(conferenceableCall);
        when(activeCall.getConferenceableCalls()).thenReturn(conferenceableCalls);

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_ADDHELDTOCONF);

        verify(mMockCallsManager).conference(activeCall, conferenceableCall);
        assertEquals(didProcess, true);
    }

    @MediumTest
    @Test
    public void testProcessChldHoldActiveSwapConference() throws Exception {
        // Create an active CDMA Call with a call on hold and simulate a swapConference().
        Call parentCall = createActiveCall();
        final Call foregroundCall = mock(Call.class);
        final Call heldCall = createHeldCall();
        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false);
        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
            add(foregroundCall);
            add(heldCall);
        }});

        boolean didProcess = mBluetoothPhoneService.mBinder.processChld(
                CHLD_TYPE_HOLDACTIVE_ACCEPTHELD);

        verify(parentCall).swapConference();
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), eq(""),
                eq(128));
        assertEquals(didProcess, true);
    }

    // Testing the CallsManager Listener Functionality on Bluetooth
    @MediumTest
    @Test
    public void testOnCallAddedRinging() throws Exception {
        Call ringingCall = createRingingCall();
        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));

        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown));

    }

    @MediumTest
    @Test
    public void testOnCallAddedCdmaActiveHold() throws Exception {
        // Call has been put into a CDMA "conference" with one call on hold.
        Call parentCall = createActiveCall();
        final Call foregroundCall = mock(Call.class);
        final Call heldCall = createHeldCall();
        addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE);
        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        when(parentCall.isConference()).thenReturn(true);
        when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{
            add(foregroundCall);
            add(heldCall);
        }});

        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(parentCall);

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
                eq(""), eq(128));

    }

    @MediumTest
    @Test
    public void testOnCallRemoved() throws Exception {
        Call activeCall = createActiveCall();
        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(activeCall);
        doReturn(null).when(mMockCallsManager).getActiveCall();
        mBluetoothPhoneService.mCallsManagerListener.onCallRemoved(activeCall);

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
    }

    @MediumTest
    @Test
    public void testOnCallStateChangedConnectingCall() throws Exception {
        Call activeCall = mock(Call.class);
        Call connectingCall = mock(Call.class);
        when(connectingCall.getState()).thenReturn(CallState.CONNECTING);
        ArrayList<Call> calls = new ArrayList<>();
        calls.add(connectingCall);
        calls.add(activeCall);
        when(mMockCallsManager.getCalls()).thenReturn(calls);

        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
                CallState.ACTIVE, CallState.ON_HOLD);

        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
                anyString(), anyInt());
    }

    @MediumTest
    @Test
    public void testOnCallStateChangedDialing() throws Exception {
        Call activeCall = createActiveCall();

        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
                CallState.CONNECTING, CallState.DIALING);

        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
                anyString(), anyInt());
    }

    @MediumTest
    @Test
    public void testOnCallStateChangedAlerting() throws Exception {
        Call outgoingCall = createOutgoingCall();

        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(outgoingCall,
                CallState.NEW, CallState.DIALING);

        verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_DIALING, "", 128);
        verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_ALERTING, "", 128);
    }

    @MediumTest
    @Test
    public void testOnCallStateChangedDisconnected() throws Exception {
        Call disconnectedCall = createDisconnectedCall();
        doReturn(true).when(mMockCallsManager).hasOnlyDisconnectedCalls();
        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(disconnectedCall,
                CallState.DISCONNECTING, CallState.DISCONNECTED);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
                eq(""), eq(128));

        doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
        mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(true);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
                eq(""), eq(128));

        mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(false);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
    }

    @MediumTest
    @Test
    public void testOnCallStateChanged() throws Exception {
        Call ringingCall = createRingingCall();
        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown));

        //Switch to active
        doReturn(null).when(mMockCallsManager).getRingingCall();
        when(mMockCallsManager.getActiveCall()).thenReturn(ringingCall);

        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
                CallState.RINGING, CallState.ACTIVE);

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
    }

    @MediumTest
    @Test
    public void testOnCallStateChangedGSMSwap() throws Exception {
        Call heldCall = createHeldCall();
        when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
        doReturn(2).when(mMockCallsManager).getNumHeldCalls();
        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(heldCall,
                CallState.ACTIVE, CallState.ON_HOLD);

        verify(mMockBluetoothHeadset, never()).phoneStateChanged(eq(0), eq(2), eq(CALL_STATE_HELD),
                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
    }

    @MediumTest
    @Test
    public void testOnIsConferencedChanged() throws Exception {
        // Start with two calls that are being merged into a CDMA conference call. The
        // onIsConferencedChanged method will be called multiple times during the call. Make sure
        // that the bluetooth phone state is updated properly.
        Call parentCall = createActiveCall();
        Call activeCall = mock(Call.class);
        Call heldCall = createHeldCall();
        when(activeCall.getParentCall()).thenReturn(parentCall);
        when(heldCall.getParentCall()).thenReturn(parentCall);
        ArrayList<Call> calls = new ArrayList<>();
        calls.add(activeCall);
        when(parentCall.getChildCalls()).thenReturn(calls);
        when(parentCall.isConference()).thenReturn(true);
        removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
        addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE);
        when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false);

        // Be sure that onIsConferencedChanged rejects spurious changes during set up of
        // CDMA "conference"
        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(activeCall);
        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
                anyString(), anyInt());
        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(heldCall);
        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
                anyString(), anyInt());
        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
                anyString(), anyInt());

        calls.add(heldCall);
        mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
    }

    @MediumTest
    @Test
    public void testBluetoothAdapterReceiver() throws Exception {
        Call ringingCall = createRingingCall();
        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:5550000"));

        Intent intent = new Intent();
        intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON);
        mBluetoothPhoneService.mBluetoothAdapterReceiver.onReceive(mContext, intent);

        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
                eq("5550000"), eq(PhoneNumberUtils.TOA_Unknown));
    }

    private void addCallCapability(Call call, int capability) {
        when(call.can(capability)).thenReturn(true);
    }

    private void removeCallCapability(Call call, int capability) {
        when(call.can(capability)).thenReturn(false);
    }

    private Call createActiveCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getActiveCall()).thenReturn(call);
        return call;
    }

    private Call createRingingCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getRingingCall()).thenReturn(call);
        return call;
    }

    private Call createHeldCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getHeldCall()).thenReturn(call);
        return call;
    }

    private Call createOutgoingCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getOutgoingCall()).thenReturn(call);
        return call;
    }

    private Call createDisconnectedCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getFirstCallWithState(CallState.DISCONNECTED)).thenReturn(call);
        return call;
    }

    private Call createForegroundCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getForegroundCall()).thenReturn(call);
        return call;
    }

    private static ComponentName makeQuickConnectionServiceComponentName() {
        return new ComponentName("com.android.server.telecom.tests",
                "com.android.server.telecom.tests.MockConnectionService");
    }

    private static PhoneAccountHandle makeQuickAccountHandle(String id) {
        return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id,
                Binder.getCallingUserHandle());
    }

    private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
        return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx);
    }

    private PhoneAccount makeQuickAccount(String id, int idx) {
        return makeQuickAccountBuilder(id, idx)
                .setAddress(Uri.parse(TEST_ACCOUNT_ADDRESS + idx))
                .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
                .setCapabilities(idx)
                .setIcon(Icon.createWithResource(
                        "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
                .setShortDescription("desc" + idx)
                .setIsEnabled(true)
                .build();
    }
}
