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