Loading flags/data.aconfig +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" Loading Loading @@ -69,4 +83,3 @@ flag { description: "notify data activity changed for slot id" bug: "309896936" } src/java/com/android/internal/telephony/PhoneFactory.java +2 −1 Original line number Diff line number Diff line Loading @@ -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); Loading src/java/com/android/internal/telephony/TelephonyComponentFactory.java +2 −2 Original line number Diff line number Diff line Loading @@ -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); } /** Loading src/java/com/android/internal/telephony/data/AutoDataSwitchController.java +187 −52 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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 + "}"; Loading Loading @@ -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; Loading Loading @@ -275,7 +309,7 @@ public class AutoDataSwitchController extends Handler { } /** Notify subscriptions changed. */ public void notifySubscriptionsChanged() { public void notifySubscriptionsMappingChanged() { sendEmptyMessage(EVENT_SUBSCRIPTIONS_CHANGED); } Loading @@ -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)); } /** Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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)); Loading Loading @@ -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 { Loading Loading @@ -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()) { Loading @@ -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()) { Loading @@ -667,7 +803,6 @@ public class AutoDataSwitchController extends Handler { } } } } debugMessage.append(", found no qualified candidate."); return INVALID_PHONE_INDEX; } Loading @@ -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; } /** Loading src/java/com/android/internal/telephony/data/PhoneSwitcher.java +23 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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]; Loading Loading @@ -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)); Loading Loading @@ -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)); Loading Loading @@ -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; } Loading Loading @@ -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())); Loading Loading @@ -1080,6 +1097,7 @@ public class PhoneSwitcher extends Handler { registerForImsRadioTechChange(mContext, i); } diffDetected = true; mAutoDataSwitchController.notifySubscriptionsMappingChanged(); } } Loading Loading
flags/data.aconfig +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" Loading Loading @@ -69,4 +83,3 @@ flag { description: "notify data activity changed for slot id" bug: "309896936" }
src/java/com/android/internal/telephony/PhoneFactory.java +2 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
src/java/com/android/internal/telephony/TelephonyComponentFactory.java +2 −2 Original line number Diff line number Diff line Loading @@ -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); } /** Loading
src/java/com/android/internal/telephony/data/AutoDataSwitchController.java +187 −52 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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 + "}"; Loading Loading @@ -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; Loading Loading @@ -275,7 +309,7 @@ public class AutoDataSwitchController extends Handler { } /** Notify subscriptions changed. */ public void notifySubscriptionsChanged() { public void notifySubscriptionsMappingChanged() { sendEmptyMessage(EVENT_SUBSCRIPTIONS_CHANGED); } Loading @@ -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)); } /** Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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)); Loading Loading @@ -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 { Loading Loading @@ -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()) { Loading @@ -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()) { Loading @@ -667,7 +803,6 @@ public class AutoDataSwitchController extends Handler { } } } } debugMessage.append(", found no qualified candidate."); return INVALID_PHONE_INDEX; } Loading @@ -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; } /** Loading
src/java/com/android/internal/telephony/data/PhoneSwitcher.java +23 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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]; Loading Loading @@ -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)); Loading Loading @@ -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)); Loading Loading @@ -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; } Loading Loading @@ -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())); Loading Loading @@ -1080,6 +1097,7 @@ public class PhoneSwitcher extends Handler { registerForImsRadioTechChange(mContext, i); } diffDetected = true; mAutoDataSwitchController.notifySubscriptionsMappingChanged(); } } Loading