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

Commit 4b88a5c7 authored by Malcolm Chen's avatar Malcolm Chen Committed by Xiangyu/Malcolm Chen
Browse files

Fix that PhoneSwitcher only listens to call state change of default sub.

PhoneSwitcher currently listens to precise calls state change through
PhoneStateListener, which without specifying a subId will monitor call
state of default voice subscription. This is enough for CBRS data switching
as default voice subscription is always the primary, but not enough as
we now support switching in DSDS case.
So here we are making the change to listen to precise call state change
on both phones (CS or PS call).

Bug: 134981077
Test: manual and unittest
Change-Id: Idd21283ba3f01bc99fd9afff7c83a79711649f01
parent 97e5eb0b
Loading
Loading
Loading
Loading
+38 −53
Original line number Diff line number Diff line
@@ -17,8 +17,6 @@
package com.android.internal.telephony;

import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
import static android.telephony.PhoneStateListener.LISTEN_PRECISE_CALL_STATE;
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -50,7 +48,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.PreciseCallState;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -223,15 +220,17 @@ public class PhoneSwitcher extends Handler {
    // mEmergencyOverride, start the countdown to remove the override using the message
    // EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE. The only exception to this is if the device moves to
    // ECBM, which is detected by EVENT_EMERGENCY_TOGGLE.
    private static final int EVENT_PHONE_IN_CALL_CHANGED          = 109;
    @VisibleForTesting
    public static final int EVENT_PRECISE_CALL_STATE_CHANGED      = 109;
    private static final int EVENT_NETWORK_VALIDATION_DONE        = 110;
    private static final int EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK = 111;
    private static final int EVENT_MODEM_COMMAND_DONE             = 112;
    private static final int EVENT_MODEM_COMMAND_RETRY            = 113;
    private static final int EVENT_DATA_ENABLED_CHANGED           = 114;
    @VisibleForTesting
    public static final int EVENT_DATA_ENABLED_CHANGED            = 114;
    // An emergency call is about to be originated and requires the DDS to be overridden.
    // Uses EVENT_PHONE_IN_CALL_CHANGED message to start countdown to finish override defined in
    // mEmergencyOverride. If EVENT_PHONE_IN_CALL_CHANGED does not come in
    // Uses EVENT_PRECISE_CALL_STATE_CHANGED message to start countdown to finish override defined
    // in mEmergencyOverride. If EVENT_PRECISE_CALL_STATE_CHANGED does not come in
    // DEFAULT_DATA_OVERRIDE_TIMEOUT_MS milliseconds, then the override will be removed.
    private static final int EVENT_OVERRIDE_DDS_FOR_EMERGENCY     = 115;
    // If it exists, remove the current mEmergencyOverride DDS override.
@@ -315,6 +314,22 @@ public class PhoneSwitcher extends Handler {
        mValidator = CellularNetworkValidator.getInstance();
    }

    private boolean isPhoneInVoiceCallChanged() {
        int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall;
        // If there's no active call, the value will become INVALID_PHONE_INDEX
        // and internet data will be switched back to system selected or user selected
        // subscription.
        mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX;
        for (Phone phone : mPhones) {
            if (isCallActive(phone) || isCallActive(phone.getImsPhone())) {
                mPhoneIdInVoiceCall = phone.getPhoneId();
                break;
            }
        }

        return (mPhoneIdInVoiceCall != oldPhoneIdInVoiceCall);
    }

    @VisibleForTesting
    public PhoneSwitcher(int maxActivePhones, int numPhones, Context context,
            SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
@@ -335,58 +350,25 @@ public class PhoneSwitcher extends Handler {
            public void onPhoneCapabilityChanged(PhoneCapability capability) {
                onPhoneCapabilityChangedInternal(capability);
            }

            @Override
            public void onPreciseCallStateChanged(PreciseCallState callState) {
                int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall;
                // If there's no active call, the value will become INVALID_PHONE_INDEX
                // and internet data will be switched back to system selected or user selected
                // subscription.
                mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX;
                for (Phone phone : mPhones) {
                    if (isCallActive(phone) || isCallActive(phone.getImsPhone())) {
                        mPhoneIdInVoiceCall = phone.getPhoneId();
                        break;
                    }
                }

                if (mPhoneIdInVoiceCall != oldPhoneIdInVoiceCall) {
                    log("mPhoneIdInVoiceCall changed from" + oldPhoneIdInVoiceCall
                            + " to " + mPhoneIdInVoiceCall);

                    // Switches and listens to the updated voice phone.
                    Phone dataPhone = findPhoneById(mPhoneIdInVoiceCall);
                    if (dataPhone != null && dataPhone.getDataEnabledSettings() != null) {
                        dataPhone.getDataEnabledSettings()
                                .registerForDataEnabledChanged(getInstance(),
                                        EVENT_DATA_ENABLED_CHANGED, null);
                    }

                    Phone oldDataPhone = findPhoneById(oldPhoneIdInVoiceCall);
                    if (oldDataPhone != null && oldDataPhone.getDataEnabledSettings() != null) {
                        oldDataPhone.getDataEnabledSettings()
                                .unregisterForDataEnabledChanged(getInstance());
                    }

                    Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PHONE_IN_CALL_CHANGED);
                    msg.sendToTarget();
                }
            }
        };

        mValidator = CellularNetworkValidator.getInstance();

        TelephonyManager telephonyManager =
                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(mPhoneStateListener, LISTEN_PHONE_CAPABILITY_CHANGE
                | LISTEN_PRECISE_CALL_STATE);

        mActivePhoneRegistrants = new RegistrantList();
        mPhoneStates = new PhoneState[numPhones];
        for (int i = 0; i < numPhones; i++) {
            mPhoneStates[i] = new PhoneState();
            if (mPhones[i] != null) {
                mPhones[i].registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
                // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone.
                mPhones[i].registerForPreciseCallStateChanged(
                        this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
                if (mPhones[i].getImsPhone() != null) {
                    mPhones[i].getImsPhone().registerForPreciseCallStateChanged(
                            this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
                }
                mPhones[i].getDataEnabledSettings().registerForDataEnabledChanged(
                        this, EVENT_DATA_ENABLED_CHANGED, null);
            }
        }

@@ -510,7 +492,10 @@ public class PhoneSwitcher extends Handler {
                onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE");
                break;
            }
            case EVENT_PHONE_IN_CALL_CHANGED: {
            case EVENT_PRECISE_CALL_STATE_CHANGED: {
                // If the phoneId in voice call didn't change, do nothing.
                if (!isPhoneInVoiceCallChanged()) break;

                // Only handle this event if we are currently waiting for the emergency call
                // associated with the override request to start or end.
                if (mEmergencyOverride != null && mEmergencyOverride.mPendingOriginatingCall) {
@@ -529,7 +514,7 @@ public class PhoneSwitcher extends Handler {
            }
            // fall through
            case EVENT_DATA_ENABLED_CHANGED:
                if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PHONE_IN_CALL_CHANGED")) {
                if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PRECISE_CALL_STATE_CHANGED")) {
                    logDataSwitchEvent(mOpptDataSubId,
                            TelephonyEvent.EventState.EVENT_STATE_START,
                            DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL);
@@ -601,8 +586,8 @@ public class PhoneSwitcher extends Handler {
                Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE);
                // Make sure that if we never get an incall indication that we remove the override.
                sendMessageDelayed(msg2, DEFAULT_DATA_OVERRIDE_TIMEOUT_MS);
                // Wait for call to end and EVENT_PHONE_IN_CALL_CHANGED to be called, then start
                // timer to remove DDS emergency override.
                // Wait for call to end and EVENT_PRECISE_CALL_STATE_CHANGED to be called, then
                // start timer to remove DDS emergency override.
                if (!onEvaluate(REQUESTS_UNCHANGED, "emer_override_dds")) {
                    // Nothing changed as a result of override, so no modem command was sent. Treat
                    // as success.
+20 −3
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.internal.telephony;

import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED;
import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -565,8 +568,16 @@ public class PhoneSwitcherTest extends TelephonyTest {
        setAllPhonesInactive();
        // Initialization done.

        // Phone2 has active call. So data switch to it.
        // Phone2 has active call, but data is turned off. So no data switching should happen.
        notifyDataEnabled(false);
        notifyPhoneAsInCall(mPhone2);
        verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
        waitABit();
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));

        // Phone2 has active call. So data switch to it.
        notifyDataEnabled(true);
        verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
        assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 1));
        assertFalse(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, 0));
@@ -863,13 +874,19 @@ public class PhoneSwitcherTest extends TelephonyTest {

    private void notifyPhoneAsInCall(Phone phone) {
        doReturn(mActiveCall).when(phone).getForegroundCall();
        mPhoneSwitcher.mPhoneStateListener.onPreciseCallStateChanged(null);
        mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
        waitABit();
    }

    private void notifyPhoneAsInactive(Phone phone) {
        doReturn(mInactiveCall).when(phone).getForegroundCall();
        mPhoneSwitcher.mPhoneStateListener.onPreciseCallStateChanged(null);
        mPhoneSwitcher.sendEmptyMessage(EVENT_PRECISE_CALL_STATE_CHANGED);
        waitABit();
    }

    private void notifyDataEnabled(boolean dataEnabled) {
        doReturn(dataEnabled).when(mDataEnabledSettings).isDataEnabled(anyInt());
        mPhoneSwitcher.sendEmptyMessage(EVENT_DATA_ENABLED_CHANGED);
        waitABit();
    }