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

Commit ff6733ab authored by Hall Liu's avatar Hall Liu Committed by android-build-merger
Browse files

Merge "Refactor the holding logic in ImsPhoneCallTracker"

am: 62de98e1

Change-Id: I492a571986aef646d3936c8fa39efe47d27a8874
parents 93f94352 62de98e1
Loading
Loading
Loading
Loading
+5 −141
Original line number Diff line number Diff line
@@ -16,20 +16,19 @@

package com.android.internal.telephony;

import com.android.internal.telephony.sip.SipPhone;

import android.content.Context;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.RegistrantList;
import android.os.Registrant;
import android.telecom.VideoProfile;
import android.os.RegistrantList;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;

import com.android.internal.telephony.sip.SipPhone;

import java.util.ArrayList;
import java.util.Collections;
@@ -665,54 +664,6 @@ public class CallManager {
        phone.unregisterForSuppServiceFailed(handler);
    }

    /**
     * Answers a ringing or waiting call.
     *
     * Active call, if any, go on hold.
     * If active call can't be held, i.e., a background call of the same channel exists,
     * the active call will be hang up.
     *
     * Answering occurs asynchronously, and final notification occurs via
     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
     * java.lang.Object) registerForPreciseCallStateChanged()}.
     *
     * @exception CallStateException when call is not ringing or waiting
     */
    public void acceptCall(Call ringingCall) throws CallStateException {
        Phone ringingPhone = ringingCall.getPhone();

        if (VDBG) {
            Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")");
            Rlog.d(LOG_TAG, toString());
        }

        if ( hasActiveFgCall() ) {
            Phone activePhone = getActiveFgCall().getPhone();
            boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
            boolean sameChannel = (activePhone == ringingPhone);

            if (VDBG) {
                Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
            }

            if (sameChannel && hasBgCall) {
                getActiveFgCall().hangup();
            } else if (!sameChannel && !hasBgCall) {
                activePhone.switchHoldingAndActive();
            } else if (!sameChannel && hasBgCall) {
                getActiveFgCall().hangup();
            }
        }

        // We only support the AUDIO_ONLY video state in this scenario.
        ringingPhone.acceptCall(VideoProfile.STATE_AUDIO_ONLY);

        if (VDBG) {
            Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")");
            Rlog.d(LOG_TAG, toString());
        }
    }

    /**
     * Reject (ignore) a ringing call. In GSM, this means UDUB
     * (User Determined User Busy). Reject occurs asynchronously,
@@ -724,7 +675,6 @@ public class CallManager {
     */
    public void rejectCall(Call ringingCall) throws CallStateException {
        if (VDBG) {
            Rlog.d(LOG_TAG, "rejectCall(" +ringingCall + ")");
            Rlog.d(LOG_TAG, toString());
        }

@@ -738,92 +688,6 @@ public class CallManager {
        }
    }

    /**
     * Places active call on hold, and makes held call active.
     * Switch occurs asynchronously and may fail.
     *
     * There are 4 scenarios
     * 1. only active call but no held call, aka, hold
     * 2. no active call but only held call, aka, unhold
     * 3. both active and held calls from same phone, aka, swap
     * 4. active and held calls from different phones, aka, phone swap
     *
     * Final notification occurs via
     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
     * java.lang.Object) registerForPreciseCallStateChanged()}.
     *
     * @exception CallStateException if active call is ringing, waiting, or
     * dialing/alerting, or heldCall can't be active.
     * In these cases, this operation may not be performed.
     */
    public void switchHoldingAndActive(Call heldCall) throws CallStateException {
        Phone activePhone = null;
        Phone heldPhone = null;

        if (VDBG) {
            Rlog.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")");
            Rlog.d(LOG_TAG, toString());
        }

        if (hasActiveFgCall()) {
            activePhone = getActiveFgCall().getPhone();
        }

        if (heldCall != null) {
            heldPhone = heldCall.getPhone();
        }

        if (activePhone != null) {
            activePhone.switchHoldingAndActive();
        }

        if (heldPhone != null && heldPhone != activePhone) {
            heldPhone.switchHoldingAndActive();
        }

        if (VDBG) {
            Rlog.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")");
            Rlog.d(LOG_TAG, toString());
        }
    }

    /**
     * Hangup foreground call and resume the specific background call
     *
     * Note: this is noop if there is no foreground call or the heldCall is null
     *
     * @param heldCall to become foreground
     * @throws CallStateException
     */
    public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException {
        Phone foregroundPhone = null;
        Phone backgroundPhone = null;

        if (VDBG) {
            Rlog.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")");
            Rlog.d(LOG_TAG, toString());
        }

        if (hasActiveFgCall()) {
            foregroundPhone = getFgPhone();
            if (heldCall != null) {
                backgroundPhone = heldCall.getPhone();
                if (foregroundPhone == backgroundPhone) {
                    getActiveFgCall().hangup();
                } else {
                // the call to be hangup and resumed belongs to different phones
                    getActiveFgCall().hangup();
                    switchHoldingAndActive(heldCall);
                }
            }
        }

        if (VDBG) {
            Rlog.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")");
            Rlog.d(LOG_TAG, toString());
        }
    }

    /**
     * Whether or not the phone can conference in the current phone
     * state--that is, one call holding and one call active.
+22 −5
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ public class ImsPhone extends ImsPhoneBase {
    @Override
    public void
    switchHoldingAndActive() throws CallStateException {
        mCT.switchWaitingOrHoldingAndActive();
        throw new UnsupportedOperationException("Use hold() and unhold() instead.");
    }

    @Override
@@ -411,6 +411,23 @@ public class ImsPhone extends ImsPhoneBase {
        return mCT.isImsServiceReady();
    }

    /**
     * Hold the currently active call, possibly unholding a currently held call.
     * @throws CallStateException
     */
    public void holdActiveCall() throws CallStateException {
        mCT.holdActiveCall();
    }

    /**
     * Unhold the currently active call, possibly holding a currently active call.
     * If the call tracker is already in the middle of a hold operation, this is a noop.
     * @throws CallStateException
     */
    public void unholdHeldCall() throws CallStateException {
        mCT.unholdHeldCall();
    }

    private boolean handleCallDeflectionIncallSupplementaryService(
            String dialString) {
        if (dialString.length() > 1) {
@@ -494,8 +511,8 @@ public class ImsPhone extends ImsPhoneBase {
                    if (DBG) logd("MmiCode 1: hangup foreground");
                    mCT.hangup(call);
                } else {
                    if (DBG) logd("MmiCode 1: switchWaitingOrHoldingAndActive");
                    mCT.switchWaitingOrHoldingAndActive();
                    if (DBG) logd("MmiCode 1: holdActiveCallForWaitingCall");
                    mCT.holdActiveCallForWaitingCall();
                }
            }
        } catch (CallStateException e) {
@@ -522,8 +539,8 @@ public class ImsPhone extends ImsPhoneBase {
                    if (DBG) logd("MmiCode 2: accept ringing call");
                    mCT.acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
                } else {
                    if (DBG) logd("MmiCode 2: switchWaitingOrHoldingAndActive");
                    mCT.switchWaitingOrHoldingAndActive();
                    if (DBG) logd("MmiCode 2: holdActiveCall");
                    mCT.holdActiveCall();
                }
            } catch (CallStateException e) {
                if (DBG) Rlog.d(LOG_TAG, "switch failed", e);
+200 −102

File changed.

Preview size limit exceeded, changes collapsed.

+16 −68
Original line number Diff line number Diff line
@@ -15,6 +15,22 @@
 */
package com.android.internal.telephony;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyChar;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -27,26 +43,9 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.lang.reflect.Field;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyChar;
import static org.mockito.Mockito.anyString;

public class CallManagerTest extends TelephonyTest {

    @Mock
@@ -152,12 +151,6 @@ public class CallManagerTest extends TelephonyTest {
        assertEquals(0, dialArgsCaptor.getValue().videoState);
    }

    @SmallTest @Test
    public void testBasicAcceptCall() throws Exception {
        CallManager.getInstance().acceptCall(mRingingCall);
        verify(mPhone, times(1)).acceptCall(anyInt());
    }

    @SmallTest @Test
    public void testBasicRejectCall() throws Exception {
        //verify can dial and dial function of the phone is being triggered
@@ -229,51 +222,6 @@ public class CallManagerTest extends TelephonyTest {
        verify(mPhone, times(1)).setMute(true);
    }

    @SmallTest @Test
    public void testSwitchHoldingAndActive() throws Exception {
        /* case 1: only active call */
        doReturn(false).when(mFgCall).isIdle();
        CallManager.getInstance().switchHoldingAndActive(null);
        verify(mPhone, times(1)).switchHoldingAndActive();
        /* case 2: no active call but only held call, aka, unhold */
        doReturn(true).when(mFgCall).isIdle();
        CallManager.getInstance().switchHoldingAndActive(mBgCall);
        verify(mPhone, times(2)).switchHoldingAndActive();
        /* case 3: both active and held calls from same phone, aka, swap */
        doReturn(false).when(mFgCall).isIdle();
        CallManager.getInstance().switchHoldingAndActive(mBgCall);
        verify(mPhone, times(3)).switchHoldingAndActive();
        GsmCdmaPhone mPhoneHold = Mockito.mock(GsmCdmaPhone.class);
        /* case 4: active and held calls from different phones, aka, phone swap */
        doReturn(mPhoneHold).when(mBgCall).getPhone();
        CallManager.getInstance().switchHoldingAndActive(mBgCall);
        verify(mPhone, times(4)).switchHoldingAndActive();
        verify(mPhoneHold, times(1)).switchHoldingAndActive();
    }

    @SmallTest @Test
    public void testHangupForegroundResumeBackground() throws Exception {
        CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
        /* no active fgCall */
        verify(mPhone, times(0)).switchHoldingAndActive();
        verify(mFgCall, times(0)).hangup();

        /* have active foreground call, get hanged up */
        doReturn(false).when(mFgCall).isIdle();
        CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
        verify(mFgCall, times(1)).hangup();
        verify(mPhone, times(0)).switchHoldingAndActive();

        /* mock bgcall and fgcall from different phone */
        GsmCdmaPhone mPhoneHold = Mockito.mock(GsmCdmaPhone.class);
        doReturn(mPhoneHold).when(mBgCall).getPhone();
        CallManager.getInstance().hangupForegroundResumeBackground(mBgCall);
        verify(mFgCall, times(2)).hangup();
        /* always hangup fgcall and both phone trigger swap */
        verify(mPhoneHold, times(1)).switchHoldingAndActive();
        verify(mPhone, times(1)).switchHoldingAndActive();
    }

    @SmallTest @Test
    public void testFgCallActiveDial() throws Exception {
        /* set Fg/Bg Call state to active, verify CallManager Logical */
+11 −11
Original line number Diff line number Diff line
@@ -120,18 +120,18 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest {
        }
    }

    private void imsCallMocking(final ImsCall mImsCall) throws Exception {
    private void imsCallMocking(final ImsCall imsCall) throws Exception {

        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                // trigger the listener on accept call
                if (mImsCallListener != null) {
                    mImsCallListener.onCallStarted(mImsCall);
                    mImsCallListener.onCallStarted(imsCall);
                }
                return null;
            }
        }).when(mImsCall).accept(anyInt());
        }).when(imsCall).accept(anyInt());

        doAnswer(new Answer<Void>() {
            @Override
@@ -139,12 +139,12 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest {
                // trigger the listener on reject call
                int reasonCode = (int) invocation.getArguments()[0];
                if (mImsCallListener != null) {
                    mImsCallListener.onCallStartFailed(mImsCall, new ImsReasonInfo(reasonCode, -1));
                    mImsCallListener.onCallTerminated(mImsCall, new ImsReasonInfo(reasonCode, -1));
                    mImsCallListener.onCallStartFailed(imsCall, new ImsReasonInfo(reasonCode, -1));
                    mImsCallListener.onCallTerminated(imsCall, new ImsReasonInfo(reasonCode, -1));
                }
                return null;
            }
        }).when(mImsCall).reject(anyInt());
        }).when(imsCall).reject(anyInt());

        doAnswer(new Answer<Void>() {
            @Override
@@ -152,23 +152,23 @@ public class ImsPhoneCallTrackerTest extends TelephonyTest {
                // trigger the listener on reject call
                int reasonCode = (int) invocation.getArguments()[0];
                if (mImsCallListener != null) {
                    mImsCallListener.onCallTerminated(mImsCall, new ImsReasonInfo(reasonCode, -1));
                    mImsCallListener.onCallTerminated(imsCall, new ImsReasonInfo(reasonCode, -1));
                }
                return null;
            }
        }).when(mImsCall).terminate(anyInt());
        }).when(imsCall).terminate(anyInt());

        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                if (mImsCallListener != null) {
                    mImsCallListener.onCallHeld(mImsCall);
                    mImsCallListener.onCallHeld(imsCall);
                }
                return null;
            }
        }).when(mImsCall).hold();
        }).when(imsCall).hold();

        mImsCall.attachSession(mImsCallSession);
        imsCall.attachSession(mImsCallSession);
    }

    @Before
Loading