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

Commit 0c403a28 authored by Pengquan Meng's avatar Pengquan Meng Committed by android-build-merger
Browse files

Revert "Integrate connectionServiceFocusManager into call flow"

am: fc9c8ffc

Change-Id: I45f5faee1a3133bfd851514d94e89ee7b9851b79
parents 2e8ff200 fc9c8ffc
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -1763,8 +1763,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
    /**
     * Puts the call on hold if it is currently active.
     */
    @VisibleForTesting
    public void hold() {
    void hold() {
        if (mState == CallState.ACTIVE) {
            if (mConnectionService != null) {
                mConnectionService.hold(this);
@@ -1779,8 +1778,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
    /**
     * Releases the call from hold if it is currently active.
     */
    @VisibleForTesting
    public void unhold() {
    void unhold() {
        if (mState == CallState.ON_HOLD) {
            if (mConnectionService != null) {
                mConnectionService.unhold(this);
@@ -2802,10 +2800,6 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        return mOriginalConnectionId;
    }

    ConnectionServiceFocusManager getConnectionServiceFocusManager() {
        return mCallsManager.getConnectionServiceFocusManager();
    }

    /**
     * Determines if a {@link Call}'s capabilities bitmask indicates that video is supported either
     * remotely or locally.
+139 −228
Original line number Diff line number Diff line
@@ -122,11 +122,6 @@ public class CallsManager extends Call.ListenerBase
        void onDisconnectedTonePlaying(boolean isTonePlaying);
    }

    /** Interface used to define the action which is executed delay under some condition. */
    interface PendingAction {
        void performAction();
    }

    private static final String TAG = "CallsManager";

    /**
@@ -267,27 +262,10 @@ public class CallsManager extends Call.ListenerBase
    private final ClockProxy mClockProxy;
    private final Set<Call> mLocallyDisconnectingCalls = new HashSet<>();
    private final Set<Call> mPendingCallsToDisconnect = new HashSet<>();
    private final ConnectionServiceFocusManager mConnectionSvrFocusMgr;
    /* Handler tied to thread in which CallManager was initialized. */
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final EmergencyCallHelper mEmergencyCallHelper;

    private final ConnectionServiceFocusManager.CallsManagerRequester mRequester =
            new ConnectionServiceFocusManager.CallsManagerRequester() {
                @Override
                public void releaseConnectionService(
                        ConnectionServiceFocusManager.ConnectionServiceFocus connectionService) {
                    mCalls.stream()
                            .filter(c -> c.getConnectionServiceWrapper().equals(connectionService))
                            .forEach(c -> c.disconnect());
                }

                @Override
                public void setCallsManagerListener(CallsManagerListener listener) {
                    mListeners.add(listener);
                }
            };

    private boolean mCanAddCall = true;

    private TelephonyManager.MultiSimVariants mRadioSimVariants = null;
@@ -323,8 +301,6 @@ public class CallsManager extends Call.ListenerBase
            HeadsetMediaButtonFactory headsetMediaButtonFactory,
            ProximitySensorManagerFactory proximitySensorManagerFactory,
            InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
            ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory
                    connectionServiceFocusManagerFactory,
            CallAudioManager.AudioServiceFactory audioServiceFactory,
            BluetoothRouteManager bluetoothManager,
            WiredHeadsetManager wiredHeadsetManager,
@@ -392,9 +368,6 @@ public class CallsManager extends Call.ListenerBase
                        mContext.getSystemService(Context.AUDIO_SERVICE)),
                playerFactory, mRinger, new RingbackPlayer(playerFactory), mDtmfLocalTonePlayer);

        mConnectionSvrFocusMgr = connectionServiceFocusManagerFactory.create(
                mRequester, Looper.getMainLooper());

        mHeadsetMediaButton = headsetMediaButtonFactory.create(context, this, mLock);
        mTtyManager = new TtyManager(context, mWiredHeadsetManager);
        mProximitySensorManager = proximitySensorManagerFactory.create(context, this);
@@ -889,23 +862,24 @@ public class CallsManager extends Call.ListenerBase
            if (call.isSelfManaged()) {
                // Self managed calls will always be voip audio mode.
                call.setIsVoipAudioMode(true);
            }

            Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();

            if (activeCall != null && !canHold(activeCall)) {
            } else {
                // Incoming call is not self-managed, so we need to set extras on it to indicate
                // whether answering will cause a background self-managed call to drop.
                if (hasSelfManagedCalls()) {
                    Bundle dropCallExtras = new Bundle();
                    dropCallExtras.putBoolean(Connection.EXTRA_ANSWERING_DROPS_FG_CALL, true);

                    // Include the name of the app which will drop the call.
                if (activeCall != null) {
                    CharSequence droppedApp = activeCall.getTargetPhoneAccountLabel();
                    Call foregroundCall = getForegroundCall();
                    if (foregroundCall != null) {
                        CharSequence droppedApp = foregroundCall.getTargetPhoneAccountLabel();
                        dropCallExtras.putCharSequence(
                                Connection.EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME, droppedApp);
                        Log.i(this, "Incoming managed call will drop %s call.", droppedApp);
                    }
                    call.putExtras(Call.SOURCE_CONNECTION_SERVICE, dropCallExtras);
                }
            }

            if (extras.getBoolean(PhoneAccount.EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE)) {
                Log.d(this, "processIncomingCallIntent: defaulting to voip mode for call %s",
@@ -1064,8 +1038,7 @@ public class CallsManager extends Call.ListenerBase
     * @param initiatingUser {@link UserHandle} of user that place the outgoing call.
     * @param originalIntent
     */
    @VisibleForTesting
    public Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras,
    Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras,
            UserHandle initiatingUser, Intent originalIntent) {
        boolean isReusedCall = true;
        Call call = reuseOutgoingCall(handle);
@@ -1154,28 +1127,22 @@ public class CallsManager extends Call.ListenerBase
        // a call, or cancel this call altogether. If a call is being reused, then it has already
        // passed the makeRoomForOutgoingCall check once and will fail the second time due to the
        // call transitioning into the CONNECTING state.
        if (!isPotentialInCallMMICode && (!isReusedCall
                && !makeRoomForOutgoingCall(call, call.isEmergencyCall()))) {
            Call foregroundCall = getForegroundCall();
            Log.d(this, "No more room for outgoing call %s ", call);
            if (foregroundCall.isSelfManaged()) {
                // If the ongoing call is a self-managed call, then prompt the user to ask if they'd
                // like to disconnect their ongoing call and place the outgoing call.
                call.setOriginalCallIntent(originalIntent);
                startCallConfirmation(call);
            } else {
                // If the ongoing call is a managed call, we will prevent the outgoing call from
                // dialing.
                notifyCreateConnectionFailed(call.getTargetPhoneAccount(), call);
        if (!isSelfManaged && !isPotentialInCallMMICode && (!isReusedCall &&
                !makeRoomForOutgoingCall(call, call.isEmergencyCall()))) {
            // just cancel at this point.
            Log.i(this, "No remaining room for outgoing call: %s", call);
            if (mCalls.contains(call)) {
                // This call can already exist if it is a reused call,
                // See {@link #reuseOutgoingCall}.
                call.disconnect();
            }
            return null;
        }

        // The outgoing call can be placed, go forward.

        boolean needsAccountSelection =
                phoneAccountHandle == null && potentialPhoneAccounts.size() > 1
                        && !call.isEmergencyCall() && !isSelfManaged;

        if (needsAccountSelection) {
            // This is the state where the user is expected to select an account
            call.setState(CallState.SELECT_PHONE_ACCOUNT, "needs account selection");
@@ -1198,7 +1165,6 @@ public class CallsManager extends Call.ListenerBase
            call.setState(
                    CallState.CONNECTING,
                    phoneAccountHandle == null ? "no-handle" : phoneAccountHandle.toString());

            if (extras != null
                    && extras.getBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, false)) {
                if (accountToUse != null
@@ -1209,9 +1175,15 @@ public class CallsManager extends Call.ListenerBase
        }
        setIntentExtrasAndStartTime(call, extras);

        if ((isPotentialMMICode(handle) || isPotentialInCallMMICode) && !needsAccountSelection) {
        if ((isPotentialMMICode(handle) || isPotentialInCallMMICode)
                && !needsAccountSelection) {
            // Do not add the call if it is a potential MMI code.
            call.addListener(this);
        } else if (!isSelfManaged && hasSelfManagedCalls() && !call.isEmergencyCall()) {
            // Adding a managed call and there are ongoing self-managed call(s).
            call.setOriginalCallIntent(originalIntent);
            startCallConfirmation(call);
            return null;
        } else if (!mCalls.contains(call)) {
            // We check if mCalls already contains the call because we could potentially be reusing
            // a call which was previously added (See {@link #reuseOutgoingCall}).
@@ -1362,13 +1334,12 @@ public class CallsManager extends Call.ListenerBase
            // Otherwise the connection will be initiated when the account is set by the user.
            if (call.isSelfManaged() && !isOutgoingCallPermitted) {
                notifyCreateConnectionFailed(call.getTargetPhoneAccount(), call);
            } else if (!call.isSelfManaged() && hasSelfManagedCalls() && !call.isEmergencyCall()) {
                markCallDisconnectedDueToSelfManagedCall(call);
            } else {
                if (call.isEmergencyCall()) {
                    // Disconnect calls from other ConnectionServices other than the one the
                    // emergency call targets.
                    // Except, do not disconnect calls from the Connection Manager's
                    // ConnectionService.
                    disconnectCallsHaveDifferentConnectionService(call);
                    // Disconnect all self-managed calls to make priority for emergency call.
                    disconnectSelfManagedCalls();
                }

                call.startCreateConnection(mPhoneAccountRegistrar);
@@ -1407,22 +1378,60 @@ public class CallsManager extends Call.ListenerBase
        if (!mCalls.contains(call)) {
            Log.i(this, "Request to answer a non-existent call %s", call);
        } else {
            // Hold or disconnect the active call and request call focus for the incoming call.
            Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
            Log.d(this, "Incoming call = %s Ongoing call %s", call, activeCall);
            if (activeCall != null) {
                if (canHold(activeCall)) {
                    Log.d(this, "answerCall hold active call");
                    activeCall.hold();
            Call foregroundCall = getForegroundCall();
            // If the foreground call is not the ringing call and it is currently isActive() or
            // STATE_DIALING, put it on hold before answering the call.
            if (foregroundCall != null && foregroundCall != call &&
                    (foregroundCall.isActive() ||
                     foregroundCall.getState() == CallState.DIALING ||
                     foregroundCall.getState() == CallState.PULLING)) {
                if (!foregroundCall.getTargetPhoneAccount().equals(
                                call.getTargetPhoneAccount()) &&
                        ((call.isSelfManaged() != foregroundCall.isSelfManaged()) ||
                         call.isSelfManaged())) {
                    // The foreground call is from another connection service, and either:
                    // 1. FG call's managed state doesn't match that of the incoming call.
                    //    E.g. Incoming is self-managed and FG is managed, or incoming is managed
                    //    and foreground is self-managed.
                    // 2. The incoming call is self-managed.
                    //    E.g. The incoming call is
                    Log.i(this, "Answering call from %s CS; disconnecting calls from %s CS.",
                            foregroundCall.isSelfManaged() ? "selfMg" : "mg",
                            call.isSelfManaged() ? "selfMg" : "mg");
                    disconnectOtherCalls(call.getTargetPhoneAccount());
                } else if (0 == (foregroundCall.getConnectionCapabilities()
                        & Connection.CAPABILITY_HOLD)) {
                    // This call does not support hold.  If it is from a different connection
                    // service, then disconnect it, otherwise allow the connection service to
                    // figure out the right states.
                    if (foregroundCall.getConnectionService() != call.getConnectionService()) {
                        foregroundCall.disconnect();
                    }
                } else {
                    Log.d(this, "answerCall disconnect active call");
                    activeCall.disconnect();
                    Call heldCall = getHeldCall();
                    if (heldCall != null) {
                        Log.i(this, "Disconnecting held call %s before holding active call.",
                                heldCall);
                        heldCall.disconnect();
                    }

                    foregroundCall.hold();
                }
                // TODO: Wait until we get confirmation of the active call being
                // on-hold before answering the new call.
                // TODO: Import logic from CallManager.acceptCall()
            }

            for (CallsManagerListener listener : mListeners) {
                listener.onIncomingCallAnswered(call);
            }

            mConnectionSvrFocusMgr.requestFocus(
                    call,
                    new RequestCallback(new ActionAnswerCall(call, videoState)));
            // We do not update the UI until we get confirmation of the answer() through
            // {@link #markCallAsActive}.
            call.answer(videoState);
            if (isSpeakerphoneAutoEnabledForVideoCalls(videoState)) {
                call.setStartWithSpeakerphoneOn(true);
            }
        }
    }

@@ -1592,19 +1601,20 @@ public class CallsManager extends Call.ListenerBase
        if (!mCalls.contains(call)) {
            Log.w(this, "Unknown call (%s) asked to be removed from hold", call);
        } else {
           Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
            if (activeCall != null) {
                if (canHold(activeCall)) {
                    activeCall.hold();
                    Log.addEvent(activeCall, LogUtils.Events.SWAP);
                    Log.addEvent(call, LogUtils.Events.SWAP);
                } else {
                    activeCall.disconnect();
            boolean otherCallHeld = false;
            Log.d(this, "unholding call: (%s)", call);
            for (Call c : mCalls) {
                // Only attempt to hold parent calls and not the individual children.
                if (c != null && c.isAlive() && c != call && c.getParentCall() == null) {
                    otherCallHeld = true;
                    Log.addEvent(c, LogUtils.Events.SWAP);
                    c.hold();
                }
            }
            mConnectionSvrFocusMgr.requestFocus(
                    call,
                    new RequestCallback(new ActionUnHoldCall(call)));
            if (otherCallHeld) {
                Log.addEvent(call, LogUtils.Events.SWAP);
            }
            call.unhold();
        }
    }

@@ -1813,21 +1823,9 @@ public class CallsManager extends Call.ListenerBase
    }

    void markCallAsActive(Call call) {
        if (call.isSelfManaged()) {
            // backward compatibility, the self-managed connection service will set the call state
            // to active directly. We should request the call focus for self-managed call before
            // the state change
            mConnectionSvrFocusMgr.requestFocus(
                    call,
                    new RequestCallback(new ActionSetCallState(
                            call,
                            CallState.ACTIVE,
                            "active set explicitly for self-managed")));
        } else {
        setCallState(call, CallState.ACTIVE, "active set explicitly");
        maybeMoveToSpeakerPhone(call);
    }
    }

    @VisibleForTesting
    public void markCallAsOnHold(Call call) {
@@ -2548,11 +2546,6 @@ public class CallsManager extends Call.ListenerBase
        return (int) callsStream.count();
    }

    private boolean hasMaximumLiveCalls(Call exceptCall) {
        return MAXIMUM_LIVE_CALLS <= getNumCallsWithState(CALL_FILTER_ALL,
                exceptCall, null /* phoneAccountHandle*/, LIVE_CALL_STATES);
    }

    private boolean hasMaximumManagedLiveCalls(Call exceptCall) {
        return MAXIMUM_LIVE_CALLS <= getNumCallsWithState(false /* isSelfManaged */,
                exceptCall, null /* phoneAccountHandle */, LIVE_CALL_STATES);
@@ -2580,11 +2573,6 @@ public class CallsManager extends Call.ListenerBase
                phoneAccountHandle, CallState.RINGING);
    }

    private boolean hasMaximumOutgoingCalls(Call exceptCall) {
        return MAXIMUM_LIVE_CALLS <= getNumCallsWithState(CALL_FILTER_ALL,
                exceptCall, null /* phoneAccountHandle */, OUTGOING_CALL_STATES);
    }

    private boolean hasMaximumManagedOutgoingCalls(Call exceptCall) {
        return MAXIMUM_OUTGOING_CALLS <= getNumCallsWithState(false /* isSelfManaged */, exceptCall,
                null /* phoneAccountHandle */, OUTGOING_CALL_STATES);
@@ -2672,7 +2660,7 @@ public class CallsManager extends Call.ListenerBase
    }

    private boolean makeRoomForOutgoingCall(Call call, boolean isEmergency) {
        if (hasMaximumLiveCalls(call)) {
        if (hasMaximumManagedLiveCalls(call)) {
            // NOTE: If the amount of live calls changes beyond 1, this logic will probably
            // have to change.
            Call liveCall = getFirstCallWithState(LIVE_CALL_STATES);
@@ -2686,7 +2674,7 @@ public class CallsManager extends Call.ListenerBase
                return true;
            }

            if (hasMaximumOutgoingCalls(call)) {
            if (hasMaximumManagedOutgoingCalls(call)) {
                Call outgoingCall = getFirstCallWithState(OUTGOING_CALL_STATES);
                if (isEmergency && !outgoingCall.isEmergencyCall()) {
                    // Disconnect the current outgoing call if it's not an emergency call. If the
@@ -2708,13 +2696,20 @@ public class CallsManager extends Call.ListenerBase
                return false;
            }

            // Disconnected the live call if the outgoing call is an emergency call.
            if (isEmergency && !canHold(liveCall)) {
            if (hasMaximumManagedHoldingCalls(call)) {
                // There is no more room for any more calls, unless it's an emergency.
                if (isEmergency) {
                    // Kill the current active call, this is easier then trying to disconnect a
                    // holding call and hold an active call.
                    call.getAnalytics().setCallIsAdditional(true);
                    liveCall.getAnalytics().setCallIsInterrupted(true);
                    liveCall.disconnect();
                    return true;
                }
                return false;  // No more room!
            }

            // We have room for at least one more holding call at this point.

            // TODO: Remove once b/23035408 has been corrected.
            // If the live call is a conference, it will not have a target phone account set.  This
@@ -2751,7 +2746,7 @@ public class CallsManager extends Call.ListenerBase
            }

            // Try to hold the live call before attempting the new outgoing call.
            if (canHold(liveCall)) {
            if (liveCall.can(Connection.CAPABILITY_HOLD)) {
                Log.i(this, "makeRoomForOutgoingCall: holding live call.");
                call.getAnalytics().setCallIsAdditional(true);
                liveCall.getAnalytics().setCallIsInterrupted(true);
@@ -2996,10 +2991,13 @@ public class CallsManager extends Call.ListenerBase
                    !hasMaximumManagedLiveCalls(excludeCall) &&
                    !hasMaximumManagedHoldingCalls(excludeCall);
        } else {
            // Only permit self-managed outgoing calls if there is no ongoing emergency calls and
            // the ongoing call can be held.
            Call foregroundCall = getForegroundCall();
            return !hasEmergencyCall() && (foregroundCall == null || canHold(foregroundCall));
            // Only permit outgoing calls if there is no ongoing emergency calls and all other calls
            // are associated with the current PhoneAccountHandle.
            return !hasEmergencyCall() && (
                    (excludeCall != null && excludeCall.getHandoverSourceCall() != null) || (
                            !hasMaximumSelfManagedCalls(excludeCall, phoneAccountHandle)
                                    && !hasCallsForOtherPhoneAccount(phoneAccountHandle)
                                    && !hasManagedCalls()));
        }
    }

@@ -3085,9 +3083,14 @@ public class CallsManager extends Call.ListenerBase
        mPendingCall = call;

        // Figure out the name of the app in charge of the self-managed call(s).
        Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
        if (activeCall != null) {
            CharSequence ongoingAppName = activeCall.getTargetPhoneAccountLabel();
        Call selfManagedCall = mCalls.stream()
                .filter(c -> c.isSelfManaged())
                .findFirst()
                .orElse(null);
        CharSequence ongoingAppName = "";
        if (selfManagedCall != null) {
            ongoingAppName = selfManagedCall.getTargetPhoneAccountLabel();
        }
        Log.i(this, "startCallConfirmation: callId=%s, ongoingApp=%s", call.getId(),
                ongoingAppName);

@@ -3097,7 +3100,6 @@ public class CallsManager extends Call.ListenerBase
        confirmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivityAsUser(confirmIntent, UserHandle.CURRENT);
    }
    }

    /**
     * Disconnects all self-managed calls.
@@ -3118,14 +3120,6 @@ public class CallsManager extends Call.ListenerBase
        mCallAudioManager.switchBaseline();
    }

    private void disconnectCallsHaveDifferentConnectionService(Call exceptCall) {
        mCalls.stream().filter(c ->
                c.getConnectionService() != exceptCall.getConnectionService()
                        && c.getConnectionManagerPhoneAccount()
                        != exceptCall.getConnectionManagerPhoneAccount())
                .forEach(c -> c.disconnect());
    }

    /**
     * Dumps the state of the {@link CallsManager}.
     *
@@ -3598,87 +3592,4 @@ public class CallsManager extends Call.ListenerBase

        call.startCreateConnection(mPhoneAccountRegistrar);
    }

    ConnectionServiceFocusManager getConnectionServiceFocusManager() {
        return mConnectionSvrFocusMgr;
    }

    private boolean canHold(Call call) {
        return call.can(Connection.CAPABILITY_HOLD);
    }

    private final class ActionSetCallState implements PendingAction {

        private final Call mCall;
        private final int mState;
        private final String mTag;

        ActionSetCallState(Call call, int state, String tag) {
            mCall = call;
            mState = state;
            mTag = tag;
        }

        @Override
        public void performAction() {
            Log.d(this, "perform set call state for %s, state = %s", mCall, mState);
            setCallState(mCall, mState, mTag);
        }
    }

    private final class ActionUnHoldCall implements PendingAction {
        private final Call mCall;

        ActionUnHoldCall(Call call) {
            mCall = call;
        }

        @Override
        public void performAction() {
            Log.d(this, "perform unhold call for %s", mCall);
            mCall.unhold();
        }
    }

    private final class ActionAnswerCall implements PendingAction {
        private final Call mCall;
        private final int mVideoState;

        ActionAnswerCall(Call call, int videoState) {
            mCall = call;
            mVideoState = videoState;
        }

        @Override
        public void performAction() {
            Log.d(this, "perform answer call for %s, videoState = %d", mCall, mVideoState);
            for (CallsManagerListener listener : mListeners) {
                listener.onIncomingCallAnswered(mCall);
            }

            // We do not update the UI until we get confirmation of the answer() through
            // {@link #markCallAsActive}.
            mCall.answer(mVideoState);
            if (isSpeakerphoneAutoEnabledForVideoCalls(mVideoState)) {
                mCall.setStartWithSpeakerphoneOn(true);
            }
        }
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static final class RequestCallback implements
            ConnectionServiceFocusManager.RequestFocusCallback {
        private PendingAction mPendingAction;

        RequestCallback(PendingAction pendingAction) {
            mPendingAction = pendingAction;
        }

        @Override
        public void onRequestFocusDone(ConnectionServiceFocusManager.CallFocus call) {
            if (mPendingAction != null) {
                mPendingAction.performAction();
            }
        }
    }
}
Loading