1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.data; 18 19 import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG; 20 import static android.telephony.SubscriptionManager.DEFAULT_PHONE_INDEX; 21 import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 22 import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX; 23 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; 24 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION; 25 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS; 26 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; 27 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM; 28 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; 29 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE; 30 31 import static java.util.Arrays.copyOf; 32 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.content.BroadcastReceiver; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.net.ConnectivityManager; 40 import android.net.MatchAllNetworkSpecifier; 41 import android.net.Network; 42 import android.net.NetworkCapabilities; 43 import android.net.NetworkFactory; 44 import android.net.NetworkRequest; 45 import android.net.NetworkSpecifier; 46 import android.net.TelephonyNetworkSpecifier; 47 import android.os.AsyncResult; 48 import android.os.Handler; 49 import android.os.Looper; 50 import android.os.Message; 51 import android.os.PersistableBundle; 52 import android.os.Registrant; 53 import android.os.RegistrantList; 54 import android.os.RemoteException; 55 import android.telephony.CarrierConfigManager; 56 import android.telephony.PhoneStateListener; 57 import android.telephony.SubscriptionInfo; 58 import android.telephony.SubscriptionManager; 59 import android.telephony.TelephonyManager; 60 import android.telephony.TelephonyRegistryManager; 61 import android.telephony.ims.ImsReasonInfo; 62 import android.telephony.ims.ImsRegistrationAttributes; 63 import android.telephony.ims.RegistrationManager; 64 import android.telephony.ims.stub.ImsRegistrationImplBase; 65 import android.util.ArrayMap; 66 import android.util.LocalLog; 67 import android.util.Log; 68 import android.util.SparseIntArray; 69 70 import com.android.ims.ImsException; 71 import com.android.ims.ImsManager; 72 import com.android.internal.annotations.VisibleForTesting; 73 import com.android.internal.telephony.Call; 74 import com.android.internal.telephony.CommandException; 75 import com.android.internal.telephony.ISetOpportunisticDataCallback; 76 import com.android.internal.telephony.IccCard; 77 import com.android.internal.telephony.Phone; 78 import com.android.internal.telephony.PhoneConfigurationManager; 79 import com.android.internal.telephony.PhoneFactory; 80 import com.android.internal.telephony.RadioConfig; 81 import com.android.internal.telephony.TelephonyIntents; 82 import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList; 83 import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback; 84 import com.android.internal.telephony.flags.FeatureFlags; 85 import com.android.internal.telephony.imsphone.ImsPhone; 86 import com.android.internal.telephony.metrics.TelephonyMetrics; 87 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent; 88 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch; 89 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch; 90 import com.android.internal.telephony.subscription.SubscriptionInfoInternal; 91 import com.android.internal.telephony.subscription.SubscriptionManagerService; 92 import com.android.internal.telephony.subscription.SubscriptionManagerService.WatchedInt; 93 import com.android.internal.util.IndentingPrintWriter; 94 import com.android.telephony.Rlog; 95 96 import java.io.FileDescriptor; 97 import java.io.PrintWriter; 98 import java.util.ArrayList; 99 import java.util.Calendar; 100 import java.util.HashSet; 101 import java.util.List; 102 import java.util.Map; 103 import java.util.Set; 104 import java.util.concurrent.CompletableFuture; 105 import java.util.concurrent.Executor; 106 107 /** 108 * Utility singleton to monitor subscription changes and incoming NetworkRequests 109 * and determine which phone/phones are active. 110 * <p> 111 * Manages the ALLOW_DATA calls to modems and notifies phones about changes to 112 * the active phones. Note we don't wait for data attach (which may not happen anyway). 113 */ 114 public class PhoneSwitcher extends Handler { 115 private static final String LOG_TAG = "PhoneSwitcher"; 116 protected static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE); 117 118 private static final int MODEM_COMMAND_RETRY_PERIOD_MS = 5000; 119 // After the emergency call ends, wait for a few seconds to see if we enter ECBM before starting 120 // the countdown to remove the emergency DDS override. 121 @VisibleForTesting 122 // not final for testing. 123 public static int ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 5000; 124 // Wait for a few seconds after the override request comes in to receive the outgoing call 125 // event. If it does not happen before the timeout specified, cancel the override. 126 @VisibleForTesting 127 public static int DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 5000; 128 129 // If there are no subscriptions in a device, then the phone to be used for emergency should 130 // always be the "first" phone. 131 private static final int DEFAULT_EMERGENCY_PHONE_ID = 0; 132 133 /** 134 * Container for an ongoing request to override the DDS in the context of an ongoing emergency 135 * call to allow for carrier specific operations, such as provide SUPL updates during or after 136 * the emergency call, since some modems do not support these operations on the non DDS. 137 */ 138 private static final class EmergencyOverrideRequest { 139 /* The Phone ID that the DDS should be set to. */ 140 int mPhoneId = INVALID_PHONE_INDEX; 141 /* The time after the emergency call ends that the DDS should be overridden for. */ 142 int mGnssOverrideTimeMs = -1; 143 /* A callback to the requester notifying them if the initial call to the modem to override 144 * the DDS was successful. 145 */ 146 CompletableFuture<Boolean> mOverrideCompleteFuture; 147 /* In the special case that the device goes into emergency callback mode after the emergency 148 * call ends, keep the override until ECM finishes and then start the mGnssOverrideTimeMs 149 * timer to leave DDS override. 150 */ 151 boolean mRequiresEcmFinish = false; 152 153 /* 154 * Keeps track of whether or not this request has already serviced the outgoing emergency 155 * call. Once finished, do not delay for any other calls. 156 */ 157 boolean mPendingOriginatingCall = true; 158 159 /** 160 * @return true if there is a pending override complete callback. 161 */ isCallbackAvailable()162 boolean isCallbackAvailable() { 163 return mOverrideCompleteFuture != null; 164 } 165 166 /** 167 * Send the override complete callback the result of setting the DDS to the new value. 168 */ sendOverrideCompleteCallbackResultAndClear(boolean result)169 void sendOverrideCompleteCallbackResultAndClear(boolean result) { 170 if (isCallbackAvailable()) { 171 mOverrideCompleteFuture.complete(result); 172 mOverrideCompleteFuture = null; 173 } 174 } 175 176 177 @Override toString()178 public String toString() { 179 return String.format("EmergencyOverrideRequest: [phoneId= %d, overrideMs= %d," 180 + " hasCallback= %b, ecmFinishStatus= %b]", mPhoneId, mGnssOverrideTimeMs, 181 isCallbackAvailable(), mRequiresEcmFinish); 182 } 183 } 184 185 @NonNull 186 private final NetworkRequestList mNetworkRequestList = new NetworkRequestList(); 187 protected final RegistrantList mActivePhoneRegistrants; 188 private final SubscriptionManagerService mSubscriptionManagerService; 189 @NonNull 190 private final FeatureFlags mFlags; 191 protected final Context mContext; 192 private final LocalLog mLocalLog; 193 protected PhoneState[] mPhoneStates; 194 protected int[] mPhoneSubscriptions; 195 private boolean mIsRegisteredForImsRadioTechChange; 196 @VisibleForTesting 197 protected final CellularNetworkValidator mValidator; 198 private int mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 199 /** The reason for the last time changing preferred data sub **/ 200 private int mLastSwitchPreferredDataReason = -1; 201 private boolean mPendingSwitchNeedValidation; 202 @VisibleForTesting 203 public final CellularNetworkValidator.ValidationCallback mValidationCallback = 204 new CellularNetworkValidator.ValidationCallback() { 205 @Override 206 public void onValidationDone(boolean validated, int subId) { 207 Message.obtain(PhoneSwitcher.this, 208 EVENT_NETWORK_VALIDATION_DONE, subId, validated ? 1 : 0).sendToTarget(); 209 } 210 211 @Override 212 public void onNetworkAvailable(Network network, int subId) { 213 Message.obtain(PhoneSwitcher.this, 214 EVENT_NETWORK_AVAILABLE, subId, 0, network).sendToTarget(); 215 216 } 217 }; 218 219 // How many phones (correspondingly logical modems) are allowed for PS attach. This is used 220 // when we specifically use setDataAllowed to initiate on-demand PS(data) attach for each phone. 221 protected int mMaxDataAttachModemCount; 222 // Local cache of TelephonyManager#getActiveModemCount(). 1 if in single SIM mode, 2 if in dual 223 // SIM mode. 224 protected int mActiveModemCount; 225 protected static PhoneSwitcher sPhoneSwitcher = null; 226 227 // Which primary (non-opportunistic) subscription is set as data subscription among all primary 228 // subscriptions. This value usually comes from user setting, and it's the subscription used for 229 // Internet data if mOpptDataSubId is not set. 230 protected int mPrimaryDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 231 232 // The automatically suggested preferred data subId (by e.g. CBRS or auto data switch), a 233 // candidate for preferred data subId, which is eventually presided by 234 // updatePreferredDataPhoneId(). 235 // If CBRS/auto switch feature selects the primary data subId as the preferred data subId, 236 // its value will be DEFAULT_SUBSCRIPTION_ID. 237 private int mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 238 239 // The phone ID that has an active voice call. If set, and its mobile data setting is on, 240 // it will become the mPreferredDataPhoneId. 241 protected int mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX; 242 243 @VisibleForTesting 244 // It decides: 245 // 1. In modem layer, which modem is DDS (preferred to have data traffic on) 246 // 2. In TelephonyNetworkFactory, which subscription will apply default network requests, which 247 // are requests without specifying a subId. 248 // Corresponding phoneId after considering mOpptDataSubId, mPrimaryDataSubId and 249 // mPhoneIdInVoiceCall above. 250 protected int mPreferredDataPhoneId = SubscriptionManager.INVALID_PHONE_INDEX; 251 252 // Subscription ID corresponds to mPreferredDataPhoneId. 253 protected WatchedInt mPreferredDataSubId = new WatchedInt( 254 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 255 256 // If non-null, An emergency call is about to be started, is ongoing, or has just ended and we 257 // are overriding the DDS. 258 // Internal state, should ONLY be accessed/modified inside of the handler. 259 private EmergencyOverrideRequest mEmergencyOverride; 260 261 private ISetOpportunisticDataCallback mSetOpptSubCallback; 262 263 private static final int EVENT_PRIMARY_DATA_SUB_CHANGED = 101; 264 protected static final int EVENT_SUBSCRIPTION_CHANGED = 102; 265 private static final int EVENT_REQUEST_NETWORK = 103; 266 private static final int EVENT_RELEASE_NETWORK = 104; 267 // ECBM has started/ended. If we just ended an emergency call and mEmergencyOverride is not 268 // null, we will wait for EVENT_EMERGENCY_TOGGLE again with ECBM ending to send the message 269 // EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE to remove the override after the mEmergencyOverride 270 // override timer ends. 271 private static final int EVENT_EMERGENCY_TOGGLE = 105; 272 private static final int EVENT_RADIO_CAPABILITY_CHANGED = 106; 273 private static final int EVENT_OPPT_DATA_SUB_CHANGED = 107; 274 private static final int EVENT_RADIO_ON = 108; 275 // A call has either started or ended. If an emergency ended and DDS is overridden using 276 // mEmergencyOverride, start the countdown to remove the override using the message 277 // EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE. The only exception to this is if the device moves to 278 // ECBM, which is detected by EVENT_EMERGENCY_TOGGLE. 279 private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 109; 280 private static final int EVENT_NETWORK_VALIDATION_DONE = 110; 281 282 private static final int EVENT_MODEM_COMMAND_DONE = 112; 283 private static final int EVENT_MODEM_COMMAND_RETRY = 113; 284 285 // An emergency call is about to be originated and requires the DDS to be overridden. 286 // Uses EVENT_PRECISE_CALL_STATE_CHANGED message to start countdown to finish override defined 287 // in mEmergencyOverride. If EVENT_PRECISE_CALL_STATE_CHANGED does not come in 288 // DEFAULT_DATA_OVERRIDE_TIMEOUT_MS milliseconds, then the override will be removed. 289 private static final int EVENT_OVERRIDE_DDS_FOR_EMERGENCY = 115; 290 // If it exists, remove the current mEmergencyOverride DDS override. 291 private static final int EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE = 116; 292 // If it exists, remove the current mEmergencyOverride DDS override. 293 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 117; 294 private static final int EVENT_NETWORK_AVAILABLE = 118; 295 private static final int EVENT_PROCESS_SIM_STATE_CHANGE = 119; 296 private static final int EVENT_IMS_RADIO_TECH_CHANGED = 120; 297 298 // List of events triggers re-evaluations 299 private static final String EVALUATION_REASON_RADIO_ON = "EVENT_RADIO_ON"; 300 301 // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's 302 // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse 303 // will be either HAL_COMMAND_ALLOW_DATA or HAL_COMMAND_ALLOW_DATA or HAL_COMMAND_UNKNOWN. 304 protected static final int HAL_COMMAND_UNKNOWN = 0; 305 protected static final int HAL_COMMAND_ALLOW_DATA = 1; 306 protected static final int HAL_COMMAND_PREFERRED_DATA = 2; 307 protected int mHalCommandToUse = HAL_COMMAND_UNKNOWN; 308 309 protected RadioConfig mRadioConfig; 310 311 private static final int MAX_LOCAL_LOG_LINES = 256; 312 313 // Default timeout value of network validation in millisecond. 314 private static final int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000; 315 316 /** Controller that tracks {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH} */ 317 @NonNull private final AutoDataSwitchController mAutoDataSwitchController; 318 /** Callback to deal with requests made by the auto data switch controller. */ 319 @NonNull private final AutoDataSwitchController.AutoDataSwitchControllerCallback 320 mAutoDataSwitchCallback; 321 322 private final ConnectivityManager mConnectivityManager; 323 private int mImsRegistrationTech = REGISTRATION_TECH_NONE; 324 @VisibleForTesting 325 public final SparseIntArray mImsRegistrationRadioTechMap = new SparseIntArray(); 326 @NonNull 327 private final List<Set<CommandException.Error>> mCurrentDdsSwitchFailure; 328 329 /** Data settings manager callback. Key is the phone id. */ 330 @NonNull 331 private final Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks = 332 new ArrayMap<>(); 333 334 private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback { 335 public int mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 336 public int mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; 337 @Override onCapabilitiesChanged(@onNull Network network, NetworkCapabilities networkCapabilities)338 public void onCapabilitiesChanged(@NonNull Network network, 339 NetworkCapabilities networkCapabilities) { 340 if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 341 if (SubscriptionManager.isValidSubscriptionId(mExpectedSubId) 342 && mExpectedSubId == getSubIdFromNetworkSpecifier( 343 networkCapabilities.getNetworkSpecifier())) { 344 logDataSwitchEvent( 345 mExpectedSubId, 346 TelephonyEvent.EventState.EVENT_STATE_END, 347 mSwitchReason); 348 mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 349 mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; 350 } 351 } 352 mAutoDataSwitchController.updateDefaultNetworkCapabilities(networkCapabilities); 353 } 354 355 @Override onLost(@onNull Network network)356 public void onLost(@NonNull Network network) { 357 mAutoDataSwitchController.updateDefaultNetworkCapabilities(null); 358 } 359 } 360 361 private final RegistrationManager.RegistrationCallback mRegistrationCallback = 362 new RegistrationManager.RegistrationCallback() { 363 @Override 364 public void onRegistered(@NonNull ImsRegistrationAttributes attributes) { 365 int imsRegistrationTech = attributes.getRegistrationTechnology(); 366 if (imsRegistrationTech != mImsRegistrationTech) { 367 mImsRegistrationTech = imsRegistrationTech; 368 sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); 369 } 370 } 371 372 @Override 373 public void onUnregistered(@NonNull ImsReasonInfo info) { 374 if (mImsRegistrationTech != REGISTRATION_TECH_NONE) { 375 mImsRegistrationTech = REGISTRATION_TECH_NONE; 376 sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED)); 377 } 378 } 379 }; 380 381 private final DefaultNetworkCallback mDefaultNetworkCallback = new DefaultNetworkCallback(); 382 383 /** 384 * Interface to get ImsRegistrationTech. It's a wrapper of ImsManager#getRegistrationTech, 385 * to make it mock-able in unittests. 386 */ 387 public interface ImsRegTechProvider { 388 /** Get IMS registration tech. */ get(Context context, int phoneId)389 @ImsRegistrationImplBase.ImsRegistrationTech int get(Context context, int phoneId); 390 } 391 392 @VisibleForTesting 393 public ImsRegTechProvider mImsRegTechProvider = 394 (context, phoneId) -> ImsManager.getInstance(context, phoneId).getRegistrationTech(); 395 396 /** 397 * Interface to register RegistrationCallback. It's a wrapper of 398 * ImsManager#addRegistrationCallback, to make it mock-able in unittests. 399 */ 400 public interface ImsRegisterCallback { 401 /** Set RegistrationCallback. */ setCallback(Context context, int phoneId, RegistrationManager.RegistrationCallback cb, Executor executor)402 void setCallback(Context context, int phoneId, RegistrationManager.RegistrationCallback cb, 403 Executor executor) throws ImsException; 404 } 405 406 @VisibleForTesting 407 public ImsRegisterCallback mImsRegisterCallback = 408 (context, phoneId, cb, executor)-> ImsManager.getInstance(context, phoneId) 409 .addRegistrationCallback(cb, executor); 410 411 /** 412 * Method to get singleton instance. 413 */ getInstance()414 public static PhoneSwitcher getInstance() { 415 return sPhoneSwitcher; 416 } 417 418 /** 419 * Method to create singleton instance. 420 */ make(int maxDataAttachModemCount, Context context, Looper looper, @NonNull FeatureFlags flags)421 public static PhoneSwitcher make(int maxDataAttachModemCount, Context context, Looper looper, 422 @NonNull FeatureFlags flags) { 423 if (sPhoneSwitcher == null) { 424 sPhoneSwitcher = new PhoneSwitcher(maxDataAttachModemCount, context, looper, flags); 425 } 426 427 return sPhoneSwitcher; 428 } 429 updatesIfPhoneInVoiceCallChanged()430 private boolean updatesIfPhoneInVoiceCallChanged() { 431 int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall; 432 // If there's no active call, the value will become INVALID_PHONE_INDEX 433 // and internet data will be switched back to system selected or user selected 434 // subscription. 435 mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX; 436 for (Phone phone : PhoneFactory.getPhones()) { 437 if (isPhoneInVoiceCall(phone) || isPhoneInVoiceCall(phone.getImsPhone())) { 438 mPhoneIdInVoiceCall = phone.getPhoneId(); 439 break; 440 } 441 } 442 443 if (mPhoneIdInVoiceCall != oldPhoneIdInVoiceCall) { 444 logl("isPhoneInVoiceCallChanged from phoneId " + oldPhoneIdInVoiceCall 445 + " to phoneId " + mPhoneIdInVoiceCall); 446 return true; 447 } else { 448 return false; 449 } 450 } 451 registerForImsRadioTechChange(Context context, int phoneId)452 private void registerForImsRadioTechChange(Context context, int phoneId) { 453 try { 454 mImsRegisterCallback.setCallback(context, phoneId, mRegistrationCallback, this::post); 455 mIsRegisteredForImsRadioTechChange = true; 456 } catch (ImsException imsException) { 457 mIsRegisteredForImsRadioTechChange = false; 458 } 459 } 460 registerForImsRadioTechChange()461 private void registerForImsRadioTechChange() { 462 // register for radio tech change to listen to radio tech handover. 463 if (!mIsRegisteredForImsRadioTechChange) { 464 for (int i = 0; i < mActiveModemCount; i++) { 465 registerForImsRadioTechChange(mContext, i); 466 } 467 } 468 } 469 evaluateIfImmediateDataSwitchIsNeeded(String evaluationReason, int switchReason)470 private void evaluateIfImmediateDataSwitchIsNeeded(String evaluationReason, int switchReason) { 471 if (onEvaluate(REQUESTS_UNCHANGED, evaluationReason)) { 472 logDataSwitchEvent(mPreferredDataSubId.get(), 473 TelephonyEvent.EventState.EVENT_STATE_START, 474 switchReason); 475 registerDefaultNetworkChangeCallback(mPreferredDataSubId.get(), 476 switchReason); 477 } 478 } 479 480 @VisibleForTesting PhoneSwitcher(int maxActivePhones, Context context, Looper looper, @NonNull FeatureFlags featureFlags)481 public PhoneSwitcher(int maxActivePhones, Context context, Looper looper, 482 @NonNull FeatureFlags featureFlags) { 483 super(looper); 484 mContext = context; 485 mFlags = featureFlags; 486 mActiveModemCount = getTm().getActiveModemCount(); 487 mPhoneSubscriptions = new int[mActiveModemCount]; 488 mPhoneStates = new PhoneState[mActiveModemCount]; 489 mMaxDataAttachModemCount = maxActivePhones; 490 mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES); 491 492 mSubscriptionManagerService = SubscriptionManagerService.getInstance(); 493 494 mRadioConfig = RadioConfig.getInstance(); 495 mValidator = CellularNetworkValidator.getInstance(); 496 497 mCurrentDdsSwitchFailure = new ArrayList<>(); 498 IntentFilter filter = new IntentFilter(); 499 filter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); 500 mContext.registerReceiver(mSimStateIntentReceiver, filter); 501 502 mActivePhoneRegistrants = new RegistrantList(); 503 for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) { 504 mPhoneStates[phoneId] = new PhoneState(); 505 Phone phone = PhoneFactory.getPhone(phoneId); 506 if (phone != null) { 507 phone.registerForEmergencyCallToggle( 508 this, EVENT_EMERGENCY_TOGGLE, null); 509 // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone. 510 phone.registerForPreciseCallStateChanged( 511 this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 512 if (phone.getImsPhone() != null) { 513 phone.getImsPhone().registerForPreciseCallStateChanged( 514 this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 515 if (mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 516 // Initialize IMS registration tech 517 mImsRegistrationRadioTechMap.put(phoneId, REGISTRATION_TECH_NONE); 518 ((ImsPhone) phone.getImsPhone()).registerForImsRegistrationChanges( 519 this, EVENT_IMS_RADIO_TECH_CHANGED, null); 520 521 log("register handler to receive IMS registration : " + phoneId); 522 } 523 } 524 mDataSettingsManagerCallbacks.computeIfAbsent(phoneId, 525 v -> new DataSettingsManagerCallback(this::post) { 526 @Override 527 public void onDataEnabledChanged(boolean enabled, 528 @TelephonyManager.DataEnabledChangedReason int reason, 529 @NonNull String callingPackage) { 530 PhoneSwitcher.this.onDataEnabledChanged(); 531 } 532 @Override 533 public void onDataRoamingEnabledChanged(boolean enabled) { 534 PhoneSwitcher.this.mAutoDataSwitchController.evaluateAutoDataSwitch( 535 AutoDataSwitchController 536 .EVALUATION_REASON_DATA_SETTINGS_CHANGED); 537 }}); 538 phone.getDataSettingsManager().registerCallback( 539 mDataSettingsManagerCallbacks.get(phoneId)); 540 541 if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 542 registerForImsRadioTechChange(context, phoneId); 543 } 544 } 545 Set<CommandException.Error> ddsFailure = new HashSet<>(); 546 mCurrentDdsSwitchFailure.add(ddsFailure); 547 } 548 549 if (mActiveModemCount > 0) { 550 PhoneFactory.getPhone(0).mCi.registerForOn(this, EVENT_RADIO_ON, null); 551 } 552 553 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 554 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 555 telephonyRegistryManager.addOnSubscriptionsChangedListener( 556 mSubscriptionsChangedListener, this::post); 557 558 mConnectivityManager = 559 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 560 561 mAutoDataSwitchCallback = new AutoDataSwitchController.AutoDataSwitchControllerCallback() { 562 @Override 563 public void onRequireValidation(int targetPhoneId, boolean needValidation) { 564 int targetSubId = targetPhoneId == DEFAULT_PHONE_INDEX 565 ? DEFAULT_SUBSCRIPTION_ID 566 : mSubscriptionManagerService.getSubId(targetPhoneId); 567 PhoneSwitcher.this.validate(targetSubId, needValidation, 568 DataSwitch.Reason.DATA_SWITCH_REASON_AUTO, null); 569 } 570 571 @Override 572 public void onRequireImmediatelySwitchToPhone(int targetPhoneId, 573 @AutoDataSwitchController.AutoDataSwitchEvaluationReason int reason) { 574 PhoneSwitcher.this.mAutoSelectedDataSubId = 575 targetPhoneId == DEFAULT_PHONE_INDEX 576 ? DEFAULT_SUBSCRIPTION_ID 577 : mSubscriptionManagerService.getSubId(targetPhoneId); 578 PhoneSwitcher.this.evaluateIfImmediateDataSwitchIsNeeded( 579 AutoDataSwitchController.evaluationReasonToString(reason), 580 DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); 581 } 582 583 @Override 584 public void onRequireCancelAnyPendingAutoSwitchValidation() { 585 PhoneSwitcher.this.cancelPendingAutoDataSwitchValidation(); 586 } 587 }; 588 mAutoDataSwitchController = new AutoDataSwitchController(context, looper, this, 589 mFlags, mAutoDataSwitchCallback); 590 591 mContext.registerReceiver(mDefaultDataChangedReceiver, 592 new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)); 593 594 PhoneConfigurationManager.registerForMultiSimConfigChange( 595 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 596 597 mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this); 598 599 final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder() 600 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 601 .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS) 602 .addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL) 603 .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN) 604 .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA) 605 .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) 606 .addCapability(NetworkCapabilities.NET_CAPABILITY_CBS) 607 .addCapability(NetworkCapabilities.NET_CAPABILITY_IA) 608 .addCapability(NetworkCapabilities.NET_CAPABILITY_RCS) 609 .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL) 610 .addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP) 611 .addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE) 612 .addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS) 613 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 614 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 615 .addCapability(NetworkCapabilities.NET_CAPABILITY_MCX) 616 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY) 617 .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH) 618 .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1) 619 .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2) 620 .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3) 621 .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4) 622 .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5) 623 .setNetworkSpecifier(new MatchAllNetworkSpecifier()); 624 625 if (mFlags.satelliteInternet()) { 626 // TODO: b/328622096 remove the try/catch 627 try { 628 builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE); 629 } catch (IllegalArgumentException exception) { 630 loge("TRANSPORT_SATELLITE is not supported."); 631 } 632 } 633 634 NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context, 635 builder.build(), this); 636 // we want to see all requests 637 networkFactory.registerIgnoringScore(); 638 639 updateHalCommandToUse(); 640 641 logl("PhoneSwitcher started"); 642 } 643 644 private final BroadcastReceiver mDefaultDataChangedReceiver = new BroadcastReceiver() { 645 @Override 646 public void onReceive(Context context, Intent intent) { 647 Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PRIMARY_DATA_SUB_CHANGED); 648 msg.sendToTarget(); 649 } 650 }; 651 652 private final BroadcastReceiver mSimStateIntentReceiver = new BroadcastReceiver() { 653 @Override 654 public void onReceive(Context context, Intent intent) { 655 String action = intent.getAction(); 656 if (action.equals(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)) { 657 int state = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE, 658 TelephonyManager.SIM_STATE_UNKNOWN); 659 int slotIndex = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 660 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 661 logl("mSimStateIntentReceiver: slotIndex = " + slotIndex + " state = " + state); 662 obtainMessage(EVENT_PROCESS_SIM_STATE_CHANGE, slotIndex, state).sendToTarget(); 663 } 664 } 665 }; 666 isSimApplicationReady(int slotIndex)667 private boolean isSimApplicationReady(int slotIndex) { 668 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 669 return false; 670 } 671 672 SubscriptionInfo info = mSubscriptionManagerService 673 .getActiveSubscriptionInfoForSimSlotIndex(slotIndex, 674 mContext.getOpPackageName(), mContext.getAttributionTag()); 675 boolean uiccAppsEnabled = info != null && info.areUiccApplicationsEnabled(); 676 677 IccCard iccCard = PhoneFactory.getPhone(slotIndex).getIccCard(); 678 if (!iccCard.isEmptyProfile() && uiccAppsEnabled) { 679 logl("isSimApplicationReady: SIM is ready for slotIndex: " + slotIndex); 680 return true; 681 } else { 682 return false; 683 } 684 } 685 686 private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener = 687 new SubscriptionManager.OnSubscriptionsChangedListener() { 688 @Override 689 public void onSubscriptionsChanged() { 690 Message msg = PhoneSwitcher.this.obtainMessage(EVENT_SUBSCRIPTION_CHANGED); 691 msg.sendToTarget(); 692 } 693 }; 694 695 @Override handleMessage(Message msg)696 public void handleMessage(Message msg) { 697 switch (msg.what) { 698 case EVENT_SUBSCRIPTION_CHANGED: { 699 onEvaluate(REQUESTS_UNCHANGED, "subscription changed"); 700 break; 701 } 702 case EVENT_PRIMARY_DATA_SUB_CHANGED: { 703 evaluateIfImmediateDataSwitchIsNeeded("primary data sub changed", 704 DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); 705 break; 706 } 707 case EVENT_REQUEST_NETWORK: { 708 onRequestNetwork((NetworkRequest)msg.obj); 709 break; 710 } 711 case EVENT_RELEASE_NETWORK: { 712 onReleaseNetwork((NetworkRequest)msg.obj); 713 break; 714 } 715 case EVENT_EMERGENCY_TOGGLE: { 716 boolean isInEcm = isInEmergencyCallbackMode(); 717 if (mEmergencyOverride != null) { 718 logl("Emergency override - ecbm status = " + isInEcm); 719 if (isInEcm) { 720 // The device has gone into ECBM. Wait until it's out. 721 removeMessages(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 722 mEmergencyOverride.mRequiresEcmFinish = true; 723 } else if (mEmergencyOverride.mRequiresEcmFinish) { 724 // we have exited ECM! Start the timer to exit DDS override. 725 Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 726 sendMessageDelayed(msg2, mEmergencyOverride.mGnssOverrideTimeMs); 727 } 728 } 729 onEvaluate(REQUESTS_CHANGED, "emergencyToggle"); 730 break; 731 } 732 case EVENT_RADIO_CAPABILITY_CHANGED: { 733 final int phoneId = msg.arg1; 734 sendRilCommands(phoneId); 735 break; 736 } 737 case EVENT_OPPT_DATA_SUB_CHANGED: { 738 int subId = msg.arg1; 739 boolean needValidation = (msg.arg2 == 1); 740 ISetOpportunisticDataCallback callback = 741 (ISetOpportunisticDataCallback) msg.obj; 742 setOpportunisticDataSubscription(subId, needValidation, callback); 743 break; 744 } 745 case EVENT_RADIO_ON: { 746 updateHalCommandToUse(); 747 onEvaluate(REQUESTS_UNCHANGED, EVALUATION_REASON_RADIO_ON); 748 break; 749 } 750 case EVENT_IMS_RADIO_TECH_CHANGED: { 751 // register for radio tech change to listen to radio tech handover in case previous 752 // attempt was not successful 753 if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 754 registerForImsRadioTechChange(); 755 } else { 756 if (msg.obj == null) { 757 log("EVENT_IMS_RADIO_TECH_CHANGED but parameter is not available"); 758 break; 759 } 760 if (!onImsRadioTechChanged((AsyncResult) (msg.obj))) { 761 break; 762 } 763 } 764 765 // if voice call state changes or in voice call didn't change 766 // but RAT changes(e.g. Iwlan -> cross sim), reevaluate for data switch. 767 if (updatesIfPhoneInVoiceCallChanged() || isAnyVoiceCallActiveOnDevice()) { 768 evaluateIfImmediateDataSwitchIsNeeded("Ims radio tech changed", 769 DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); 770 } 771 break; 772 } 773 case EVENT_PRECISE_CALL_STATE_CHANGED: { 774 // register for radio tech change to listen to radio tech handover in case previous 775 // attempt was not successful 776 if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 777 registerForImsRadioTechChange(); 778 } 779 780 // If the phoneId in voice call didn't change, do nothing. 781 if (!updatesIfPhoneInVoiceCallChanged()) { 782 break; 783 } 784 785 if (!isAnyVoiceCallActiveOnDevice()) { 786 for (int i = 0; i < mActiveModemCount; i++) { 787 if (mCurrentDdsSwitchFailure.get(i).contains( 788 CommandException.Error.OP_NOT_ALLOWED_DURING_VOICE_CALL) 789 && isPhoneIdValidForRetry(i)) { 790 sendRilCommands(i); 791 } 792 } 793 } 794 795 // Only handle this event if we are currently waiting for the emergency call 796 // associated with the override request to start or end. 797 if (mEmergencyOverride != null && mEmergencyOverride.mPendingOriginatingCall) { 798 removeMessages(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 799 if (mPhoneIdInVoiceCall == SubscriptionManager.INVALID_PHONE_INDEX) { 800 // not in a call anymore. 801 Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 802 sendMessageDelayed(msg2, mEmergencyOverride.mGnssOverrideTimeMs 803 + ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS); 804 // Do not extend the emergency override by waiting for other calls to end. 805 // If it needs to be extended, a new request will come in and replace the 806 // current override. 807 mEmergencyOverride.mPendingOriginatingCall = false; 808 } 809 } 810 // Always update data modem via data during call code path, because 811 // mAutoSelectedDataSubId doesn't know about any data switch due to voice call 812 evaluateIfImmediateDataSwitchIsNeeded("precise call state changed", 813 DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); 814 if (!isAnyVoiceCallActiveOnDevice()) { 815 // consider auto switch on hang up all voice call 816 mAutoDataSwitchController.evaluateAutoDataSwitch( 817 AutoDataSwitchController.EVALUATION_REASON_VOICE_CALL_END); 818 } 819 break; 820 } 821 case EVENT_NETWORK_VALIDATION_DONE: { 822 int subId = msg.arg1; 823 boolean passed = (msg.arg2 == 1); 824 onValidationDone(subId, passed); 825 break; 826 } 827 case EVENT_NETWORK_AVAILABLE: { 828 int subId = msg.arg1; 829 Network network = (Network) msg.obj; 830 onNetworkAvailable(subId, network); 831 break; 832 } 833 case EVENT_MODEM_COMMAND_DONE: { 834 AsyncResult ar = (AsyncResult) msg.obj; 835 onDdsSwitchResponse(ar); 836 break; 837 } 838 case EVENT_MODEM_COMMAND_RETRY: { 839 int phoneId = (int) msg.obj; 840 if (mActiveModemCount <= phoneId) { 841 break; 842 } 843 if (isPhoneIdValidForRetry(phoneId)) { 844 logl("EVENT_MODEM_COMMAND_RETRY: resend modem command on phone " + phoneId); 845 sendRilCommands(phoneId); 846 } else { 847 logl("EVENT_MODEM_COMMAND_RETRY: skip retry as DDS sub changed"); 848 mCurrentDdsSwitchFailure.get(phoneId).clear(); 849 } 850 break; 851 } 852 case EVENT_OVERRIDE_DDS_FOR_EMERGENCY: { 853 EmergencyOverrideRequest req = (EmergencyOverrideRequest) msg.obj; 854 if (mEmergencyOverride != null) { 855 // If an override request comes in for a different phone ID than what is already 856 // being overridden, ignore. We should not try to switch DDS while already 857 // waiting for SUPL. 858 if (mEmergencyOverride.mPhoneId != req.mPhoneId) { 859 logl("emergency override requested for phone id " + req.mPhoneId + " when " 860 + "there is already an override in place for phone id " 861 + mEmergencyOverride.mPhoneId + ". Ignoring."); 862 if (req.isCallbackAvailable()) { 863 // Send failed result 864 req.mOverrideCompleteFuture.complete(false); 865 } 866 break; 867 } else { 868 if (mEmergencyOverride.isCallbackAvailable()) { 869 // Unblock any waiting overrides if a new request comes in before the 870 // previous one is processed. 871 mEmergencyOverride.mOverrideCompleteFuture.complete(false); 872 } 873 } 874 } 875 mEmergencyOverride = req; 876 877 logl("new emergency override - " + mEmergencyOverride); 878 // a new request has been created, remove any previous override complete scheduled. 879 removeMessages(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 880 Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 881 // Make sure that if we never get an incall indication that we remove the override. 882 sendMessageDelayed(msg2, DEFAULT_DATA_OVERRIDE_TIMEOUT_MS); 883 // Wait for call to end and EVENT_PRECISE_CALL_STATE_CHANGED to be called, then 884 // start timer to remove DDS emergency override. 885 if (!onEvaluate(REQUESTS_UNCHANGED, "emer_override_dds")) { 886 // Nothing changed as a result of override, so no modem command was sent. Treat 887 // as success. 888 mEmergencyOverride.sendOverrideCompleteCallbackResultAndClear(true); 889 // Do not clear mEmergencyOverride here, as we still want to keep the override 890 // active for the time specified in case the user tries to switch default data. 891 } 892 break; 893 } 894 case EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE: { 895 logl("Emergency override removed - " + mEmergencyOverride); 896 mEmergencyOverride = null; 897 onEvaluate(REQUESTS_UNCHANGED, "emer_rm_override_dds"); 898 break; 899 } 900 case EVENT_MULTI_SIM_CONFIG_CHANGED: { 901 int activeModemCount = (int) ((AsyncResult) msg.obj).result; 902 onMultiSimConfigChanged(activeModemCount); 903 break; 904 } 905 case EVENT_PROCESS_SIM_STATE_CHANGE: { 906 int slotIndex = msg.arg1; 907 int simState = msg.arg2; 908 909 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 910 logl("EVENT_PROCESS_SIM_STATE_CHANGE: skip processing due to invalid slotId: " 911 + slotIndex); 912 } else if (TelephonyManager.SIM_STATE_LOADED == simState) { 913 if (mCurrentDdsSwitchFailure.get(slotIndex).contains( 914 CommandException.Error.INVALID_SIM_STATE) 915 && isSimApplicationReady(slotIndex)) { 916 sendRilCommands(slotIndex); 917 } 918 // SIM loaded after subscriptions slot mapping are done. Evaluate for auto 919 // data switch. 920 mAutoDataSwitchController.evaluateAutoDataSwitch( 921 AutoDataSwitchController.EVALUATION_REASON_SIM_LOADED); 922 } 923 break; 924 } 925 } 926 } 927 928 /** 929 * Only provide service for the handler of PhoneSwitcher. 930 * @return true if the radio tech changed, otherwise false 931 */ onImsRadioTechChanged(@onNull AsyncResult asyncResult)932 private boolean onImsRadioTechChanged(@NonNull AsyncResult asyncResult) { 933 ImsPhone.ImsRegistrationRadioTechInfo imsRegistrationRadioTechInfo = 934 (ImsPhone.ImsRegistrationRadioTechInfo) asyncResult.result; 935 if (imsRegistrationRadioTechInfo == null 936 || imsRegistrationRadioTechInfo.phoneId() == INVALID_PHONE_INDEX 937 || imsRegistrationRadioTechInfo.imsRegistrationState() 938 == RegistrationManager.REGISTRATION_STATE_REGISTERING) { 939 // Ignore REGISTERING state, handle only REGISTERED and NOT_REGISTERED 940 log("onImsRadioTechChanged : result is not available"); 941 return false; 942 } 943 944 int phoneId = imsRegistrationRadioTechInfo.phoneId(); 945 int subId = SubscriptionManager.getSubscriptionId(phoneId); 946 int tech = imsRegistrationRadioTechInfo.imsRegistrationTech(); 947 log("onImsRadioTechChanged phoneId : " + phoneId + " subId : " + subId + " old tech : " 948 + mImsRegistrationRadioTechMap.get(phoneId, REGISTRATION_TECH_NONE) 949 + " new tech : " + tech); 950 951 if (mImsRegistrationRadioTechMap.get(phoneId, REGISTRATION_TECH_NONE) == tech) { 952 // Registration tech not changed 953 return false; 954 } 955 956 mImsRegistrationRadioTechMap.put(phoneId, tech); 957 958 // Need to update the cached IMS registration tech but no need to do any of the 959 // following. When the SIM removed, REGISTRATION_STATE_NOT_REGISTERED is notified. 960 return subId != INVALID_SUBSCRIPTION_ID; 961 } 962 onMultiSimConfigChanged(int activeModemCount)963 private synchronized void onMultiSimConfigChanged(int activeModemCount) { 964 // No change. 965 if (mActiveModemCount == activeModemCount) return; 966 int oldActiveModemCount = mActiveModemCount; 967 mActiveModemCount = activeModemCount; 968 969 mPhoneSubscriptions = copyOf(mPhoneSubscriptions, mActiveModemCount); 970 mPhoneStates = copyOf(mPhoneStates, mActiveModemCount); 971 972 // Dual SIM -> Single SIM switch. 973 for (int phoneId = oldActiveModemCount - 1; phoneId >= mActiveModemCount; phoneId--) { 974 mCurrentDdsSwitchFailure.remove(phoneId); 975 } 976 977 // Single SIM -> Dual SIM switch. 978 for (int phoneId = oldActiveModemCount; phoneId < mActiveModemCount; phoneId++) { 979 mPhoneStates[phoneId] = new PhoneState(); 980 Phone phone = PhoneFactory.getPhone(phoneId); 981 if (phone == null) continue; 982 983 phone.registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null); 984 // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone. 985 phone.registerForPreciseCallStateChanged(this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 986 if (phone.getImsPhone() != null) { 987 phone.getImsPhone().registerForPreciseCallStateChanged( 988 this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 989 if (mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 990 // Initialize IMS registration tech for new phoneId 991 mImsRegistrationRadioTechMap.put(phoneId, REGISTRATION_TECH_NONE); 992 ((ImsPhone) phone.getImsPhone()).registerForImsRegistrationChanges( 993 this, EVENT_IMS_RADIO_TECH_CHANGED, null); 994 995 log("register handler to receive IMS registration : " + phoneId); 996 } 997 } 998 999 mDataSettingsManagerCallbacks.computeIfAbsent(phone.getPhoneId(), 1000 v -> new DataSettingsManagerCallback(this::post) { 1001 @Override 1002 public void onDataEnabledChanged(boolean enabled, 1003 @TelephonyManager.DataEnabledChangedReason int reason, 1004 @NonNull String callingPackage) { 1005 PhoneSwitcher.this.onDataEnabledChanged(); 1006 } 1007 @Override 1008 public void onDataRoamingEnabledChanged(boolean enabled) { 1009 PhoneSwitcher.this.mAutoDataSwitchController.evaluateAutoDataSwitch( 1010 AutoDataSwitchController 1011 .EVALUATION_REASON_DATA_SETTINGS_CHANGED); 1012 } 1013 }); 1014 phone.getDataSettingsManager().registerCallback( 1015 mDataSettingsManagerCallbacks.get(phone.getPhoneId())); 1016 1017 Set<CommandException.Error> ddsFailure = new HashSet<>(); 1018 mCurrentDdsSwitchFailure.add(ddsFailure); 1019 1020 if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 1021 registerForImsRadioTechChange(mContext, phoneId); 1022 } 1023 } 1024 1025 mAutoDataSwitchController.onMultiSimConfigChanged(activeModemCount); 1026 } 1027 1028 /** 1029 * Called when 1030 * 1. user changed mobile data settings 1031 * 2. OR user changed auto data switch feature 1032 */ onDataEnabledChanged()1033 private void onDataEnabledChanged() { 1034 if (isAnyVoiceCallActiveOnDevice()) { 1035 // user changed data related settings during call, switch or turn off immediately 1036 evaluateIfImmediateDataSwitchIsNeeded( 1037 "user changed data settings during call", 1038 DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); 1039 } else { 1040 mAutoDataSwitchController.evaluateAutoDataSwitch(AutoDataSwitchController 1041 .EVALUATION_REASON_DATA_SETTINGS_CHANGED); 1042 } 1043 } 1044 isInEmergencyCallbackMode()1045 private boolean isInEmergencyCallbackMode() { 1046 for (Phone p : PhoneFactory.getPhones()) { 1047 if (p == null) continue; 1048 if (p.isInEcm()) return true; 1049 Phone imsPhone = p.getImsPhone(); 1050 if (imsPhone != null && imsPhone.isInEcm()) { 1051 return true; 1052 } 1053 } 1054 return false; 1055 } 1056 1057 private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory { 1058 private final PhoneSwitcher mPhoneSwitcher; PhoneSwitcherNetworkRequestListener(Looper l, Context c, NetworkCapabilities nc, PhoneSwitcher ps)1059 public PhoneSwitcherNetworkRequestListener (Looper l, Context c, 1060 NetworkCapabilities nc, PhoneSwitcher ps) { 1061 super(l, c, "PhoneSwitcherNetworkRequstListener", nc); 1062 mPhoneSwitcher = ps; 1063 } 1064 1065 @Override needNetworkFor(@onNull NetworkRequest networkRequest)1066 protected void needNetworkFor(@NonNull NetworkRequest networkRequest) { 1067 if (VDBG) log("needNetworkFor " + networkRequest); 1068 Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK); 1069 msg.obj = networkRequest; 1070 msg.sendToTarget(); 1071 } 1072 1073 @Override releaseNetworkFor(@onNull NetworkRequest networkRequest)1074 protected void releaseNetworkFor(@NonNull NetworkRequest networkRequest) { 1075 if (VDBG) log("releaseNetworkFor " + networkRequest); 1076 Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK); 1077 msg.obj = networkRequest; 1078 msg.sendToTarget(); 1079 } 1080 } 1081 onRequestNetwork(NetworkRequest networkRequest)1082 private void onRequestNetwork(NetworkRequest networkRequest) { 1083 TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest( 1084 networkRequest, PhoneFactory.getDefaultPhone(), mFlags); 1085 if (!mNetworkRequestList.contains(telephonyNetworkRequest)) { 1086 mNetworkRequestList.add(telephonyNetworkRequest); 1087 onEvaluate(REQUESTS_CHANGED, "netRequest"); 1088 } 1089 } 1090 onReleaseNetwork(NetworkRequest networkRequest)1091 private void onReleaseNetwork(NetworkRequest networkRequest) { 1092 TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest( 1093 networkRequest, PhoneFactory.getDefaultPhone(), mFlags); 1094 if (mNetworkRequestList.remove(telephonyNetworkRequest)) { 1095 onEvaluate(REQUESTS_CHANGED, "netReleased"); 1096 collectReleaseNetworkMetrics(networkRequest); 1097 } 1098 } 1099 registerDefaultNetworkChangeCallback(int expectedSubId, int reason)1100 private void registerDefaultNetworkChangeCallback(int expectedSubId, int reason) { 1101 mDefaultNetworkCallback.mExpectedSubId = expectedSubId; 1102 mDefaultNetworkCallback.mSwitchReason = reason; 1103 } 1104 collectRequestNetworkMetrics(NetworkRequest networkRequest)1105 private void collectRequestNetworkMetrics(NetworkRequest networkRequest) { 1106 // Request network for MMS will temporary disable the network on default data subscription, 1107 // this only happen on multi-sim device. 1108 if (mActiveModemCount > 1 && networkRequest.hasCapability( 1109 NetworkCapabilities.NET_CAPABILITY_MMS)) { 1110 OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch(); 1111 onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS; 1112 onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_START; 1113 TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch); 1114 } 1115 } 1116 collectReleaseNetworkMetrics(NetworkRequest networkRequest)1117 private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) { 1118 // Release network for MMS will recover the network on default data subscription, this only 1119 // happen on multi-sim device. 1120 if (mActiveModemCount > 1 && networkRequest.hasCapability( 1121 NetworkCapabilities.NET_CAPABILITY_MMS)) { 1122 OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch(); 1123 onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS; 1124 onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_END; 1125 TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch); 1126 } 1127 } 1128 1129 /** 1130 * Cancel any auto switch attempts when the current environment is not suitable for auto switch. 1131 */ cancelPendingAutoDataSwitchValidation()1132 private void cancelPendingAutoDataSwitchValidation() { 1133 if (mValidator.isValidating()) { 1134 mValidator.stopValidation(); 1135 1136 removeMessages(EVENT_NETWORK_VALIDATION_DONE); 1137 removeMessages(EVENT_NETWORK_AVAILABLE); 1138 mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 1139 mPendingSwitchNeedValidation = false; 1140 } 1141 } 1142 getTm()1143 private TelephonyManager getTm() { 1144 return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 1145 } 1146 1147 protected static final boolean REQUESTS_CHANGED = true; 1148 protected static final boolean REQUESTS_UNCHANGED = false; 1149 /** 1150 * Re-evaluate things. Do nothing if nothing's changed. 1151 * <p> 1152 * Otherwise, go through the requests in priority order adding their phone until we've added up 1153 * to the max allowed. Then go through shutting down phones that aren't in the active phone 1154 * list. Finally, activate all phones in the active phone list. 1155 * 1156 * @return {@code True} if the default data subscription need to be changed. 1157 */ onEvaluate(boolean requestsChanged, String reason)1158 protected boolean onEvaluate(boolean requestsChanged, String reason) { 1159 StringBuilder sb = new StringBuilder(reason); 1160 1161 // If we use HAL_COMMAND_PREFERRED_DATA, 1162 boolean diffDetected = mHalCommandToUse != HAL_COMMAND_PREFERRED_DATA && requestsChanged; 1163 1164 // Check if user setting of default non-opportunistic data sub is changed. 1165 int primaryDataSubId = mSubscriptionManagerService.getDefaultDataSubId(); 1166 if (primaryDataSubId != mPrimaryDataSubId) { 1167 sb.append(" mPrimaryDataSubId ").append(mPrimaryDataSubId).append("->") 1168 .append(primaryDataSubId); 1169 mPrimaryDataSubId = primaryDataSubId; 1170 mLastSwitchPreferredDataReason = DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL; 1171 } 1172 1173 // Check to see if there is any active subscription on any phone 1174 boolean hasAnyActiveSubscription = false; 1175 1176 // Check if phoneId to subId mapping is changed. 1177 for (int i = 0; i < mActiveModemCount; i++) { 1178 int sub = SubscriptionManager.getSubscriptionId(i); 1179 1180 if (SubscriptionManager.isValidSubscriptionId(sub)) hasAnyActiveSubscription = true; 1181 1182 if (sub != mPhoneSubscriptions[i]) { 1183 sb.append(" phone[").append(i).append("] ").append(mPhoneSubscriptions[i]); 1184 sb.append("->").append(sub); 1185 if (mAutoSelectedDataSubId == mPhoneSubscriptions[i]) { 1186 mAutoSelectedDataSubId = DEFAULT_SUBSCRIPTION_ID; 1187 } 1188 mPhoneSubscriptions[i] = sub; 1189 1190 if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) { 1191 // Listen to IMS radio tech change for new sub 1192 if (SubscriptionManager.isValidSubscriptionId(sub)) { 1193 registerForImsRadioTechChange(mContext, i); 1194 } 1195 } 1196 1197 diffDetected = true; 1198 mAutoDataSwitchController.notifySubscriptionsMappingChanged(); 1199 } 1200 } 1201 1202 if (!hasAnyActiveSubscription) { 1203 transitionToEmergencyPhone(); 1204 } else { 1205 if (VDBG) log("Found an active subscription"); 1206 } 1207 1208 // Check if phoneId for preferred data is changed. 1209 int oldPreferredDataPhoneId = mPreferredDataPhoneId; 1210 1211 // Check if subId for preferred data is changed. 1212 int oldPreferredDataSubId = mPreferredDataSubId.get(); 1213 1214 // When there are no subscriptions, the preferred data phone ID is invalid, but we want 1215 // to keep a valid phoneId for Emergency, so skip logic that updates for preferred data 1216 // phone ID. Ideally there should be a single set of checks that evaluate the correct 1217 // phoneId on a service-by-service basis (EIMS being one), but for now... just bypass 1218 // this logic in the no-SIM case. 1219 if (hasAnyActiveSubscription) updatePreferredDataPhoneId(); 1220 1221 if (oldPreferredDataPhoneId != mPreferredDataPhoneId) { 1222 sb.append(" preferred data phoneId ").append(oldPreferredDataPhoneId) 1223 .append("->").append(mPreferredDataPhoneId); 1224 diffDetected = true; 1225 } else if (oldPreferredDataSubId != mPreferredDataSubId.get()) { 1226 logl("SIM refresh, notify dds change"); 1227 // Inform connectivity about the active data phone 1228 notifyPreferredDataSubIdChanged(); 1229 } 1230 1231 // Always force DDS when radio on. This is to handle the corner cases that modem and android 1232 // DDS are out of sync after APM, AP should force DDS when radio on. long term solution 1233 // should be having API to query preferred data modem to detect the out-of-sync scenarios. 1234 if (diffDetected || EVALUATION_REASON_RADIO_ON.equals(reason)) { 1235 logl("evaluating due to " + sb); 1236 if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) { 1237 // With HAL_COMMAND_PREFERRED_DATA, all phones are assumed to allow PS attach. 1238 // So marking all phone as active, and the phone with mPreferredDataPhoneId 1239 // will send radioConfig command. 1240 for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) { 1241 mPhoneStates[phoneId].active = true; 1242 } 1243 sendRilCommands(mPreferredDataPhoneId); 1244 } else { 1245 List<Integer> newActivePhones = new ArrayList<>(); 1246 1247 // If all phones can have PS attached, activate all. 1248 // Otherwise, choose to activate phones according to requests. And 1249 // if list is not full, add mPreferredDataPhoneId. 1250 if (mMaxDataAttachModemCount == mActiveModemCount) { 1251 for (int i = 0; i < mMaxDataAttachModemCount; i++) { 1252 newActivePhones.add(i); 1253 } 1254 } else { 1255 // First try to activate phone in voice call. 1256 if (mPhoneIdInVoiceCall != SubscriptionManager.INVALID_PHONE_INDEX) { 1257 newActivePhones.add(mPhoneIdInVoiceCall); 1258 } 1259 1260 if (newActivePhones.size() < mMaxDataAttachModemCount) { 1261 for (TelephonyNetworkRequest networkRequest : mNetworkRequestList) { 1262 int phoneIdForRequest = phoneIdForRequest(networkRequest); 1263 if (phoneIdForRequest == INVALID_PHONE_INDEX) continue; 1264 if (newActivePhones.contains(phoneIdForRequest)) continue; 1265 newActivePhones.add(phoneIdForRequest); 1266 if (newActivePhones.size() >= mMaxDataAttachModemCount) break; 1267 } 1268 } 1269 1270 if (newActivePhones.size() < mMaxDataAttachModemCount 1271 && !newActivePhones.contains(mPreferredDataPhoneId) 1272 && SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) { 1273 newActivePhones.add(mPreferredDataPhoneId); 1274 } 1275 } 1276 1277 if (VDBG) { 1278 log("mPrimaryDataSubId = " + mPrimaryDataSubId); 1279 log("mAutoSelectedDataSubId = " + mAutoSelectedDataSubId); 1280 for (int i = 0; i < mActiveModemCount; i++) { 1281 log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]"); 1282 } 1283 log(" newActivePhones:"); 1284 for (Integer i : newActivePhones) log(" " + i); 1285 } 1286 1287 for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) { 1288 if (!newActivePhones.contains(phoneId)) { 1289 deactivate(phoneId); 1290 } 1291 } 1292 1293 // only activate phones up to the limit 1294 for (int phoneId : newActivePhones) { 1295 activate(phoneId); 1296 } 1297 } 1298 } 1299 return diffDetected; 1300 } 1301 1302 protected static class PhoneState { 1303 public volatile boolean active = false; 1304 public long lastRequested = 0; 1305 } 1306 activate(int phoneId)1307 protected void activate(int phoneId) { 1308 switchPhone(phoneId, true); 1309 } 1310 deactivate(int phoneId)1311 protected void deactivate(int phoneId) { 1312 switchPhone(phoneId, false); 1313 } 1314 switchPhone(int phoneId, boolean active)1315 private void switchPhone(int phoneId, boolean active) { 1316 PhoneState state = mPhoneStates[phoneId]; 1317 if (state.active == active) return; 1318 state.active = active; 1319 logl((active ? "activate " : "deactivate ") + phoneId); 1320 state.lastRequested = System.currentTimeMillis(); 1321 sendRilCommands(phoneId); 1322 } 1323 1324 /** 1325 * Used when the modem may have been rebooted and we 1326 * want to resend setDataAllowed or setPreferredDataSubscriptionId 1327 */ onRadioCapChanged(int phoneId)1328 public void onRadioCapChanged(int phoneId) { 1329 if (!SubscriptionManager.isValidPhoneId(phoneId)) return; 1330 Message msg = obtainMessage(EVENT_RADIO_CAPABILITY_CHANGED); 1331 msg.arg1 = phoneId; 1332 msg.sendToTarget(); 1333 } 1334 1335 /** 1336 * Switch the Default data for the context of an outgoing emergency call. 1337 * <p> 1338 * In some cases, we need to try to switch the Default Data subscription before placing the 1339 * emergency call on DSDS devices. This includes the following situation: 1340 * - The modem does not support processing GNSS SUPL requests on the non-default data 1341 * subscription. For some carriers that do not provide a control plane fallback mechanism, the 1342 * SUPL request will be dropped and we will not be able to get the user's location for the 1343 * emergency call. In this case, we need to swap default data temporarily. 1344 * @param phoneId The phone to use to evaluate whether or not the default data should be moved 1345 * to this subscription. 1346 * @param overrideTimeSec The amount of time to override the default data setting for after the 1347 * emergency call ends. 1348 * @param dataSwitchResult A {@link CompletableFuture} to be called with a {@link Boolean} 1349 * result when the default data switch has either completed (true) or 1350 * failed (false). 1351 */ overrideDefaultDataForEmergency(int phoneId, int overrideTimeSec, CompletableFuture<Boolean> dataSwitchResult)1352 public void overrideDefaultDataForEmergency(int phoneId, int overrideTimeSec, 1353 CompletableFuture<Boolean> dataSwitchResult) { 1354 if (!SubscriptionManager.isValidPhoneId(phoneId)) return; 1355 Message msg = obtainMessage(EVENT_OVERRIDE_DDS_FOR_EMERGENCY); 1356 EmergencyOverrideRequest request = new EmergencyOverrideRequest(); 1357 request.mPhoneId = phoneId; 1358 request.mGnssOverrideTimeMs = overrideTimeSec * 1000; 1359 request.mOverrideCompleteFuture = dataSwitchResult; 1360 msg.obj = request; 1361 msg.sendToTarget(); 1362 } 1363 sendRilCommands(int phoneId)1364 protected void sendRilCommands(int phoneId) { 1365 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1366 logl("sendRilCommands: skip dds switch due to invalid phoneId=" + phoneId); 1367 return; 1368 } 1369 1370 Message message = Message.obtain(this, EVENT_MODEM_COMMAND_DONE, phoneId); 1371 if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) { 1372 // Skip ALLOW_DATA for single SIM device 1373 if (mActiveModemCount > 1) { 1374 PhoneFactory.getPhone(phoneId).mCi.setDataAllowed(isPhoneActive(phoneId), message); 1375 } 1376 } else if (phoneId == mPreferredDataPhoneId) { 1377 // Only setPreferredDataModem if the phoneId equals to current mPreferredDataPhoneId 1378 logl("sendRilCommands: setPreferredDataModem - phoneId: " + phoneId); 1379 mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, message); 1380 } 1381 } 1382 phoneIdForRequest(TelephonyNetworkRequest networkRequest)1383 private int phoneIdForRequest(TelephonyNetworkRequest networkRequest) { 1384 NetworkRequest netRequest = networkRequest.getNativeNetworkRequest(); 1385 int subId = getSubIdFromNetworkSpecifier(netRequest.getNetworkSpecifier()); 1386 1387 if (subId == DEFAULT_SUBSCRIPTION_ID) return mPreferredDataPhoneId; 1388 if (subId == INVALID_SUBSCRIPTION_ID) return INVALID_PHONE_INDEX; 1389 1390 int preferredDataSubId = (mPreferredDataPhoneId >= 0 1391 && mPreferredDataPhoneId < mActiveModemCount) 1392 ? mPhoneSubscriptions[mPreferredDataPhoneId] : INVALID_SUBSCRIPTION_ID; 1393 1394 // Currently we assume multi-SIM devices will only support one Internet PDN connection. So 1395 // if Internet PDN is established on the non-preferred phone, it will interrupt 1396 // Internet connection on the preferred phone. So we only accept Internet request with 1397 // preferred data subscription or no specified subscription. 1398 // One exception is, if it's restricted request (doesn't have NET_CAPABILITY_NOT_RESTRICTED) 1399 // it will be accepted, which is used temporary data usage from system. 1400 if (netRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 1401 && netRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 1402 && subId != preferredDataSubId && subId != mValidator.getSubIdInValidation()) { 1403 // Returning INVALID_PHONE_INDEX will result in netRequest not being handled. 1404 return INVALID_PHONE_INDEX; 1405 } 1406 1407 // Try to find matching phone ID. If it doesn't exist, we'll end up returning INVALID. 1408 int phoneId = INVALID_PHONE_INDEX; 1409 for (int i = 0; i < mActiveModemCount; i++) { 1410 if (mPhoneSubscriptions[i] == subId) { 1411 phoneId = i; 1412 break; 1413 } 1414 } 1415 return phoneId; 1416 } 1417 getSubIdFromNetworkSpecifier(NetworkSpecifier specifier)1418 protected int getSubIdFromNetworkSpecifier(NetworkSpecifier specifier) { 1419 if (specifier == null) { 1420 return DEFAULT_SUBSCRIPTION_ID; 1421 } 1422 if (specifier instanceof TelephonyNetworkSpecifier) { 1423 return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); 1424 } 1425 return INVALID_SUBSCRIPTION_ID; 1426 } 1427 isActiveSubId(int subId)1428 private boolean isActiveSubId(int subId) { 1429 SubscriptionInfoInternal subInfo = mSubscriptionManagerService 1430 .getSubscriptionInfoInternal(subId); 1431 return subInfo != null && subInfo.isActive(); 1432 } 1433 1434 // This updates mPreferredDataPhoneId which decides which phone should handle default network 1435 // requests. updatePreferredDataPhoneId()1436 protected void updatePreferredDataPhoneId() { 1437 if (mEmergencyOverride != null && findPhoneById(mEmergencyOverride.mPhoneId) != null) { 1438 // Override DDS for emergency even if user data is not enabled, since it is an 1439 // emergency. 1440 // TODO: Provide a notification to the user that metered data is currently being 1441 // used during this period. 1442 logl("updatePreferredDataPhoneId: preferred data overridden for emergency." 1443 + " phoneId = " + mEmergencyOverride.mPhoneId); 1444 mPreferredDataPhoneId = mEmergencyOverride.mPhoneId; 1445 mLastSwitchPreferredDataReason = DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; 1446 } else { 1447 int imsRegTech = mImsRegTechProvider.get(mContext, mPhoneIdInVoiceCall); 1448 if (isAnyVoiceCallActiveOnDevice() && imsRegTech != REGISTRATION_TECH_IWLAN) { 1449 if (imsRegTech != REGISTRATION_TECH_CROSS_SIM) { 1450 mPreferredDataPhoneId = shouldSwitchDataDueToInCall() 1451 ? mPhoneIdInVoiceCall : getFallbackDataPhoneIdForInternetRequests(); 1452 } else { 1453 logl("IMS call on cross-SIM, skip switching data to phone " 1454 + mPhoneIdInVoiceCall); 1455 } 1456 } else { 1457 mPreferredDataPhoneId = getFallbackDataPhoneIdForInternetRequests(); 1458 } 1459 } 1460 1461 mPreferredDataSubId.set(SubscriptionManager.getSubscriptionId(mPreferredDataPhoneId)); 1462 } 1463 1464 /** 1465 * @return the default data phone Id (or auto selected phone Id in auto data switch/CBRS case) 1466 */ getFallbackDataPhoneIdForInternetRequests()1467 private int getFallbackDataPhoneIdForInternetRequests() { 1468 int fallbackSubId = isActiveSubId(mAutoSelectedDataSubId) 1469 ? mAutoSelectedDataSubId : mPrimaryDataSubId; 1470 1471 if (SubscriptionManager.isUsableSubIdValue(fallbackSubId)) { 1472 for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) { 1473 if (mPhoneSubscriptions[phoneId] == fallbackSubId) { 1474 return phoneId; 1475 } 1476 } 1477 } 1478 return SubscriptionManager.INVALID_PHONE_INDEX; 1479 } 1480 1481 /** 1482 * If a phone is in call and user enabled its mobile data and auto data switch feature, we 1483 * should switch internet connection to it because the other modem will lose data connection 1484 * anyway. 1485 * @return {@code true} if should switch data to the phone in voice call 1486 */ shouldSwitchDataDueToInCall()1487 private boolean shouldSwitchDataDueToInCall() { 1488 Phone voicePhone = findPhoneById(mPhoneIdInVoiceCall); 1489 Phone defaultDataPhone = getPhoneBySubId(mPrimaryDataSubId); 1490 return defaultDataPhone != null // check user enabled data 1491 && defaultDataPhone.isUserDataEnabled() 1492 && voicePhone != null // check user enabled voice during call feature 1493 && voicePhone.getDataSettingsManager().isDataEnabled(); 1494 } 1495 transitionToEmergencyPhone()1496 protected void transitionToEmergencyPhone() { 1497 if (mActiveModemCount <= 0) { 1498 logl("No phones: unable to reset preferred phone for emergency"); 1499 return; 1500 } 1501 1502 if (mPreferredDataPhoneId != DEFAULT_EMERGENCY_PHONE_ID) { 1503 logl("No active subscriptions: resetting preferred phone to 0 for emergency"); 1504 mPreferredDataPhoneId = DEFAULT_EMERGENCY_PHONE_ID; 1505 } 1506 1507 if (mPreferredDataSubId.get() != INVALID_SUBSCRIPTION_ID) { 1508 mPreferredDataSubId.set(INVALID_SUBSCRIPTION_ID); 1509 notifyPreferredDataSubIdChanged(); 1510 } 1511 } 1512 getPhoneBySubId(int subId)1513 private Phone getPhoneBySubId(int subId) { 1514 return findPhoneById(mSubscriptionManagerService.getPhoneId(subId)); 1515 } 1516 findPhoneById(final int phoneId)1517 private Phone findPhoneById(final int phoneId) { 1518 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1519 return null; 1520 } 1521 return PhoneFactory.getPhone(phoneId); 1522 } 1523 shouldApplyNetworkRequest( TelephonyNetworkRequest networkRequest, int phoneId)1524 public synchronized boolean shouldApplyNetworkRequest( 1525 TelephonyNetworkRequest networkRequest, int phoneId) { 1526 if (!SubscriptionManager.isValidPhoneId(phoneId)) return false; 1527 1528 int subId = SubscriptionManager.getSubscriptionId(phoneId); 1529 1530 // In any case, if phone state is inactive, don't apply the network request. 1531 if (!isPhoneActive(phoneId) || (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID 1532 && !isEmergencyNetworkRequest(networkRequest))) { 1533 return false; 1534 } 1535 1536 NetworkRequest netRequest = networkRequest.getNativeNetworkRequest(); 1537 subId = getSubIdFromNetworkSpecifier(netRequest.getNetworkSpecifier()); 1538 1539 //if this phone is an emergency networkRequest 1540 //and subId is not specified that is invalid or default 1541 if (isAnyVoiceCallActiveOnDevice() && isEmergencyNetworkRequest(networkRequest) 1542 && (subId == DEFAULT_SUBSCRIPTION_ID || subId == INVALID_SUBSCRIPTION_ID)) { 1543 return phoneId == mPhoneIdInVoiceCall; 1544 } 1545 1546 int phoneIdToHandle = phoneIdForRequest(networkRequest); 1547 return phoneId == phoneIdToHandle; 1548 } 1549 isEmergencyNetworkRequest(TelephonyNetworkRequest networkRequest)1550 boolean isEmergencyNetworkRequest(TelephonyNetworkRequest networkRequest) { 1551 return networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS); 1552 } 1553 1554 @VisibleForTesting isPhoneActive(int phoneId)1555 protected boolean isPhoneActive(int phoneId) { 1556 if (phoneId >= mActiveModemCount) 1557 return false; 1558 return mPhoneStates[phoneId].active; 1559 } 1560 1561 /** 1562 * If preferred phone changes, or phone activation status changes, registrants 1563 * will be notified. 1564 */ registerForActivePhoneSwitch(Handler h, int what, Object o)1565 public void registerForActivePhoneSwitch(Handler h, int what, Object o) { 1566 Registrant r = new Registrant(h, what, o); 1567 mActivePhoneRegistrants.add(r); 1568 r.notifyRegistrant(); 1569 } 1570 1571 /** 1572 * Set opportunistic data subscription. It's an indication to switch Internet data to this 1573 * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate 1574 * it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting 1575 * opportunistic data sub and switch data back to primary sub. 1576 * 1577 * @param subId the opportunistic data subscription to switch to. pass DEFAULT_SUBSCRIPTION_ID 1578 * if un-setting it. 1579 * @param needValidation whether Telephony will wait until the network is validated by 1580 * connectivity service before switching data to it. More details see 1581 * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. 1582 * @param callback Callback will be triggered once it succeeds or failed. 1583 * Pass null if don't care about the result. 1584 */ setOpportunisticDataSubscription(int subId, boolean needValidation, ISetOpportunisticDataCallback callback)1585 private void setOpportunisticDataSubscription(int subId, boolean needValidation, 1586 ISetOpportunisticDataCallback callback) { 1587 validate(subId, needValidation, 1588 DataSwitch.Reason.DATA_SWITCH_REASON_CBRS, callback); 1589 } 1590 1591 /** 1592 * Try setup a new internet connection on the subId that's pending validation. If the validation 1593 * succeeds, this subId will be evaluated for being the preferred data subId; If fails, nothing 1594 * happens. 1595 * Callback will be updated with the validation result. 1596 * 1597 * @param subId Sub Id that's pending switch, awaiting validation. 1598 * @param needValidation {@code false} if switch to the subId even if validation fails. 1599 * @param switchReason The switch reason for this validation 1600 * @param callback Optional - specific for external opportunistic sub validation request. 1601 */ validate(int subId, boolean needValidation, int switchReason, @Nullable ISetOpportunisticDataCallback callback)1602 private void validate(int subId, boolean needValidation, int switchReason, 1603 @Nullable ISetOpportunisticDataCallback callback) { 1604 int subIdToValidate = (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) 1605 ? mPrimaryDataSubId : subId; 1606 logl("Validate subId " + subId + " due to " + switchReasonToString(switchReason) 1607 + " needValidation=" + needValidation + " subIdToValidate=" + subIdToValidate 1608 + " mAutoSelectedDataSubId=" + mAutoSelectedDataSubId 1609 + " mPreferredDataSubId=" + mPreferredDataSubId.get()); 1610 if (!isActiveSubId(subIdToValidate)) { 1611 logl("Can't switch data to inactive subId " + subIdToValidate); 1612 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 1613 // the default data sub is not selected yet, store the intent of switching to 1614 // default subId once it becomes available. 1615 mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 1616 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS); 1617 } else { 1618 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION); 1619 } 1620 return; 1621 } 1622 1623 if (mValidator.isValidating()) { 1624 mValidator.stopValidation(); 1625 sendSetOpptCallbackHelper(mSetOpptSubCallback, SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED); 1626 mSetOpptSubCallback = null; 1627 } 1628 1629 // Remove EVENT_NETWORK_VALIDATION_DONE. Don't handle validation result of previous subId 1630 // if queued. 1631 removeMessages(EVENT_NETWORK_VALIDATION_DONE); 1632 removeMessages(EVENT_NETWORK_AVAILABLE); 1633 1634 mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 1635 1636 if (subIdToValidate == mPreferredDataSubId.get()) { 1637 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 1638 mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 1639 } 1640 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS); 1641 return; 1642 } 1643 1644 mLastSwitchPreferredDataReason = switchReason; 1645 logDataSwitchEvent(subIdToValidate, 1646 TelephonyEvent.EventState.EVENT_STATE_START, 1647 switchReason); 1648 registerDefaultNetworkChangeCallback(subIdToValidate, 1649 switchReason); 1650 1651 // If validation feature is not supported, set it directly. Otherwise, 1652 // start validation on the subscription first. 1653 if (!mValidator.isValidationFeatureSupported()) { 1654 setAutoSelectedDataSubIdInternal(subId); 1655 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS); 1656 return; 1657 } 1658 1659 // Even if needValidation is false, we still send request to validator. The reason is we 1660 // want to delay data switch until network is available on the target sub, to have a 1661 // smoothest transition possible. 1662 // In this case, even if data connection eventually failed in 2 seconds, we still 1663 // confirm the switch, to maximally respect the request. 1664 mPendingSwitchSubId = subIdToValidate; 1665 mPendingSwitchNeedValidation = needValidation; 1666 mSetOpptSubCallback = callback; 1667 long validationTimeout = getValidationTimeout(subIdToValidate, needValidation); 1668 mValidator.validate(subIdToValidate, validationTimeout, false, mValidationCallback); 1669 } 1670 getValidationTimeout(int subId, boolean needValidation)1671 private long getValidationTimeout(int subId, boolean needValidation) { 1672 if (!needValidation) return DEFAULT_VALIDATION_EXPIRATION_TIME; 1673 1674 long validationTimeout = DEFAULT_VALIDATION_EXPIRATION_TIME; 1675 CarrierConfigManager configManager = (CarrierConfigManager) 1676 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1677 if (configManager != null) { 1678 PersistableBundle b = configManager.getConfigForSubId(subId); 1679 if (b != null) { 1680 validationTimeout = b.getLong(KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG); 1681 } 1682 } 1683 return validationTimeout; 1684 } 1685 sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result)1686 private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) { 1687 if (callback == null) return; 1688 try { 1689 callback.onComplete(result); 1690 } catch (RemoteException exception) { 1691 logl("RemoteException " + exception); 1692 } 1693 } 1694 1695 /** 1696 * Evaluate whether the specified sub Id can be set to be the preferred data sub Id. 1697 * 1698 * @param subId The subId that we tried to validate: could possibly be unvalidated if validation 1699 * feature is not supported. 1700 */ setAutoSelectedDataSubIdInternal(int subId)1701 private void setAutoSelectedDataSubIdInternal(int subId) { 1702 if (mAutoSelectedDataSubId != subId) { 1703 mAutoSelectedDataSubId = subId; 1704 onEvaluate(REQUESTS_UNCHANGED, switchReasonToString(mLastSwitchPreferredDataReason)); 1705 } 1706 } 1707 confirmSwitch(int subId, boolean confirm)1708 private void confirmSwitch(int subId, boolean confirm) { 1709 logl("confirmSwitch: subId " + subId + (confirm ? " confirmed." : " cancelled.")); 1710 int resultForCallBack; 1711 if (!isActiveSubId(subId)) { 1712 logl("confirmSwitch: subId " + subId + " is no longer active"); 1713 resultForCallBack = SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION; 1714 } else if (!confirm) { 1715 resultForCallBack = SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; 1716 1717 // retry for auto data switch validation failure 1718 if (mLastSwitchPreferredDataReason == DataSwitch.Reason.DATA_SWITCH_REASON_AUTO) { 1719 mAutoDataSwitchController.evaluateRetryOnValidationFailed(); 1720 } 1721 } else { 1722 if (subId == mPrimaryDataSubId) { 1723 setAutoSelectedDataSubIdInternal(DEFAULT_SUBSCRIPTION_ID); 1724 } else { 1725 setAutoSelectedDataSubIdInternal(subId); 1726 } 1727 resultForCallBack = SET_OPPORTUNISTIC_SUB_SUCCESS; 1728 mAutoDataSwitchController.resetFailedCount(); 1729 } 1730 1731 // Trigger callback if needed 1732 sendSetOpptCallbackHelper(mSetOpptSubCallback, resultForCallBack); 1733 mSetOpptSubCallback = null; 1734 mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 1735 } 1736 onNetworkAvailable(int subId, Network network)1737 private void onNetworkAvailable(int subId, Network network) { 1738 log("onNetworkAvailable: on subId " + subId); 1739 // Do nothing unless pending switch matches target subId and it doesn't require 1740 // validation pass. 1741 if (mPendingSwitchSubId == INVALID_SUBSCRIPTION_ID || mPendingSwitchSubId != subId 1742 || mPendingSwitchNeedValidation) { 1743 return; 1744 } 1745 confirmSwitch(subId, true); 1746 } 1747 onValidationDone(int subId, boolean passed)1748 private void onValidationDone(int subId, boolean passed) { 1749 logl("onValidationDone: " + (passed ? "passed" : "failed") + " on subId " + subId); 1750 if (mPendingSwitchSubId == INVALID_SUBSCRIPTION_ID || mPendingSwitchSubId != subId) return; 1751 1752 // If validation failed and mPendingSwitch.mNeedValidation is false, we still confirm 1753 // the switch. 1754 confirmSwitch(subId, passed || !mPendingSwitchNeedValidation); 1755 } 1756 1757 /** 1758 * Notify PhoneSwitcher to try to switch data to an opportunistic subscription. 1759 * <p> 1760 * Set opportunistic data subscription. It's an indication to switch Internet data to this 1761 * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate 1762 * it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting 1763 * opportunistic data sub and switch data back to primary sub. 1764 * 1765 * @param subId the opportunistic data subscription to switch to. pass DEFAULT_SUBSCRIPTION_ID 1766 * if un-setting it. 1767 * @param needValidation whether Telephony will wait until the network is validated by 1768 * connectivity service before switching data to it. More details see 1769 * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. 1770 * @param callback Callback will be triggered once it succeeds or failed. 1771 * Pass null if don't care about the result. 1772 */ trySetOpportunisticDataSubscription(int subId, boolean needValidation, ISetOpportunisticDataCallback callback)1773 public void trySetOpportunisticDataSubscription(int subId, boolean needValidation, 1774 ISetOpportunisticDataCallback callback) { 1775 logl("Try set opportunistic data subscription to subId " + subId 1776 + (needValidation ? " with " : " without ") + "validation"); 1777 PhoneSwitcher.this.obtainMessage(EVENT_OPPT_DATA_SUB_CHANGED, 1778 subId, needValidation ? 1 : 0, callback).sendToTarget(); 1779 } 1780 isPhoneInVoiceCall(Phone phone)1781 protected boolean isPhoneInVoiceCall(Phone phone) { 1782 if (phone == null) { 1783 return false; 1784 } 1785 1786 // A phone in voice call might trigger data being switched to it. 1787 // Exclude dialing to give modem time to process an EMC first before dealing with DDS switch 1788 // Include alerting because modem RLF leads to delay in switch, so carrier required to 1789 // switch in alerting phase. 1790 // TODO: check ringing call for vDADA 1791 return (!phone.getBackgroundCall().isIdle() 1792 && phone.getBackgroundCall().getState() != Call.State.DIALING) 1793 || (!phone.getForegroundCall().isIdle() 1794 && phone.getForegroundCall().getState() != Call.State.DIALING); 1795 } 1796 updateHalCommandToUse()1797 private void updateHalCommandToUse() { 1798 mHalCommandToUse = mRadioConfig.isSetPreferredDataCommandSupported() 1799 ? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA; 1800 } 1801 getPreferredDataPhoneId()1802 public int getPreferredDataPhoneId() { 1803 return mPreferredDataPhoneId; 1804 } 1805 1806 /** 1807 * Log debug messages and also log into the local log. 1808 * @param l debug messages 1809 */ logl(String l)1810 protected void logl(String l) { 1811 log(l); 1812 mLocalLog.log(l); 1813 } 1814 1815 /** 1816 * Log debug messages. 1817 * @param s debug messages 1818 */ log(@onNull String s)1819 private void log(@NonNull String s) { 1820 Rlog.d(LOG_TAG, s); 1821 } 1822 1823 /** 1824 * Log debug error messages. 1825 * @param s debug messages 1826 */ loge(@onNull String s)1827 private void loge(@NonNull String s) { 1828 Rlog.e(LOG_TAG, s); 1829 } 1830 1831 1832 /** 1833 * Convert data switch reason into string. 1834 * 1835 * @param reason The switch reason. 1836 * @return The switch reason in string format. 1837 */ 1838 @NonNull switchReasonToString(int reason)1839 private static String switchReasonToString(int reason) { 1840 return switch (reason) { 1841 case DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN -> "UNKNOWN"; 1842 case DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL -> "MANUAL"; 1843 case DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL -> "IN_CALL"; 1844 case DataSwitch.Reason.DATA_SWITCH_REASON_CBRS -> "CBRS"; 1845 case DataSwitch.Reason.DATA_SWITCH_REASON_AUTO -> "AUTO"; 1846 default -> "UNKNOWN(" + reason + ")"; 1847 }; 1848 } 1849 1850 /** 1851 * Concert switching state to string 1852 * 1853 * @param state The switching state. 1854 * @return The switching state in string format. 1855 */ 1856 @NonNull switchStateToString(int state)1857 private static String switchStateToString(int state) { 1858 return switch (state) { 1859 case TelephonyEvent.EventState.EVENT_STATE_UNKNOWN -> "UNKNOWN"; 1860 case TelephonyEvent.EventState.EVENT_STATE_START -> "START"; 1861 case TelephonyEvent.EventState.EVENT_STATE_END -> "END"; 1862 default -> "UNKNOWN(" + state + ")"; 1863 }; 1864 } 1865 1866 /** 1867 * Log data switch event 1868 * 1869 * @param subId Subscription index. 1870 * @param state The switching state. 1871 * @param reason The switching reason. 1872 */ 1873 private void logDataSwitchEvent(int subId, int state, int reason) { 1874 logl("Data switch state=" + switchStateToString(state) + " due to reason=" 1875 + switchReasonToString(reason) + " on subId " + subId); 1876 DataSwitch dataSwitch = new DataSwitch(); 1877 dataSwitch.state = state; 1878 dataSwitch.reason = reason; 1879 TelephonyMetrics.getInstance().writeDataSwitch(subId, dataSwitch); 1880 } 1881 1882 /** 1883 * See {@link PhoneStateListener#LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE}. 1884 */ 1885 protected void notifyPreferredDataSubIdChanged() { 1886 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) mContext 1887 .getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1888 logl("notifyPreferredDataSubIdChanged to " + mPreferredDataSubId.get()); 1889 telephonyRegistryManager.notifyActiveDataSubIdChanged(mPreferredDataSubId.get()); 1890 } 1891 1892 /** 1893 * @return The active data subscription id 1894 */ 1895 public int getActiveDataSubId() { 1896 return mPreferredDataSubId.get(); 1897 } 1898 1899 /** 1900 * @return The auto selected data subscription id. 1901 */ 1902 public int getAutoSelectedDataSubId() { 1903 return mAutoSelectedDataSubId; 1904 } 1905 1906 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1907 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 1908 pw.println("PhoneSwitcher:"); 1909 pw.increaseIndent(); 1910 Calendar c = Calendar.getInstance(); 1911 for (int i = 0; i < mActiveModemCount; i++) { 1912 PhoneState ps = mPhoneStates[i]; 1913 c.setTimeInMillis(ps.lastRequested); 1914 pw.println("PhoneId(" + i + ") active=" + ps.active 1915 + ", lastRequest=" 1916 + (ps.lastRequested == 0 ? "never" : 1917 String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c))); 1918 } 1919 pw.println("mPreferredDataPhoneId=" + mPreferredDataPhoneId); 1920 pw.println("mPreferredDataSubId=" + mPreferredDataSubId.get()); 1921 pw.println("DefaultDataSubId=" + mSubscriptionManagerService.getDefaultDataSubId()); 1922 pw.println("DefaultDataPhoneId=" + mSubscriptionManagerService.getPhoneId( 1923 mSubscriptionManagerService.getDefaultDataSubId())); 1924 pw.println("mPrimaryDataSubId=" + mPrimaryDataSubId); 1925 pw.println("mAutoSelectedDataSubId=" + mAutoSelectedDataSubId); 1926 pw.println("mIsRegisteredForImsRadioTechChange=" + mIsRegisteredForImsRadioTechChange); 1927 pw.println("mPendingSwitchNeedValidation=" + mPendingSwitchNeedValidation); 1928 pw.println("mMaxDataAttachModemCount=" + mMaxDataAttachModemCount); 1929 pw.println("mActiveModemCount=" + mActiveModemCount); 1930 pw.println("mPhoneIdInVoiceCall=" + mPhoneIdInVoiceCall); 1931 pw.println("mCurrentDdsSwitchFailure=" + mCurrentDdsSwitchFailure); 1932 pw.println("mLastSwitchPreferredDataReason=" 1933 + switchReasonToString(mLastSwitchPreferredDataReason)); 1934 pw.println("Local logs:"); 1935 pw.increaseIndent(); 1936 mLocalLog.dump(fd, pw, args); 1937 pw.decreaseIndent(); 1938 mAutoDataSwitchController.dump(fd, pw, args); 1939 pw.decreaseIndent(); 1940 } 1941 1942 private boolean isAnyVoiceCallActiveOnDevice() { 1943 boolean ret = mPhoneIdInVoiceCall != SubscriptionManager.INVALID_PHONE_INDEX; 1944 if (VDBG) log("isAnyVoiceCallActiveOnDevice: " + ret); 1945 return ret; 1946 } 1947 1948 private void onDdsSwitchResponse(AsyncResult ar) { 1949 boolean commandSuccess = ar != null && ar.exception == null; 1950 int phoneId = (int) ar.userObj; 1951 if (mEmergencyOverride != null) { 1952 logl("Emergency override result sent = " + commandSuccess); 1953 mEmergencyOverride.sendOverrideCompleteCallbackResultAndClear(commandSuccess); 1954 // Do not retry , as we do not allow changes in onEvaluate during an emergency 1955 // call. When the call ends, we will start the countdown to remove the override. 1956 } else if (!commandSuccess) { 1957 logl("onDdsSwitchResponse: DDS switch failed. with exception " + ar.exception); 1958 if (ar.exception instanceof CommandException) { 1959 CommandException.Error error = ((CommandException) 1960 (ar.exception)).getCommandError(); 1961 mCurrentDdsSwitchFailure.get(phoneId).add(error); 1962 if (error == CommandException.Error.OP_NOT_ALLOWED_DURING_VOICE_CALL) { 1963 logl("onDdsSwitchResponse: Wait for call end indication"); 1964 return; 1965 } else if (error == CommandException.Error.INVALID_SIM_STATE) { 1966 /* If there is a attach failure due to sim not ready then 1967 hold the retry until sim gets ready */ 1968 logl("onDdsSwitchResponse: Wait for SIM to get READY"); 1969 return; 1970 } 1971 } 1972 logl("onDdsSwitchResponse: Scheduling DDS switch retry"); 1973 sendMessageDelayed(Message.obtain(this, EVENT_MODEM_COMMAND_RETRY, 1974 phoneId), MODEM_COMMAND_RETRY_PERIOD_MS); 1975 return; 1976 } 1977 if (commandSuccess) { 1978 logl("onDdsSwitchResponse: DDS switch success on phoneId = " + phoneId); 1979 mAutoDataSwitchController.displayAutoDataSwitchNotification(phoneId, 1980 mLastSwitchPreferredDataReason == DataSwitch.Reason.DATA_SWITCH_REASON_AUTO); 1981 } 1982 mCurrentDdsSwitchFailure.get(phoneId).clear(); 1983 // Notify all registrants 1984 mActivePhoneRegistrants.notifyRegistrants(); 1985 notifyPreferredDataSubIdChanged(); 1986 } 1987 1988 private boolean isPhoneIdValidForRetry(int phoneId) { 1989 int ddsPhoneId = mSubscriptionManagerService.getPhoneId( 1990 mSubscriptionManagerService.getDefaultDataSubId()); 1991 if (ddsPhoneId != INVALID_PHONE_INDEX && ddsPhoneId == phoneId) { 1992 return true; 1993 } else { 1994 if (mNetworkRequestList.isEmpty()) return false; 1995 for (TelephonyNetworkRequest networkRequest : mNetworkRequestList) { 1996 if (phoneIdForRequest(networkRequest) == phoneId) { 1997 return true; 1998 } 1999 } 2000 } 2001 return false; 2002 } 2003 } 2004