diff options
Diffstat (limited to 'src/java/com/android/internal/telephony/data/PhoneSwitcher.java')
-rw-r--r-- | src/java/com/android/internal/telephony/data/PhoneSwitcher.java | 433 |
1 files changed, 64 insertions, 369 deletions
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java index d2fdf4abb9..cf1a47d3f6 100644 --- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java +++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java @@ -18,6 +18,7 @@ package com.android.internal.telephony.data; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG; +import static android.telephony.SubscriptionManager.DEFAULT_PHONE_INDEX; import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -27,14 +28,10 @@ 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; import android.annotation.Nullable; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; import android.content.BroadcastReceiver; import android.content.Context; @@ -50,7 +47,6 @@ import android.net.NetworkSpecifier; import android.net.TelephonyNetworkSpecifier; import android.os.AsyncResult; import android.os.Build; -import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -58,10 +54,7 @@ import android.os.PersistableBundle; import android.os.Registrant; import android.os.RegistrantList; import android.os.RemoteException; -import android.provider.Settings; -import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; -import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionInfo; @@ -79,6 +72,7 @@ import android.util.Log; import com.android.ims.ImsException; import com.android.ims.ImsManager; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.Call; import com.android.internal.telephony.CommandException; import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.IccCard; @@ -96,7 +90,6 @@ import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDeman import com.android.internal.telephony.subscription.SubscriptionInfoInternal; import com.android.internal.telephony.subscription.SubscriptionManagerService; import com.android.internal.telephony.subscription.SubscriptionManagerService.WatchedInt; -import com.android.internal.telephony.util.NotificationChannelController; import com.android.internal.util.IndentingPrintWriter; import com.android.telephony.Rlog; @@ -121,21 +114,6 @@ public class PhoneSwitcher extends Handler { private static final String LOG_TAG = "PhoneSwitcher"; protected static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE); - /** Fragment "key" argument passed thru {@link #SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS} */ - private static final String SETTINGS_EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key"; - /** - * When starting this activity, this extra can also be specified to supply a Bundle of arguments - * to pass to that fragment when it is instantiated during the initial creation of the activity. - */ - private static final String SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS = - ":settings:show_fragment_args"; - /** The res Id of the auto data switch fragment in settings. **/ - private static final String AUTO_DATA_SWITCH_SETTING_R_ID = "auto_data_switch"; - /** Notification tag **/ - private static final String AUTO_DATA_SWITCH_NOTIFICATION_TAG = "auto_data_switch"; - /** Notification ID **/ - private static final int AUTO_DATA_SWITCH_NOTIFICATION_ID = 1; - private static final int MODEM_COMMAND_RETRY_PERIOD_MS = 5000; // After the emergency call ends, wait for a few seconds to see if we enter ECBM before starting // the countdown to remove the emergency DDS override. @@ -257,9 +235,6 @@ public class PhoneSwitcher extends Handler { // its value will be DEFAULT_SUBSCRIPTION_ID. private int mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; - /** The count of consecutive auto switch validation failure **/ - private int mAutoSwitchRetryFailedCount = 0; - // The phone ID that has an active voice call. If set, and its mobile data setting is on, // it will become the mPreferredDataPhoneId. protected int mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX; @@ -302,10 +277,10 @@ public class PhoneSwitcher extends Handler { // ECBM, which is detected by EVENT_EMERGENCY_TOGGLE. private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 109; private static final int EVENT_NETWORK_VALIDATION_DONE = 110; - private static final int EVENT_EVALUATE_AUTO_SWITCH = 111; + private static final int EVENT_MODEM_COMMAND_DONE = 112; private static final int EVENT_MODEM_COMMAND_RETRY = 113; - private static final int EVENT_SERVICE_STATE_CHANGED = 114; + // An emergency call is about to be originated and requires the DDS to be overridden. // 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 @@ -318,7 +293,6 @@ public class PhoneSwitcher extends Handler { private static final int EVENT_NETWORK_AVAILABLE = 118; private static final int EVENT_PROCESS_SIM_STATE_CHANGE = 119; private static final int EVENT_IMS_RADIO_TECH_CHANGED = 120; - private static final int EVENT_MEETS_AUTO_DATA_SWITCH_STATE = 121; // List of events triggers re-evaluations private static final String EVALUATION_REASON_RADIO_ON = "EVENT_RADIO_ON"; @@ -343,23 +317,9 @@ public class PhoneSwitcher extends Handler { private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure; - /** - * {@code true} if requires ping test before switching preferred data modem; otherwise, switch - * even if ping test fails. - */ - private boolean mRequirePingTestBeforeDataSwitch = true; - - /** - * Time threshold in ms to define a internet connection status to be stable(e.g. out of service, - * in service, wifi is the default active network.etc), while -1 indicates auto switch - * feature disabled. - */ - private long mAutoDataSwitchAvailabilityStabilityTimeThreshold = -1; - - /** - * The maximum number of retries when a validation for switching failed. - */ - private int mAutoDataSwitchValidationMaxRetry; + private AutoDataSwitchController mAutoDataSwitchController; + private AutoDataSwitchController.AutoDataSwitchControllerCallback + mAutoDataSwitchCallback; /** Data settings manager callback. Key is the phone id. */ private final @NonNull Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks = @@ -368,12 +328,10 @@ public class PhoneSwitcher extends Handler { private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback { public int mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; public int mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; - public boolean isDefaultNetworkOnCellular = false; @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) { - isDefaultNetworkOnCellular = true; if (SubscriptionManager.isValidSubscriptionId(mExpectedSubId) && mExpectedSubId == getSubIdFromNetworkSpecifier( networkCapabilities.getNetworkSpecifier())) { @@ -384,22 +342,13 @@ public class PhoneSwitcher extends Handler { mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; } - } else { - if (isDefaultNetworkOnCellular) { - // non-cellular transport is active - isDefaultNetworkOnCellular = false; - log("default network is active on non cellular"); - evaluateIfAutoSwitchIsNeeded(); - } } + mAutoDataSwitchController.updateDefaultNetworkCapabilities(networkCapabilities); } @Override public void onLost(Network network) { - // try find an active sub to switch to - if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) { - sendEmptyMessage(EVENT_EVALUATE_AUTO_SWITCH); - } + mAutoDataSwitchController.updateDefaultNetworkCapabilities(null); } } @@ -551,8 +500,6 @@ public class PhoneSwitcher extends Handler { }}); phone.getDataSettingsManager().registerCallback( mDataSettingsManagerCallbacks.get(phoneId)); - phone.getServiceStateTracker().registerForServiceStateChanged(this, - EVENT_SERVICE_STATE_CHANGED, phoneId); registerForImsRadioTechChange(context, phoneId); } Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); @@ -563,8 +510,6 @@ public class PhoneSwitcher extends Handler { PhoneFactory.getPhone(0).mCi.registerForOn(this, EVENT_RADIO_ON, null); } - readDeviceResourceConfig(); - TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); telephonyRegistryManager.addOnSubscriptionsChangedListener( @@ -573,6 +518,36 @@ public class PhoneSwitcher extends Handler { mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + mAutoDataSwitchCallback = new AutoDataSwitchController.AutoDataSwitchControllerCallback() { + @Override + public void onRequireValidation(int targetPhoneId, boolean needValidation) { + int targetSubId = targetPhoneId == DEFAULT_PHONE_INDEX + ? DEFAULT_SUBSCRIPTION_ID + : mSubscriptionManagerService.getSubId(targetPhoneId); + PhoneSwitcher.this.validate(targetSubId, needValidation, + DataSwitch.Reason.DATA_SWITCH_REASON_AUTO, null); + } + + @Override + public void onRequireImmediatelySwitchToPhone(int targetPhoneId, + @AutoDataSwitchController.AutoDataSwitchEvaluationReason int reason) { + PhoneSwitcher.this.mAutoSelectedDataSubId = + targetPhoneId == DEFAULT_PHONE_INDEX + ? DEFAULT_SUBSCRIPTION_ID + : mSubscriptionManagerService.getSubId(targetPhoneId); + PhoneSwitcher.this.evaluateIfImmediateDataSwitchIsNeeded( + AutoDataSwitchController.evaluationReasonToString(reason), + DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); + } + + @Override + public void onRequireCancelAnyPendingAutoSwitchValidation() { + PhoneSwitcher.this.cancelPendingAutoDataSwitchValidation(); + } + }; + mAutoDataSwitchController = new AutoDataSwitchController(context, looper, this, + mAutoDataSwitchCallback); + mContext.registerReceiver(mDefaultDataChangedReceiver, new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)); @@ -675,19 +650,6 @@ public class PhoneSwitcher extends Handler { onEvaluate(REQUESTS_UNCHANGED, "subscription changed"); break; } - case EVENT_SERVICE_STATE_CHANGED: { - AsyncResult ar = (AsyncResult) msg.obj; - final int phoneId = (int) ar.userObj; - onServiceStateChanged(phoneId); - break; - } - case EVENT_MEETS_AUTO_DATA_SWITCH_STATE: { - final int targetSubId = msg.arg1; - final boolean needValidation = (boolean) msg.obj; - validate(targetSubId, needValidation, - DataSwitch.Reason.DATA_SWITCH_REASON_AUTO, null); - break; - } case EVENT_PRIMARY_DATA_SUB_CHANGED: { evaluateIfImmediateDataSwitchIsNeeded("primary data sub changed", DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); @@ -718,9 +680,6 @@ public class PhoneSwitcher extends Handler { onEvaluate(REQUESTS_CHANGED, "emergencyToggle"); break; } - case EVENT_EVALUATE_AUTO_SWITCH: - evaluateIfAutoSwitchIsNeeded(); - break; case EVENT_RADIO_CAPABILITY_CHANGED: { final int phoneId = msg.arg1; sendRilCommands(phoneId); @@ -792,7 +751,8 @@ public class PhoneSwitcher extends Handler { DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); if (!isAnyVoiceCallActiveOnDevice()) { // consider auto switch on hang up all voice call - evaluateIfAutoSwitchIsNeeded(); + mAutoDataSwitchController.evaluateAutoDataSwitch( + AutoDataSwitchController.EVALUATION_REASON_VOICE_CALL_END); } break; } @@ -892,33 +852,19 @@ public class PhoneSwitcher extends Handler { } else if (TelephonyManager.SIM_STATE_LOADED == simState) { if (mCurrentDdsSwitchFailure.get(slotIndex).contains( CommandException.Error.INVALID_SIM_STATE) - && (TelephonyManager.SIM_STATE_LOADED == simState) && isSimApplicationReady(slotIndex)) { sendRilCommands(slotIndex); } // SIM loaded after subscriptions slot mapping are done. Evaluate for auto // data switch. - sendEmptyMessage(EVENT_EVALUATE_AUTO_SWITCH); + mAutoDataSwitchController.evaluateAutoDataSwitch( + AutoDataSwitchController.EVALUATION_REASON_SIM_LOADED); } break; } } } - /** - * Read the default device config from any default phone because the resource config are per - * device. No need to register callback for the same reason. - */ - private void readDeviceResourceConfig() { - Phone phone = PhoneFactory.getDefaultPhone(); - DataConfigManager dataConfig = phone.getDataNetworkController().getDataConfigManager(); - mRequirePingTestBeforeDataSwitch = dataConfig.isPingTestBeforeAutoDataSwitchRequired(); - mAutoDataSwitchAvailabilityStabilityTimeThreshold = - dataConfig.getAutoDataSwitchAvailabilityStabilityTimeThreshold(); - mAutoDataSwitchValidationMaxRetry = - dataConfig.getAutoDataSwitchValidationMaxRetry(); - } - private synchronized void onMultiSimConfigChanged(int activeModemCount) { // No change. if (mActiveModemCount == activeModemCount) return; @@ -958,13 +904,13 @@ public class PhoneSwitcher extends Handler { }); phone.getDataSettingsManager().registerCallback( mDataSettingsManagerCallbacks.get(phone.getPhoneId())); - phone.getServiceStateTracker().registerForServiceStateChanged(this, - EVENT_SERVICE_STATE_CHANGED, phoneId); Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>(); mCurrentDdsSwitchFailure.add(ddsFailure); registerForImsRadioTechChange(mContext, phoneId); } + + mAutoDataSwitchController.onMultiSimConfigChanged(activeModemCount); } /** @@ -973,14 +919,14 @@ public class PhoneSwitcher extends Handler { * 2. OR user changed auto data switch feature */ private void onDataEnabledChanged() { - logl("user changed data related settings"); if (isAnyVoiceCallActiveOnDevice()) { // user changed data related settings during call, switch or turn off immediately evaluateIfImmediateDataSwitchIsNeeded( "user changed data settings during call", DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); } else { - evaluateIfAutoSwitchIsNeeded(); + mAutoDataSwitchController.evaluateAutoDataSwitch(AutoDataSwitchController + .EVALUATION_REASON_DATA_SETTINGS_CHANGED); } } @@ -1069,134 +1015,9 @@ public class PhoneSwitcher extends Handler { } /** - * Called when service state changed. - */ - private void onServiceStateChanged(int phoneId) { - Phone phone = findPhoneById(phoneId); - if (phone != null) { - int newRegState = phone.getServiceState() - .getNetworkRegistrationInfo( - NetworkRegistrationInfo.DOMAIN_PS, - AccessNetworkConstants.TRANSPORT_TYPE_WWAN) - .getRegistrationState(); - if (newRegState != mPhoneStates[phoneId].dataRegState) { - mPhoneStates[phoneId].dataRegState = newRegState; - logl("onServiceStateChanged: phoneId:" + phoneId + " dataReg-> " - + NetworkRegistrationInfo.registrationStateToString(newRegState)); - if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) { - sendEmptyMessage(EVENT_EVALUATE_AUTO_SWITCH); - } - } - } - } - - /** - * Evaluate if auto switch is suitable at the moment. - */ - private void evaluateIfAutoSwitchIsNeeded() { - // auto data switch feature is disabled from server - if (mAutoDataSwitchAvailabilityStabilityTimeThreshold < 0) return; - // check is valid DSDS - if (!isActiveSubId(mPrimaryDataSubId) || mSubscriptionManagerService - .getActiveSubIdList(true).length <= 1) { - return; - } - - Phone primaryDataPhone = getPhoneBySubId(mPrimaryDataSubId); - if (primaryDataPhone == null) { - loge("evaluateIfAutoSwitchIsNeeded: cannot find primary data phone. subId=" - + mPrimaryDataSubId); - return; - } - - int primaryPhoneId = primaryDataPhone.getPhoneId(); - log("evaluateIfAutoSwitchIsNeeded: primaryPhoneId: " + primaryPhoneId - + " preferredPhoneId: " + mPreferredDataPhoneId); - Phone secondaryDataPhone; - - if (mPreferredDataPhoneId == primaryPhoneId) { - // on primary data sub - - int candidateSubId = getAutoSwitchTargetSubIdIfExists(); - if (candidateSubId != INVALID_SUBSCRIPTION_ID) { - startAutoDataSwitchStabilityCheck(candidateSubId, mRequirePingTestBeforeDataSwitch); - } else { - cancelPendingAutoDataSwitch(); - } - } else if ((secondaryDataPhone = findPhoneById(mPreferredDataPhoneId)) != null) { - // on secondary data sub - - if (!primaryDataPhone.isUserDataEnabled() - || !secondaryDataPhone.isDataAllowed()) { - // immediately switch back if user setting changes - mAutoSelectedDataSubId = DEFAULT_SUBSCRIPTION_ID; - evaluateIfImmediateDataSwitchIsNeeded("User disabled data settings", - DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); - return; - } - - NetworkCapabilities defaultNetworkCapabilities = mConnectivityManager - .getNetworkCapabilities(mConnectivityManager.getActiveNetwork()); - if (defaultNetworkCapabilities != null && !defaultNetworkCapabilities - .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - log("evaluateIfAutoSwitchIsNeeded: " - + "Default network is active on non-cellular transport"); - startAutoDataSwitchStabilityCheck(DEFAULT_SUBSCRIPTION_ID, false); - return; - } - - if (mPhoneStates[secondaryDataPhone.getPhoneId()].dataRegState - != NetworkRegistrationInfo.REGISTRATION_STATE_HOME) { - // secondary phone lost its HOME availability - startAutoDataSwitchStabilityCheck(DEFAULT_SUBSCRIPTION_ID, false); - return; - } - - if (isInService(mPhoneStates[primaryPhoneId])) { - // primary becomes available - startAutoDataSwitchStabilityCheck(DEFAULT_SUBSCRIPTION_ID, - mRequirePingTestBeforeDataSwitch); - return; - } - - // cancel any previous attempts of switching back to primary - cancelPendingAutoDataSwitch(); - } - } - - /** - * @param phoneState The phone state to check - * @return {@code true} if the phone state is considered in service. - */ - private boolean isInService(@NonNull PhoneState phoneState) { - return phoneState.dataRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME - || phoneState.dataRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING; - } - - /** - * Called when the current environment suits auto data switch. - * Start pre-switch validation if the current environment suits auto data switch for - * {@link #mAutoDataSwitchAvailabilityStabilityTimeThreshold} MS. - * @param targetSubId the target sub Id. - * @param needValidation {@code true} if validation is needed. - */ - private void startAutoDataSwitchStabilityCheck(int targetSubId, boolean needValidation) { - log("startAutoDataSwitchStabilityCheck: targetSubId=" + targetSubId - + " needValidation=" + needValidation); - if (!hasMessages(EVENT_MEETS_AUTO_DATA_SWITCH_STATE, needValidation)) { - sendMessageDelayed(obtainMessage(EVENT_MEETS_AUTO_DATA_SWITCH_STATE, targetSubId, - 0/*placeholder*/, - needValidation), - mAutoDataSwitchAvailabilityStabilityTimeThreshold); - } - } - - /** * Cancel any auto switch attempts when the current environment is not suitable for auto switch. */ - private void cancelPendingAutoDataSwitch() { - mAutoSwitchRetryFailedCount = 0; - removeMessages(EVENT_MEETS_AUTO_DATA_SWITCH_STATE); + private void cancelPendingAutoDataSwitchValidation() { if (mValidator.isValidating()) { mValidator.stopValidation(); @@ -1207,56 +1028,6 @@ public class PhoneSwitcher extends Handler { } } - /** - * Called when consider switching from primary default data sub to another data sub. - * @return the target subId if a suitable candidate is found, otherwise return - * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} - */ - private int getAutoSwitchTargetSubIdIfExists() { - Phone primaryDataPhone = getPhoneBySubId(mPrimaryDataSubId); - if (primaryDataPhone == null) { - log("getAutoSwitchTargetSubId: no sim loaded"); - return INVALID_SUBSCRIPTION_ID; - } - - int primaryPhoneId = primaryDataPhone.getPhoneId(); - - if (!primaryDataPhone.isUserDataEnabled()) { - log("getAutoSwitchTargetSubId: user disabled data"); - return INVALID_SUBSCRIPTION_ID; - } - - NetworkCapabilities defaultNetworkCapabilities = mConnectivityManager - .getNetworkCapabilities(mConnectivityManager.getActiveNetwork()); - if (defaultNetworkCapabilities != null && !defaultNetworkCapabilities - .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - // Exists other active default transport - log("getAutoSwitchTargetSubId: Default network is active on non-cellular transport"); - return INVALID_SUBSCRIPTION_ID; - } - - // check whether primary and secondary signal status worth switching - if (isInService(mPhoneStates[primaryPhoneId])) { - log("getAutoSwitchTargetSubId: primary is in service"); - return INVALID_SUBSCRIPTION_ID; - } - for (int phoneId = 0; phoneId < mPhoneStates.length; phoneId++) { - if (phoneId != primaryPhoneId) { - // the alternative phone must have HOME availability - if (mPhoneStates[phoneId].dataRegState - == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) { - log("getAutoSwitchTargetSubId: found phone " + phoneId + " in HOME service"); - Phone secondaryDataPhone = findPhoneById(phoneId); - if (secondaryDataPhone != null && // check auto switch feature enabled - secondaryDataPhone.isDataAllowed()) { - return secondaryDataPhone.getSubId(); - } - } - } - } - return INVALID_SUBSCRIPTION_ID; - } - private TelephonyManager getTm() { return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); } @@ -1415,8 +1186,6 @@ public class PhoneSwitcher extends Handler { protected static class PhoneState { public volatile boolean active = false; - public @NetworkRegistrationInfo.RegistrationState int dataRegState = - NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; public long lastRequested = 0; } @@ -1836,14 +1605,12 @@ public class PhoneSwitcher extends Handler { if (!isActiveSubId(subId)) { logl("confirmSwitch: subId " + subId + " is no longer active"); resultForCallBack = SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION; - mAutoSwitchRetryFailedCount = 0; } else if (!confirm) { resultForCallBack = SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; // retry for auto data switch validation failure if (mLastSwitchPreferredDataReason == DataSwitch.Reason.DATA_SWITCH_REASON_AUTO) { - scheduleAutoSwitchRetryEvaluation(); - mAutoSwitchRetryFailedCount++; + mAutoDataSwitchController.evaluateRetryOnValidationFailed(); } } else { if (subId == mPrimaryDataSubId) { @@ -1852,7 +1619,7 @@ public class PhoneSwitcher extends Handler { setAutoSelectedDataSubIdInternal(subId); } resultForCallBack = SET_OPPORTUNISTIC_SUB_SUCCESS; - mAutoSwitchRetryFailedCount = 0; + mAutoDataSwitchController.resetFailedCount(); } // Trigger callback if needed @@ -1861,23 +1628,6 @@ public class PhoneSwitcher extends Handler { mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; } - /** - * Schedule auto data switch evaluation retry if haven't reached the max retry count. - */ - private void scheduleAutoSwitchRetryEvaluation() { - if (mAutoSwitchRetryFailedCount < mAutoDataSwitchValidationMaxRetry) { - if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) { - sendMessageDelayed(obtainMessage(EVENT_EVALUATE_AUTO_SWITCH), - mAutoDataSwitchAvailabilityStabilityTimeThreshold - << mAutoSwitchRetryFailedCount); - } - } else { - logl("scheduleAutoSwitchEvaluation: reached max auto switch retry count " - + mAutoDataSwitchValidationMaxRetry); - mAutoSwitchRetryFailedCount = 0; - } - } - private void onNetworkAvailable(int subId, Network network) { log("onNetworkAvailable: on subId " + subId); // Do nothing unless pending switch matches target subId and it doesn't require @@ -1928,8 +1678,14 @@ public class PhoneSwitcher extends Handler { } // A phone in voice call might trigger data being switched to it. + // Exclude dialing to give modem time to process an EMC first before dealing with DDS switch + // Include alerting because modem RLF leads to delay in switch, so carrier required to + // switch in alerting phase. + // TODO: check ringing call for vDADA return (!phone.getBackgroundCall().isIdle() - || !phone.getForegroundCall().isIdle()); + && phone.getBackgroundCall().getState() != Call.State.DIALING) + || (!phone.getForegroundCall().isIdle() + && phone.getForegroundCall().getState() != Call.State.DIALING); } private void updateHalCommandToUse() { @@ -2062,8 +1818,7 @@ public class PhoneSwitcher extends Handler { for (int i = 0; i < mActiveModemCount; i++) { PhoneState ps = mPhoneStates[i]; c.setTimeInMillis(ps.lastRequested); - pw.println("PhoneId(" + i + ") active=" + ps.active + ", dataRegState=" - + NetworkRegistrationInfo.registrationStateToString(ps.dataRegState) + pw.println("PhoneId(" + i + ") active=" + ps.active + ", lastRequest=" + (ps.lastRequested == 0 ? "never" : String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c))); @@ -2081,10 +1836,6 @@ public class PhoneSwitcher extends Handler { pw.println("mActiveModemCount=" + mActiveModemCount); pw.println("mPhoneIdInVoiceCall=" + mPhoneIdInVoiceCall); pw.println("mCurrentDdsSwitchFailure=" + mCurrentDdsSwitchFailure); - pw.println("mAutoDataSwitchAvailabilityStabilityTimeThreshold=" - + mAutoDataSwitchAvailabilityStabilityTimeThreshold); - pw.println("mAutoDataSwitchValidationMaxRetry=" + mAutoDataSwitchValidationMaxRetry); - pw.println("mRequirePingTestBeforeDataSwitch=" + mRequirePingTestBeforeDataSwitch); pw.println("mLastSwitchPreferredDataReason=" + switchReasonToString(mLastSwitchPreferredDataReason)); pw.println("mDisplayedAutoSwitchNotification=" + mDisplayedAutoSwitchNotification); @@ -2092,6 +1843,7 @@ public class PhoneSwitcher extends Handler { pw.increaseIndent(); mLocalLog.dump(fd, pw, args); pw.decreaseIndent(); + mAutoDataSwitchController.dump(fd, pw, args); pw.decreaseIndent(); } @@ -2130,72 +1882,15 @@ public class PhoneSwitcher extends Handler { phoneId), MODEM_COMMAND_RETRY_PERIOD_MS); return; } - if (commandSuccess) logl("onDdsSwitchResponse: DDS switch success on phoneId = " + phoneId); + if (commandSuccess) { + logl("onDdsSwitchResponse: DDS switch success on phoneId = " + phoneId); + mAutoDataSwitchController.displayAutoDataSwitchNotification(phoneId, + mLastSwitchPreferredDataReason == DataSwitch.Reason.DATA_SWITCH_REASON_AUTO); + } mCurrentDdsSwitchFailure.get(phoneId).clear(); // Notify all registrants mActivePhoneRegistrants.notifyRegistrants(); notifyPreferredDataSubIdChanged(); - displayAutoDataSwitchNotification(); - } - - /** - * Display a notification the first time auto data switch occurs. - */ - private void displayAutoDataSwitchNotification() { - NotificationManager notificationManager = (NotificationManager) - mContext.getSystemService(Context.NOTIFICATION_SERVICE); - - if (mDisplayedAutoSwitchNotification) { - // cancel posted notification if any exist - log("displayAutoDataSwitchNotification: canceling any notifications for subId " - + mAutoSelectedDataSubId); - notificationManager.cancel(AUTO_DATA_SWITCH_NOTIFICATION_TAG, - AUTO_DATA_SWITCH_NOTIFICATION_ID); - return; - } - // proceed only the first time auto data switch occurs, which includes data during call - if (mLastSwitchPreferredDataReason != DataSwitch.Reason.DATA_SWITCH_REASON_AUTO) { - log("displayAutoDataSwitchNotification: Ignore DDS switch due to " - + switchReasonToString(mLastSwitchPreferredDataReason)); - return; - } - SubscriptionInfo subInfo = mSubscriptionManagerService - .getSubscriptionInfo(mAutoSelectedDataSubId); - if (subInfo == null || subInfo.isOpportunistic()) { - loge("displayAutoDataSwitchNotification: mAutoSelectedDataSubId=" - + mAutoSelectedDataSubId + " unexpected subInfo " + subInfo); - return; - } - logl("displayAutoDataSwitchNotification: display for subId=" + mAutoSelectedDataSubId); - // "Mobile network settings" screen / dialog - Intent intent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS); - final Bundle fragmentArgs = new Bundle(); - // Special contract for Settings to highlight permission row - fragmentArgs.putString(SETTINGS_EXTRA_FRAGMENT_ARG_KEY, AUTO_DATA_SWITCH_SETTING_R_ID); - intent.putExtra(Settings.EXTRA_SUB_ID, mAutoSelectedDataSubId); - intent.putExtra(SETTINGS_EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs); - PendingIntent contentIntent = PendingIntent.getActivity( - mContext, mAutoSelectedDataSubId, intent, PendingIntent.FLAG_IMMUTABLE); - - CharSequence activeCarrierName = subInfo.getDisplayName(); - CharSequence contentTitle = mContext.getString( - com.android.internal.R.string.auto_data_switch_title, activeCarrierName); - CharSequence contentText = mContext.getText( - com.android.internal.R.string.auto_data_switch_content); - - final Notification notif = new Notification.Builder(mContext) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setSmallIcon(android.R.drawable.stat_sys_warning) - .setColor(mContext.getResources().getColor( - com.android.internal.R.color.system_notification_accent_color)) - .setChannelId(NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS) - .setContentIntent(contentIntent) - .setStyle(new Notification.BigTextStyle().bigText(contentText)) - .build(); - notificationManager.notify(AUTO_DATA_SWITCH_NOTIFICATION_TAG, - AUTO_DATA_SWITCH_NOTIFICATION_ID, notif); - mDisplayedAutoSwitchNotification = true; } private boolean isPhoneIdValidForRetry(int phoneId) { |