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