Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a9f04b3 authored by Tyler Gunn's avatar Tyler Gunn Committed by android-build-merger
Browse files

Merge "Enhancements to conference for non-conference host scenarios." into qt-dev

am: 2d82b3e4

Change-Id: I45535471004baf0a6e329c4f3f44374e048a6e3e
parents cdea6e51 2d82b3e4
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -399,6 +399,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,


    private boolean mIsConference = false;
    private boolean mIsConference = false;


    private boolean mHadChildren = false;

    private final boolean mShouldAttachToExistingConnection;
    private final boolean mShouldAttachToExistingConnection;


    private Call mParentCall = null;
    private Call mParentCall = null;
@@ -1011,6 +1013,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        return mIsConference;
        return mIsConference;
    }
    }


    /**
     * @return {@code true} if this call had children at some point, {@code false} otherwise.
     */
    public boolean hadChildren() {
        return mHadChildren;
    }

    public Uri getHandle() {
    public Uri getHandle() {
        return mHandle;
        return mHandle;
    }
    }
@@ -2476,6 +2485,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,


    private void addChildCall(Call call) {
    private void addChildCall(Call call) {
        if (!mChildCalls.contains(call)) {
        if (!mChildCalls.contains(call)) {
            mHadChildren = true;
            // Set the pseudo-active call to the latest child added to the conference.
            // Set the pseudo-active call to the latest child added to the conference.
            // See definition of mConferenceLevelActiveCall for more detail.
            // See definition of mConferenceLevelActiveCall for more detail.
            mConferenceLevelActiveCall = call;
            mConferenceLevelActiveCall = call;
+27 −18
Original line number Original line Diff line number Diff line
@@ -182,33 +182,42 @@ public final class CallLogManager extends CallsManagerListenerBase {


    /**
    /**
     * Log newly disconnected calls only if all of below conditions are met:
     * Log newly disconnected calls only if all of below conditions are met:
     * 1) Call was NOT in the "choose account" phase when disconnected
     * Call was NOT in the "choose account" phase when disconnected
     * 2) Call is NOT a conference call
     * Call is NOT a conference call which had children (unless it was remotely hosted).
     * 3) Call is NOT simulating a single party conference.
     * Call is NOT a child call from a conference which was remotely hosted.
     * 4) Call was NOT explicitly canceled, except for disconnecting from a conference.
     * Call is NOT simulating a single party conference.
     * 5) Call is NOT an external call
     * Call was NOT explicitly canceled, except for disconnecting from a conference.
     * 6) Call is NOT disconnected because of merging into a conference.
     * Call is NOT an external call
     * 7) Call is NOT a self-managed call OR call is a self-managed call which has indicated it
     * Call is NOT disconnected because of merging into a conference.
     * Call is NOT a self-managed call OR call is a self-managed call which has indicated it
     * should be logged in its PhoneAccount
     * should be logged in its PhoneAccount
     */
     */
    private boolean shouldLogDisconnectedCall(Call call, int oldState, boolean isCallCanceled) {
    @VisibleForTesting
        // 1) "Choose account" phase when disconnected
    public boolean shouldLogDisconnectedCall(Call call, int oldState, boolean isCallCanceled) {
        // "Choose account" phase when disconnected
        if (oldState == CallState.SELECT_PHONE_ACCOUNT) {
        if (oldState == CallState.SELECT_PHONE_ACCOUNT) {
            return false;
            return false;
        }
        }
        // 2) A conference call
        // A conference call which had children should not be logged, unless it was remotely hosted.
        if (call.isConference()) {
        if (call.isConference() && call.hadChildren() &&
                !call.hasProperty(Connection.PROPERTY_REMOTELY_HOSTED)) {
            return false;
        }

        // A child call of a conference which was remotely hosted; these didn't originate on this
        // device and should not be logged.
        if (call.getParentCall() != null && call.hasProperty(Connection.PROPERTY_REMOTELY_HOSTED)) {
            return false;
            return false;
        }
        }


        DisconnectCause cause = call.getDisconnectCause();
        DisconnectCause cause = call.getDisconnectCause();
        if (isCallCanceled) {
        if (isCallCanceled) {
            // 3) No log when disconnecting to simulate a single party conference.
            // No log when disconnecting to simulate a single party conference.
            if (cause != null
            if (cause != null
                    && DisconnectCause.REASON_EMULATING_SINGLE_CALL.equals(cause.getReason())) {
                    && DisconnectCause.REASON_EMULATING_SINGLE_CALL.equals(cause.getReason())) {
                return false;
                return false;
            }
            }
            // 4) Explicitly canceled
            // Explicitly canceled
            // Conference children connections only have CAPABILITY_DISCONNECT_FROM_CONFERENCE.
            // Conference children connections only have CAPABILITY_DISCONNECT_FROM_CONFERENCE.
            // Log them when they are disconnected from conference.
            // Log them when they are disconnected from conference.
            return Connection.can(call.getConnectionCapabilities(),
            return Connection.can(call.getConnectionCapabilities(),
@@ -217,12 +226,12 @@ public final class CallLogManager extends CallsManagerListenerBase {
                    // carrier requirements, e.g. could be one active and the other on hold.
                    // carrier requirements, e.g. could be one active and the other on hold.
                    || oldState == CallState.ACTIVE || oldState == CallState.ON_HOLD;
                    || oldState == CallState.ACTIVE || oldState == CallState.ON_HOLD;
        }
        }
        // 5) An external call
        // An external call
        if (call.isExternalCall()) {
        if (call.isExternalCall()) {
            return false;
            return false;
        }
        }


        // 6) Call merged into conferences.
        // Call merged into conferences.
        if (cause != null && android.telephony.DisconnectCause.toString(
        if (cause != null && android.telephony.DisconnectCause.toString(
                android.telephony.DisconnectCause.IMS_MERGED_SUCCESSFULLY)
                android.telephony.DisconnectCause.IMS_MERGED_SUCCESSFULLY)
                .equals(cause.getReason())) {
                .equals(cause.getReason())) {
@@ -232,7 +241,7 @@ public final class CallLogManager extends CallsManagerListenerBase {
        boolean shouldCallSelfManagedLogged = call.isLoggedSelfManaged()
        boolean shouldCallSelfManagedLogged = call.isLoggedSelfManaged()
                && (call.getHandoverState() == HandoverState.HANDOVER_NONE
                && (call.getHandoverState() == HandoverState.HANDOVER_NONE
                || call.getHandoverState() == HandoverState.HANDOVER_COMPLETE);
                || call.getHandoverState() == HandoverState.HANDOVER_COMPLETE);
        // 7) Call is NOT a self-managed call OR call is a self-managed call which has indicated it
        // Call is NOT a self-managed call OR call is a self-managed call which has indicated it
        // should be logged in its PhoneAccount
        // should be logged in its PhoneAccount
        return !call.isSelfManaged() || shouldCallSelfManagedLogged;
        return !call.isSelfManaged() || shouldCallSelfManagedLogged;
    }
    }
+2 −0
Original line number Original line Diff line number Diff line
@@ -2814,6 +2814,8 @@ public class CallsManager extends Call.ListenerBase


        setCallState(call, Call.getStateFromConnectionState(parcelableConference.getState()),
        setCallState(call, Call.getStateFromConnectionState(parcelableConference.getState()),
                "new conference call");
                "new conference call");
        call.setHandle(parcelableConference.getHandle(),
                parcelableConference.getHandlePresentation());
        call.setConnectionCapabilities(parcelableConference.getConnectionCapabilities());
        call.setConnectionCapabilities(parcelableConference.getConnectionCapabilities());
        call.setConnectionProperties(parcelableConference.getConnectionProperties());
        call.setConnectionProperties(parcelableConference.getConnectionProperties());
        call.setVideoState(parcelableConference.getVideoState());
        call.setVideoState(parcelableConference.getVideoState());
+135 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.telecom.tests;




import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.fail;
@@ -48,6 +49,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.provider.CallLog;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.CallLog.Calls;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.PhoneAccountHandle;
@@ -781,6 +783,136 @@ public class CallLogManagerTest extends TelecomTestCase {
        assertEquals(TEST_ISO_2, resultIso2);
        assertEquals(TEST_ISO_2, resultIso2);
    }
    }


    @SmallTest
    @Test
    public void testLogConferenceWithNoChildren() {
        Call fakeCall = makeFakeCall(
                DisconnectCause.LOCAL, // disconnectCauseCode
                true, // isConference
                true, // isIncoming
                1L, // creationTimeMillis
                1000L, // ageMillis
                TEL_PHONEHANDLE, // callHandle
                mDefaultAccountHandle, // phoneAccountHandle
                NO_VIDEO_STATE, // callVideoState
                POST_DIAL_STRING, // postDialDigits
                VIA_NUMBER_STRING, // viaNumber
                UserHandle.of(CURRENT_USER_ID)
        );
        when(fakeCall.hadChildren()).thenReturn(false);

        assertTrue(mCallLogManager.shouldLogDisconnectedCall(fakeCall, CallState.DISCONNECTED,
                false /* isCanceled */));
    }

    @SmallTest
    @Test
    public void testDoNotLogConferenceWithChildren() {
        Call fakeCall = makeFakeCall(
                DisconnectCause.LOCAL, // disconnectCauseCode
                true, // isConference
                true, // isIncoming
                1L, // creationTimeMillis
                1000L, // ageMillis
                TEL_PHONEHANDLE, // callHandle
                mDefaultAccountHandle, // phoneAccountHandle
                NO_VIDEO_STATE, // callVideoState
                POST_DIAL_STRING, // postDialDigits
                VIA_NUMBER_STRING, // viaNumber
                UserHandle.of(CURRENT_USER_ID)
        );
        when(fakeCall.hadChildren()).thenReturn(true);

        assertFalse(mCallLogManager.shouldLogDisconnectedCall(fakeCall, CallState.DISCONNECTED,
                false /* isCanceled */));
    }

    @SmallTest
    @Test
    public void testLogRemotelyHostedConferenceWithChildren() {
        Call fakeCall = makeFakeCall(
                DisconnectCause.LOCAL, // disconnectCauseCode
                true, // isConference
                true, // isIncoming
                1L, // creationTimeMillis
                1000L, // ageMillis
                TEL_PHONEHANDLE, // callHandle
                mDefaultAccountHandle, // phoneAccountHandle
                NO_VIDEO_STATE, // callVideoState
                POST_DIAL_STRING, // postDialDigits
                VIA_NUMBER_STRING, // viaNumber
                UserHandle.of(CURRENT_USER_ID)
        );
        when(fakeCall.hadChildren()).thenReturn(true);
        when(fakeCall.hasProperty(eq(Connection.PROPERTY_REMOTELY_HOSTED))).thenReturn(true);

        assertTrue(mCallLogManager.shouldLogDisconnectedCall(fakeCall, CallState.DISCONNECTED,
                false /* isCanceled */));
    }

    @SmallTest
    @Test
    public void testLogRemotelyHostedConferenceWithNoChildren() {
        Call fakeCall = makeFakeCall(
                DisconnectCause.LOCAL, // disconnectCauseCode
                true, // isConference
                true, // isIncoming
                1L, // creationTimeMillis
                1000L, // ageMillis
                TEL_PHONEHANDLE, // callHandle
                mDefaultAccountHandle, // phoneAccountHandle
                NO_VIDEO_STATE, // callVideoState
                POST_DIAL_STRING, // postDialDigits
                VIA_NUMBER_STRING, // viaNumber
                UserHandle.of(CURRENT_USER_ID)
        );
        when(fakeCall.hadChildren()).thenReturn(false);
        when(fakeCall.hasProperty(eq(Connection.PROPERTY_REMOTELY_HOSTED))).thenReturn(true);

        assertTrue(mCallLogManager.shouldLogDisconnectedCall(fakeCall, CallState.DISCONNECTED,
                false /* isCanceled */));
    }

    @SmallTest
    @Test
    public void testDoNotLogChildOfRemotelyHostedConference() {
        Call fakeConfCall = makeFakeCall(
                DisconnectCause.LOCAL, // disconnectCauseCode
                true, // isConference
                true, // isIncoming
                1L, // creationTimeMillis
                1000L, // ageMillis
                TEL_PHONEHANDLE, // callHandle
                mDefaultAccountHandle, // phoneAccountHandle
                NO_VIDEO_STATE, // callVideoState
                POST_DIAL_STRING, // postDialDigits
                VIA_NUMBER_STRING, // viaNumber
                UserHandle.of(CURRENT_USER_ID)
        );
        when(fakeConfCall.hadChildren()).thenReturn(true);
        when(fakeConfCall.hasProperty(eq(Connection.PROPERTY_REMOTELY_HOSTED))).thenReturn(true);

        Call fakeChild = makeFakeCall(
                DisconnectCause.LOCAL, // disconnectCauseCode
                false, // isConference
                true, // isIncoming
                1L, // creationTimeMillis
                1000L, // ageMillis
                TEL_PHONEHANDLE, // callHandle
                mDefaultAccountHandle, // phoneAccountHandle
                NO_VIDEO_STATE, // callVideoState
                POST_DIAL_STRING, // postDialDigits
                VIA_NUMBER_STRING, // viaNumber
                UserHandle.of(CURRENT_USER_ID)
        );
        when(fakeChild.hadChildren()).thenReturn(false);
        when(fakeChild.getParentCall()).thenReturn(fakeConfCall);
        when(fakeChild.hasProperty(eq(Connection.PROPERTY_REMOTELY_HOSTED))).thenReturn(true);

        assertFalse(mCallLogManager.shouldLogDisconnectedCall(fakeChild, CallState.DISCONNECTED,
                false /* isCanceled */));
    }

    private ArgumentCaptor<CountryListener> verifyCountryIso(CountryDetector mockDetector,
    private ArgumentCaptor<CountryListener> verifyCountryIso(CountryDetector mockDetector,
            String resultIso) {
            String resultIso) {
        ArgumentCaptor<CountryListener> captor = ArgumentCaptor.forClass(CountryListener.class);
        ArgumentCaptor<CountryListener> captor = ArgumentCaptor.forClass(CountryListener.class);
@@ -862,6 +994,9 @@ public class CallLogManagerTest extends TelecomTestCase {
        when(fakeCall.getCallDataUsage()).thenReturn(callDataUsage);
        when(fakeCall.getCallDataUsage()).thenReturn(callDataUsage);
        when(fakeCall.isEmergencyCall()).thenReturn(
        when(fakeCall.isEmergencyCall()).thenReturn(
                phoneAccountHandle.equals(EMERGENCY_ACCT_HANDLE));
                phoneAccountHandle.equals(EMERGENCY_ACCT_HANDLE));
        when(fakeCall.getParentCall()).thenReturn(null);
        when(fakeCall.hadChildren()).thenReturn(true);
        when(fakeCall.hasProperty(eq(Connection.PROPERTY_REMOTELY_HOSTED))).thenReturn(false);
        return fakeCall;
        return fakeCall;
    }
    }


+5 −1
Original line number Original line Diff line number Diff line
@@ -670,7 +670,11 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
                c.connectTimeMillis,
                c.connectTimeMillis,
                c.connectElapsedTimeMillis,
                c.connectElapsedTimeMillis,
                c.statusHints,
                c.statusHints,
                c.extras);
                c.extras,
                null,
                0,
                null,
                0);
    }
    }


    private ParcelableConnection parcelable(ConnectionInfo c) {
    private ParcelableConnection parcelable(ConnectionInfo c) {