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

Commit 04fe95c2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I17feaab5,I4157a1c5 into main

* changes:
  Add flag for auto data switch rat and ss
  Consider roaming when auto switch
parents b49deeab 8d8888f9
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
package: "com.android.internal.telephony.flags"

flag {
  name: "auto_switch_allow_roaming"
  namespace: "telephony"
  description: "Allow using roaming network as target if user allows it from settings."
  bug: "306488039"
}

flag {
  name: "auto_data_switch_rat_ss"
  namespace: "telephony"
  description: "Whether switch for better rat and signal strength"
  bug:"260928808"
}

flag {
  name: "use_alarm_callback"
  namespace: "telephony"
@@ -69,4 +83,3 @@ flag {
  description: "notify data activity changed for slot id"
  bug: "309896936"
}
+2 −1
Original line number Diff line number Diff line
@@ -265,7 +265,8 @@ public class PhoneFactory {

                sPhoneSwitcher = TelephonyComponentFactory.getInstance().inject(
                        PhoneSwitcher.class.getName()).
                        makePhoneSwitcher(maxActivePhones, sContext, Looper.myLooper());
                        makePhoneSwitcher(maxActivePhones, sContext, Looper.myLooper(),
                                featureFlags);

                sProxyController = ProxyController.getInstance(context);

+2 −2
Original line number Diff line number Diff line
@@ -481,8 +481,8 @@ public class TelephonyComponentFactory {
    }

    public PhoneSwitcher makePhoneSwitcher(int maxDataAttachModemCount, Context context,
            Looper looper) {
        return PhoneSwitcher.make(maxDataAttachModemCount, context, looper);
            Looper looper, @NonNull FeatureFlags featureFlags) {
        return PhoneSwitcher.make(maxDataAttachModemCount, context, looper, featureFlags);
    }

    /**
+187 −52
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.util.LocalLog;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.NotificationChannelController;
@@ -125,6 +126,7 @@ public class AutoDataSwitchController extends Handler {

    private final @NonNull LocalLog mLocalLog = new LocalLog(128);
    private final @NonNull Context mContext;
    private final @NonNull FeatureFlags mFlags;
    private final @NonNull SubscriptionManagerService mSubscriptionManagerService;
    private final @NonNull PhoneSwitcher mPhoneSwitcher;
    private final @NonNull AutoDataSwitchControllerCallback mPhoneSwitcherCallback;
@@ -167,15 +169,29 @@ public class AutoDataSwitchController extends Handler {
     * switch to.
     */
    private static class PhoneSignalStatus {
        /**
         * How preferred the current phone is.
         */
        enum UsableState {
            HOME(1), ROAMING_ENABLED(0), NOT_USABLE(-1);
            /**
             * The higher the score, the more preferred.
             * HOME is preferred over ROAMING assuming roaming is metered.
             */
            final int mScore;
            UsableState(int score) {
                this.mScore = score;
            }
        }
        /** The phone */
        private final @NonNull Phone mPhone;
        @NonNull private final Phone mPhone;
        /** Data registration state of the phone */
        private @RegistrationState int mDataRegState = NetworkRegistrationInfo
        @RegistrationState private int mDataRegState = NetworkRegistrationInfo
                .REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
        /** Current Telephony display info of the phone */
        private @NonNull TelephonyDisplayInfo mDisplayInfo;
        @NonNull private TelephonyDisplayInfo mDisplayInfo;
        /** Signal strength of the phone */
        private @NonNull SignalStrength mSignalStrength;
        @NonNull private SignalStrength mSignalStrength;
        /** {@code true} if this slot is listening for events. */
        private boolean mListeningForEvents;
        private PhoneSignalStatus(@NonNull Phone phone) {
@@ -193,11 +209,28 @@ public class AutoDataSwitchController extends Handler {
                    ? mPhone.getDataNetworkController().getDataConfigManager()
                            .getAutoDataSwitchScore(mDisplayInfo, mSignalStrength) : 0;
        }

        /**
         * @return The current usable state of the phone.
         */
        private UsableState getUsableState() {
            switch (mDataRegState) {
                case NetworkRegistrationInfo.REGISTRATION_STATE_HOME:
                    return UsableState.HOME;
                case NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING:
                    return mPhone.getDataRoamingEnabled()
                            ? UsableState.ROAMING_ENABLED : UsableState.NOT_USABLE;
                default:
                    return UsableState.NOT_USABLE;
            }
        }

        @Override
        public String toString() {
            return "{phone " + mPhone.getPhoneId()
                    + " score=" + getRatSignalScore() + " dataRegState="
                    + NetworkRegistrationInfo.registrationStateToString(mDataRegState)
                    + " " + getUsableState()
                    + " display=" + mDisplayInfo + " signalStrength=" + mSignalStrength.getLevel()
                    + " listeningForEvents=" + mListeningForEvents
                    + "}";
@@ -238,10 +271,11 @@ public class AutoDataSwitchController extends Handler {
     * @param phoneSwitcherCallback Callback for phone switcher to execute.
     */
    public AutoDataSwitchController(@NonNull Context context, @NonNull Looper looper,
            @NonNull PhoneSwitcher phoneSwitcher,
            @NonNull PhoneSwitcher phoneSwitcher, @NonNull FeatureFlags featureFlags,
            @NonNull AutoDataSwitchControllerCallback phoneSwitcherCallback) {
        super(looper);
        mContext = context;
        mFlags = featureFlags;
        mSubscriptionManagerService = SubscriptionManagerService.getInstance();
        mPhoneSwitcher = phoneSwitcher;
        mPhoneSwitcherCallback = phoneSwitcherCallback;
@@ -275,7 +309,7 @@ public class AutoDataSwitchController extends Handler {
    }

    /** Notify subscriptions changed. */
    public void notifySubscriptionsChanged() {
    public void notifySubscriptionsMappingChanged() {
        sendEmptyMessage(EVENT_SUBSCRIPTIONS_CHANGED);
    }

@@ -291,16 +325,19 @@ public class AutoDataSwitchController extends Handler {
                .collect(Collectors.toSet());
        // Track events only if there are at least two active visible subscriptions.
        if (activePhoneIds.size() < 2) activePhoneIds.clear();
        boolean changed = false;
        for (int phoneId = 0; phoneId < mPhonesSignalStatus.length; phoneId++) {
            if (activePhoneIds.contains(phoneId)
                    && !mPhonesSignalStatus[phoneId].mListeningForEvents) {
                registerAllEventsForPhone(phoneId);
                changed = true;
            } else if (!activePhoneIds.contains(phoneId)
                    && mPhonesSignalStatus[phoneId].mListeningForEvents) {
                unregisterAllEventsForPhone(phoneId);
                changed = true;
            }
        }
        logl("onSubscriptionChanged: " + Arrays.toString(mPhonesSignalStatus));
        if (changed) logl("onSubscriptionChanged: " + Arrays.toString(mPhonesSignalStatus));
    }

    /**
@@ -362,7 +399,7 @@ public class AutoDataSwitchController extends Handler {
            case EVENT_SERVICE_STATE_CHANGED:
                ar = (AsyncResult) msg.obj;
                phoneId = (int) ar.userObj;
                onRegistrationStateChanged(phoneId);
                onServiceStateChanged(phoneId);
                break;
            case EVENT_DISPLAY_INFO_CHANGED:
                ar = (AsyncResult) msg.obj;
@@ -396,7 +433,7 @@ public class AutoDataSwitchController extends Handler {
    /**
     * Called when registration state changed.
     */
    private void onRegistrationStateChanged(int phoneId) {
    private void onServiceStateChanged(int phoneId) {
        Phone phone = PhoneFactory.getPhone(phoneId);
        if (phone != null && isActiveModemPhone(phoneId)) {
            int oldRegState = mPhonesSignalStatus[phoneId].mDataRegState;
@@ -409,7 +446,7 @@ public class AutoDataSwitchController extends Handler {
                mPhonesSignalStatus[phoneId].mDataRegState = newRegState;
                if (isInService(oldRegState) != isInService(newRegState)
                        || isHomeService(oldRegState) != isHomeService(newRegState)) {
                    log("onRegistrationStateChanged: phone " + phoneId + " "
                    log("onServiceStateChanged: phone " + phoneId + " "
                            + NetworkRegistrationInfo.registrationStateToString(oldRegState)
                            + " -> "
                            + NetworkRegistrationInfo.registrationStateToString(newRegState));
@@ -562,35 +599,92 @@ public class AutoDataSwitchController extends Handler {
            boolean backToDefault = false;
            boolean needValidation = true;

            if (mFlags.autoSwitchAllowRoaming()) {
                if (mDefaultNetworkIsOnNonCellular) {
                log(debugMessage.append(", back to default as default network")
                        .append(" is active on nonCellular transport").toString());
                    debugMessage.append(", back to default as default network")
                            .append(" is active on nonCellular transport");
                    backToDefault = true;
                    needValidation = false;
                } else {
                    PhoneSignalStatus.UsableState defaultUsableState =
                            mPhonesSignalStatus[defaultDataPhoneId].getUsableState();
                    PhoneSignalStatus.UsableState currentUsableState =
                            mPhonesSignalStatus[preferredPhoneId].getUsableState();

                    boolean isCurrentUsable = currentUsableState.mScore
                            > PhoneSignalStatus.UsableState.NOT_USABLE.mScore;

                    if (currentUsableState.mScore < defaultUsableState.mScore) {
                        debugMessage.append(", back to default phone ").append(preferredPhoneId)
                                .append(" : ").append(defaultUsableState)
                                .append(" , backup phone: ").append(currentUsableState);

                        backToDefault = true;
                        // Require validation if the current preferred phone is usable.
                        needValidation = isCurrentUsable && mRequirePingTestBeforeSwitch;
                    } else if (defaultUsableState.mScore == currentUsableState.mScore) {
                        debugMessage.append(", default phone ").append(preferredPhoneId)
                                .append(" : ").append(defaultUsableState)
                                .append(" , backup phone: ").append(currentUsableState);

                        if (isCurrentUsable) {
                            // Both phones are usable.
                            if (isRatSignalStrengthBasedSwitchEnabled()) {
                                int defaultScore = mPhonesSignalStatus[defaultDataPhoneId]
                                        .getRatSignalScore();
                                int currentScore = mPhonesSignalStatus[preferredPhoneId]
                                        .getRatSignalScore();
                                if ((defaultScore - currentScore) > mScoreTolerance) {
                                    debugMessage
                                            .append(", back to default for higher score ")
                                            .append(defaultScore).append(" versus current ")
                                            .append(currentScore);
                                    backToDefault = true;
                                    needValidation = mRequirePingTestBeforeSwitch;
                                }
                            } else {
                                // Only OOS/in service switch is enabled, switch back.
                                debugMessage.append(", back to default as it's usable. ");
                                backToDefault = true;
                                needValidation = mRequirePingTestBeforeSwitch;
                            }
                        } else {
                            debugMessage.append(", back to default as both phones are unusable.");
                            backToDefault = true;
                            needValidation = false;
                        }
                    }
                }
            } else {
                if (mDefaultNetworkIsOnNonCellular) {
                    debugMessage.append(", back to default as default network")
                            .append(" is active on nonCellular transport");
                    backToDefault = true;
                    needValidation = false;
                } else if (!isHomeService(mPhonesSignalStatus[preferredPhoneId].mDataRegState)) {
                log(debugMessage.append(", back to default as backup phone lost HOME registration")
                        .toString());
                    debugMessage.append(", back to default as backup phone lost HOME registration");
                    backToDefault = true;
                    needValidation = false;
                } else if (isRatSignalStrengthBasedSwitchEnabled()) {
                    int defaultScore = mPhonesSignalStatus[defaultDataPhoneId].getRatSignalScore();
                    int currentScore = mPhonesSignalStatus[preferredPhoneId].getRatSignalScore();
                    if ((defaultScore - currentScore) > mScoreTolerance) {
                    log(debugMessage
                        debugMessage
                                .append(", back to default as default phone has higher score ")
                                .append(defaultScore).append(" versus current ")
                            .append(currentScore).toString());
                                .append(currentScore);
                        backToDefault = true;
                        needValidation = mRequirePingTestBeforeSwitch;
                    }
                } else if (isInService(mPhonesSignalStatus[defaultDataPhoneId].mDataRegState)) {
                log(debugMessage.append(", back to default as the default is back to service ")
                        .toString());
                    debugMessage.append(", back to default as the default is back to service ");
                    backToDefault = true;
                    needValidation = mRequirePingTestBeforeSwitch;
                }
            }

            if (backToDefault) {
                log(debugMessage.toString());
                mSelectedTargetPhoneId = defaultDataPhoneId;
                startStabilityCheck(DEFAULT_PHONE_INDEX, needValidation);
            } else {
@@ -625,20 +719,60 @@ public class AutoDataSwitchController extends Handler {
            return INVALID_PHONE_INDEX;
        }

        if (mFlags.autoSwitchAllowRoaming()) {
            // check whether primary and secondary signal status are worth switching
            if (!isRatSignalStrengthBasedSwitchEnabled()
                    && isHomeService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
                debugMessage.append(", no candidate as default phone is in HOME service");
                return INVALID_PHONE_INDEX;
            }
        } else {
            // check whether primary and secondary signal status are worth switching
            if (!isRatSignalStrengthBasedSwitchEnabled()
                    && isInService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
                debugMessage.append(", no candidate as default phone is in service");
                return INVALID_PHONE_INDEX;
            }
        }

        PhoneSignalStatus defaultPhoneStatus = mPhonesSignalStatus[defaultPhoneId];
        for (int phoneId = 0; phoneId < mPhonesSignalStatus.length; phoneId++) {
            if (phoneId != defaultPhoneId
                    // the alternative phone must have HOME availability
                    && isHomeService(mPhonesSignalStatus[phoneId].mDataRegState)) {
            if (phoneId == defaultPhoneId) continue;

            Phone secondaryDataPhone = null;
                debugMessage.append(", found phone ").append(phoneId).append(" in HOME reg");
            PhoneSignalStatus candidatePhoneStatus = mPhonesSignalStatus[phoneId];
            if (mFlags.autoSwitchAllowRoaming()) {
                PhoneSignalStatus.UsableState currentUsableState =
                        mPhonesSignalStatus[defaultPhoneId].getUsableState();
                PhoneSignalStatus.UsableState candidatePhoneUsableRank =
                        mPhonesSignalStatus[phoneId].getUsableState();
                debugMessage.append(", found phone ").append(phoneId).append(" is ").append(
                        candidatePhoneUsableRank)
                        .append(", current is ").append(currentUsableState);
                if (candidatePhoneUsableRank.mScore > currentUsableState.mScore) {
                    secondaryDataPhone = PhoneFactory.getPhone(phoneId);
                } else if (isRatSignalStrengthBasedSwitchEnabled()
                        && currentUsableState.mScore == candidatePhoneUsableRank.mScore) {
                    // Both phones are home or both roaming enabled, so compare RAT/signal score.

                    int defaultScore = defaultPhoneStatus.getRatSignalScore();
                    int candidateScore = candidatePhoneStatus.getRatSignalScore();
                    if ((candidateScore - defaultScore) > mScoreTolerance) {
                        debugMessage.append(" with higher score ").append(
                                        candidateScore)
                                .append(" versus current ").append(defaultScore);
                        secondaryDataPhone = PhoneFactory.getPhone(phoneId);
                    } else {
                        debugMessage.append(", but its score ").append(candidateScore)
                                .append(" doesn't meet the bar to switch given the current ")
                                .append(defaultScore);
                    }
                }
            } else if (isHomeService(candidatePhoneStatus.mDataRegState)) {
                // the alternative phone must have HOME availability
                debugMessage.append(", found phone ").append(phoneId).append(" in HOME service");

                if (isInService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
                if (isInService(defaultPhoneStatus.mDataRegState)) {
                    // Use score if RAT/signal strength based switch is enabled and both phone are
                    // in service.
                    if (isRatSignalStrengthBasedSwitchEnabled()) {
@@ -658,6 +792,8 @@ public class AutoDataSwitchController extends Handler {
                    // Only OOS/in service switch is enabled.
                    secondaryDataPhone = PhoneFactory.getPhone(phoneId);
                }
            }

            if (secondaryDataPhone != null) {
                // check auto switch feature enabled
                if (secondaryDataPhone.isDataAllowed()) {
@@ -667,7 +803,6 @@ public class AutoDataSwitchController extends Handler {
                }
            }
        }
        }
        debugMessage.append(", found no qualified candidate.");
        return INVALID_PHONE_INDEX;
    }
@@ -676,7 +811,7 @@ public class AutoDataSwitchController extends Handler {
     * @return {@code true} If the feature of switching base on RAT and signal strength is enabled.
     */
    private boolean isRatSignalStrengthBasedSwitchEnabled() {
        return mScoreTolerance >= 0;
        return mFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0;
    }

    /**
+23 −5
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATIO
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;

import static java.util.Arrays.copyOf;

import android.annotation.NonNull;
@@ -83,6 +84,7 @@ import com.android.internal.telephony.RadioConfig;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
@@ -184,6 +186,7 @@ public class PhoneSwitcher extends Handler {
    private final @NonNull NetworkRequestList mNetworkRequestList = new NetworkRequestList();
    protected final RegistrantList mActivePhoneRegistrants;
    private final SubscriptionManagerService mSubscriptionManagerService;
    private final @NonNull FeatureFlags mFlags;
    protected final Context mContext;
    private final LocalLog mLocalLog;
    protected PhoneState[] mPhoneStates;
@@ -397,9 +400,10 @@ public class PhoneSwitcher extends Handler {
    /**
     * Method to create singleton instance.
     */
    public static PhoneSwitcher make(int maxDataAttachModemCount, Context context, Looper looper) {
    public static PhoneSwitcher make(int maxDataAttachModemCount, Context context, Looper looper,
            @NonNull FeatureFlags flags) {
        if (sPhoneSwitcher == null) {
            sPhoneSwitcher = new PhoneSwitcher(maxDataAttachModemCount, context, looper);
            sPhoneSwitcher = new PhoneSwitcher(maxDataAttachModemCount, context, looper, flags);
        }

        return sPhoneSwitcher;
@@ -457,9 +461,11 @@ public class PhoneSwitcher extends Handler {
    }

    @VisibleForTesting
    public PhoneSwitcher(int maxActivePhones, Context context, Looper looper) {
    public PhoneSwitcher(int maxActivePhones, Context context, Looper looper,
            @NonNull FeatureFlags featureFlags) {
        super(looper);
        mContext = context;
        mFlags = featureFlags;
        mActiveModemCount = getTm().getActiveModemCount();
        mPhoneSubscriptions = new int[mActiveModemCount];
        mPhoneStates = new PhoneState[mActiveModemCount];
@@ -497,6 +503,12 @@ public class PhoneSwitcher extends Handler {
                                    @TelephonyManager.DataEnabledChangedReason int reason,
                                    @NonNull String callingPackage) {
                                PhoneSwitcher.this.onDataEnabledChanged();
                            }
                            @Override
                            public void onDataRoamingEnabledChanged(boolean enabled) {
                                PhoneSwitcher.this.mAutoDataSwitchController.evaluateAutoDataSwitch(
                                        AutoDataSwitchController
                                                .EVALUATION_REASON_DATA_SETTINGS_CHANGED);
                            }});
                phone.getDataSettingsManager().registerCallback(
                        mDataSettingsManagerCallbacks.get(phoneId));
@@ -546,7 +558,7 @@ public class PhoneSwitcher extends Handler {
            }
        };
        mAutoDataSwitchController = new AutoDataSwitchController(context, looper, this,
                mAutoDataSwitchCallback);
                mFlags, mAutoDataSwitchCallback);

        mContext.registerReceiver(mDefaultDataChangedReceiver,
                new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
@@ -647,7 +659,6 @@ public class PhoneSwitcher extends Handler {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_SUBSCRIPTION_CHANGED: {
                mAutoDataSwitchController.notifySubscriptionsChanged();
                onEvaluate(REQUESTS_UNCHANGED, "subscription changed");
                break;
            }
@@ -902,6 +913,12 @@ public class PhoneSwitcher extends Handler {
                                @NonNull String callingPackage) {
                            PhoneSwitcher.this.onDataEnabledChanged();
                        }
                        @Override
                        public void onDataRoamingEnabledChanged(boolean enabled) {
                            PhoneSwitcher.this.mAutoDataSwitchController.evaluateAutoDataSwitch(
                                    AutoDataSwitchController
                                            .EVALUATION_REASON_DATA_SETTINGS_CHANGED);
                        }
                    });
            phone.getDataSettingsManager().registerCallback(
                    mDataSettingsManagerCallbacks.get(phone.getPhoneId()));
@@ -1080,6 +1097,7 @@ public class PhoneSwitcher extends Handler {
                    registerForImsRadioTechChange(mContext, i);
                }
                diffDetected = true;
                mAutoDataSwitchController.notifySubscriptionsMappingChanged();
            }
        }

Loading