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; 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 28 import static java.util.Arrays.copyOf; 29 30 import android.compat.annotation.UnsupportedAppUsage; 31 import android.content.BroadcastReceiver; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.net.ConnectivityManager; 36 import android.net.MatchAllNetworkSpecifier; 37 import android.net.Network; 38 import android.net.NetworkCapabilities; 39 import android.net.NetworkFactory; 40 import android.net.NetworkRequest; 41 import android.net.NetworkSpecifier; 42 import android.net.TelephonyNetworkSpecifier; 43 import android.os.AsyncResult; 44 import android.os.Handler; 45 import android.os.Looper; 46 import android.os.Message; 47 import android.os.PersistableBundle; 48 import android.os.Registrant; 49 import android.os.RegistrantList; 50 import android.os.RemoteException; 51 import android.telephony.CarrierConfigManager; 52 import android.telephony.PhoneCapability; 53 import android.telephony.PhoneStateListener; 54 import android.telephony.SubscriptionManager; 55 import android.telephony.TelephonyManager; 56 import android.telephony.TelephonyRegistryManager; 57 import android.telephony.data.ApnSetting; 58 import android.util.LocalLog; 59 60 import com.android.internal.annotations.VisibleForTesting; 61 import com.android.internal.telephony.dataconnection.ApnConfigTypeRepository; 62 import com.android.internal.telephony.dataconnection.DcRequest; 63 import com.android.internal.telephony.metrics.TelephonyMetrics; 64 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent; 65 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch; 66 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch; 67 import com.android.internal.util.IndentingPrintWriter; 68 import com.android.telephony.Rlog; 69 70 import java.io.FileDescriptor; 71 import java.io.PrintWriter; 72 import java.util.ArrayList; 73 import java.util.Calendar; 74 import java.util.Collections; 75 import java.util.List; 76 import java.util.concurrent.CompletableFuture; 77 78 /** 79 * Utility singleton to monitor subscription changes and incoming NetworkRequests 80 * and determine which phone/phones are active. 81 * 82 * Manages the ALLOW_DATA calls to modems and notifies phones about changes to 83 * the active phones. Note we don't wait for data attach (which may not happen anyway). 84 */ 85 public class PhoneSwitcher extends Handler { 86 private static final String LOG_TAG = "PhoneSwitcher"; 87 protected static final boolean VDBG = false; 88 89 private static final int DEFAULT_NETWORK_CHANGE_TIMEOUT_MS = 5000; 90 private static final int MODEM_COMMAND_RETRY_PERIOD_MS = 5000; 91 // After the emergency call ends, wait for a few seconds to see if we enter ECBM before starting 92 // the countdown to remove the emergency DDS override. 93 @VisibleForTesting 94 // not final for testing. 95 public static int ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 5000; 96 // Wait for a few seconds after the override request comes in to receive the outgoing call 97 // event. If it does not happen before the timeout specified, cancel the override. 98 @VisibleForTesting 99 public static int DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 5000; 100 101 // If there are no subscriptions in a device, then the phone to be used for emergency should 102 // always be the "first" phone. 103 private static final int DEFAULT_EMERGENCY_PHONE_ID = 0; 104 105 /** 106 * Container for an ongoing request to override the DDS in the context of an ongoing emergency 107 * call to allow for carrier specific operations, such as provide SUPL updates during or after 108 * the emergency call, since some modems do not support these operations on the non DDS. 109 */ 110 private static final class EmergencyOverrideRequest { 111 /* The Phone ID that the DDS should be set to. */ 112 int mPhoneId = INVALID_PHONE_INDEX; 113 /* The time after the emergency call ends that the DDS should be overridden for. */ 114 int mGnssOverrideTimeMs = -1; 115 /* A callback to the requester notifying them if the initial call to the modem to override 116 * the DDS was successful. 117 */ 118 CompletableFuture<Boolean> mOverrideCompleteFuture; 119 /* In the special case that the device goes into emergency callback mode after the emergency 120 * call ends, keep the override until ECM finishes and then start the mGnssOverrideTimeMs 121 * timer to leave DDS override. 122 */ 123 boolean mRequiresEcmFinish = false; 124 125 /* 126 * Keeps track of whether or not this request has already serviced the outgoing emergency 127 * call. Once finished, do not delay for any other calls. 128 */ 129 boolean mPendingOriginatingCall = true; 130 131 /** 132 * @return true if there is a pending override complete callback. 133 */ isCallbackAvailable()134 boolean isCallbackAvailable() { 135 return mOverrideCompleteFuture != null; 136 } 137 138 /** 139 * Send the override complete callback the result of setting the DDS to the new value. 140 */ sendOverrideCompleteCallbackResultAndClear(boolean result)141 void sendOverrideCompleteCallbackResultAndClear(boolean result) { 142 if (isCallbackAvailable()) { 143 mOverrideCompleteFuture.complete(result); 144 mOverrideCompleteFuture = null; 145 } 146 } 147 148 149 @Override toString()150 public String toString() { 151 return String.format("EmergencyOverrideRequest: [phoneId= %d, overrideMs= %d," 152 + " hasCallback= %b, ecmFinishStatus= %b]", mPhoneId, mGnssOverrideTimeMs, 153 isCallbackAvailable(), mRequiresEcmFinish); 154 } 155 } 156 157 protected final List<DcRequest> mPrioritizedDcRequests = new ArrayList<>(); 158 protected final RegistrantList mActivePhoneRegistrants; 159 protected final SubscriptionController mSubscriptionController; 160 protected final Context mContext; 161 private final LocalLog mLocalLog; 162 protected PhoneState[] mPhoneStates; 163 protected int[] mPhoneSubscriptions; 164 @VisibleForTesting 165 protected final CellularNetworkValidator mValidator; 166 private int mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 167 private boolean mPendingSwitchNeedValidation; 168 @VisibleForTesting 169 public final CellularNetworkValidator.ValidationCallback mValidationCallback = 170 new CellularNetworkValidator.ValidationCallback() { 171 @Override 172 public void onValidationDone(boolean validated, int subId) { 173 Message.obtain(PhoneSwitcher.this, 174 EVENT_NETWORK_VALIDATION_DONE, subId, validated ? 1 : 0).sendToTarget(); 175 } 176 177 @Override 178 public void onNetworkAvailable(Network network, int subId) { 179 Message.obtain(PhoneSwitcher.this, 180 EVENT_NETWORK_AVAILABLE, subId, 0, network).sendToTarget(); 181 182 } 183 }; 184 185 @UnsupportedAppUsage 186 // How many phones (correspondingly logical modems) are allowed for PS attach. This is used 187 // when we specifically use setDataAllowed to initiate on-demand PS(data) attach for each phone. 188 protected int mMaxDataAttachModemCount; 189 // Local cache of TelephonyManager#getActiveModemCount(). 1 if in single SIM mode, 2 if in dual 190 // SIM mode. 191 protected int mActiveModemCount; 192 protected static PhoneSwitcher sPhoneSwitcher = null; 193 194 // Which primary (non-opportunistic) subscription is set as data subscription among all primary 195 // subscriptions. This value usually comes from user setting, and it's the subscription used for 196 // Internet data if mOpptDataSubId is not set. 197 protected int mPrimaryDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 198 199 // mOpptDataSubId must be an active subscription. If it's set, it overrides mPrimaryDataSubId 200 // to be used for Internet data. 201 private int mOpptDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 202 203 // The phone ID that has an active voice call. If set, and its mobile data setting is on, 204 // it will become the mPreferredDataPhoneId. 205 protected int mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX; 206 207 @VisibleForTesting 208 // It decides: 209 // 1. In modem layer, which modem is DDS (preferred to have data traffic on) 210 // 2. In TelephonyNetworkFactory, which subscription will apply default network requests, which 211 // are requests without specifying a subId. 212 // Corresponding phoneId after considering mOpptDataSubId, mPrimaryDataSubId and 213 // mPhoneIdInVoiceCall above. 214 protected int mPreferredDataPhoneId = SubscriptionManager.INVALID_PHONE_INDEX; 215 216 // Subscription ID corresponds to mPreferredDataPhoneId. 217 protected int mPreferredDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 218 219 // If non-null, An emergency call is about to be started, is ongoing, or has just ended and we 220 // are overriding the DDS. 221 // Internal state, should ONLY be accessed/modified inside of the handler. 222 private EmergencyOverrideRequest mEmergencyOverride; 223 224 private ISetOpportunisticDataCallback mSetOpptSubCallback; 225 226 private static final int EVENT_PRIMARY_DATA_SUB_CHANGED = 101; 227 protected static final int EVENT_SUBSCRIPTION_CHANGED = 102; 228 private static final int EVENT_REQUEST_NETWORK = 103; 229 private static final int EVENT_RELEASE_NETWORK = 104; 230 // ECBM has started/ended. If we just ended an emergency call and mEmergencyOverride is not 231 // null, we will wait for EVENT_EMERGENCY_TOGGLE again with ECBM ending to send the message 232 // EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE to remove the override after the mEmergencyOverride 233 // override timer ends. 234 private static final int EVENT_EMERGENCY_TOGGLE = 105; 235 private static final int EVENT_RADIO_CAPABILITY_CHANGED = 106; 236 private static final int EVENT_OPPT_DATA_SUB_CHANGED = 107; 237 private static final int EVENT_RADIO_AVAILABLE = 108; 238 // A call has either started or ended. If an emergency ended and DDS is overridden using 239 // mEmergencyOverride, start the countdown to remove the override using the message 240 // EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE. The only exception to this is if the device moves to 241 // ECBM, which is detected by EVENT_EMERGENCY_TOGGLE. 242 @VisibleForTesting 243 public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 109; 244 private static final int EVENT_NETWORK_VALIDATION_DONE = 110; 245 private static final int EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK = 111; 246 private static final int EVENT_MODEM_COMMAND_DONE = 112; 247 private static final int EVENT_MODEM_COMMAND_RETRY = 113; 248 @VisibleForTesting 249 public static final int EVENT_DATA_ENABLED_CHANGED = 114; 250 // An emergency call is about to be originated and requires the DDS to be overridden. 251 // Uses EVENT_PRECISE_CALL_STATE_CHANGED message to start countdown to finish override defined 252 // in mEmergencyOverride. If EVENT_PRECISE_CALL_STATE_CHANGED does not come in 253 // DEFAULT_DATA_OVERRIDE_TIMEOUT_MS milliseconds, then the override will be removed. 254 private static final int EVENT_OVERRIDE_DDS_FOR_EMERGENCY = 115; 255 // If it exists, remove the current mEmergencyOverride DDS override. 256 private static final int EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE = 116; 257 // If it exists, remove the current mEmergencyOverride DDS override. 258 @VisibleForTesting 259 public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 117; 260 private static final int EVENT_NETWORK_AVAILABLE = 118; 261 262 // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's 263 // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse 264 // will be either HAL_COMMAND_ALLOW_DATA or HAL_COMMAND_ALLOW_DATA or HAL_COMMAND_UNKNOWN. 265 protected static final int HAL_COMMAND_UNKNOWN = 0; 266 protected static final int HAL_COMMAND_ALLOW_DATA = 1; 267 protected static final int HAL_COMMAND_PREFERRED_DATA = 2; 268 protected int mHalCommandToUse = HAL_COMMAND_UNKNOWN; 269 270 protected RadioConfig mRadioConfig; 271 272 private final static int MAX_LOCAL_LOG_LINES = 30; 273 274 // Default timeout value of network validation in millisecond. 275 private final static int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000; 276 277 private Boolean mHasRegisteredDefaultNetworkChangeCallback = false; 278 279 private ConnectivityManager mConnectivityManager; 280 281 private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback { 282 public int mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 283 public int mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; 284 @Override onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)285 public void onCapabilitiesChanged(Network network, 286 NetworkCapabilities networkCapabilities) { 287 if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR) 288 && SubscriptionManager.isValidSubscriptionId(mExpectedSubId) 289 && mExpectedSubId == getSubIdFromNetworkSpecifier( 290 networkCapabilities.getNetworkSpecifier())) { 291 logDataSwitchEvent( 292 mExpectedSubId, 293 TelephonyEvent.EventState.EVENT_STATE_END, 294 mSwitchReason); 295 removeDefaultNetworkChangeCallback(); 296 } 297 } 298 } 299 300 private final DefaultNetworkCallback mDefaultNetworkCallback = new DefaultNetworkCallback(); 301 302 /** 303 * Method to get singleton instance. 304 */ getInstance()305 public static PhoneSwitcher getInstance() { 306 return sPhoneSwitcher; 307 } 308 309 /** 310 * Method to create singleton instance. 311 */ make(int maxDataAttachModemCount, Context context, Looper looper)312 public static PhoneSwitcher make(int maxDataAttachModemCount, Context context, Looper looper) { 313 if (sPhoneSwitcher == null) { 314 sPhoneSwitcher = new PhoneSwitcher(maxDataAttachModemCount, context, looper); 315 } 316 317 return sPhoneSwitcher; 318 } 319 isPhoneInVoiceCallChanged()320 private boolean isPhoneInVoiceCallChanged() { 321 int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall; 322 // If there's no active call, the value will become INVALID_PHONE_INDEX 323 // and internet data will be switched back to system selected or user selected 324 // subscription. 325 mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX; 326 for (Phone phone : PhoneFactory.getPhones()) { 327 if (isPhoneInVoiceCall(phone) || isPhoneInVoiceCall(phone.getImsPhone())) { 328 mPhoneIdInVoiceCall = phone.getPhoneId(); 329 break; 330 } 331 } 332 333 if (mPhoneIdInVoiceCall != oldPhoneIdInVoiceCall) { 334 log("isPhoneInVoiceCallChanged from phoneId " + oldPhoneIdInVoiceCall 335 + " to phoneId " + mPhoneIdInVoiceCall); 336 return true; 337 } else { 338 return false; 339 } 340 } 341 342 @VisibleForTesting PhoneSwitcher(int maxActivePhones, Context context, Looper looper)343 public PhoneSwitcher(int maxActivePhones, Context context, Looper looper) { 344 super(looper); 345 mContext = context; 346 mActiveModemCount = getTm().getActiveModemCount(); 347 mPhoneSubscriptions = new int[mActiveModemCount]; 348 mPhoneStates = new PhoneState[mActiveModemCount]; 349 mMaxDataAttachModemCount = maxActivePhones; 350 mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES); 351 352 mSubscriptionController = SubscriptionController.getInstance(); 353 mRadioConfig = RadioConfig.getInstance(mContext); 354 mValidator = CellularNetworkValidator.getInstance(); 355 356 mActivePhoneRegistrants = new RegistrantList(); 357 for (int i = 0; i < mActiveModemCount; i++) { 358 mPhoneStates[i] = new PhoneState(); 359 if (PhoneFactory.getPhone(i) != null) { 360 PhoneFactory.getPhone(i).registerForEmergencyCallToggle( 361 this, EVENT_EMERGENCY_TOGGLE, null); 362 // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone. 363 PhoneFactory.getPhone(i).registerForPreciseCallStateChanged( 364 this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 365 if (PhoneFactory.getPhone(i).getImsPhone() != null) { 366 PhoneFactory.getPhone(i).getImsPhone().registerForPreciseCallStateChanged( 367 this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 368 } 369 PhoneFactory.getPhone(i).getDataEnabledSettings().registerForDataEnabledChanged( 370 this, EVENT_DATA_ENABLED_CHANGED, null); 371 } 372 } 373 374 if (mActiveModemCount > 0) { 375 PhoneFactory.getPhone(0).mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 376 } 377 378 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 379 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 380 telephonyRegistryManager.addOnSubscriptionsChangedListener( 381 mSubscriptionsChangedListener, mSubscriptionsChangedListener.getHandlerExecutor()); 382 383 mConnectivityManager = 384 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 385 386 mContext.registerReceiver(mDefaultDataChangedReceiver, 387 new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)); 388 389 PhoneConfigurationManager.registerForMultiSimConfigChange( 390 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 391 392 NetworkCapabilities netCap = new NetworkCapabilities(); 393 netCap.addTransportType(TRANSPORT_CELLULAR); 394 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 395 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL); 396 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); 397 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA); 398 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); 399 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS); 400 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IA); 401 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS); 402 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP); 403 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS); 404 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 405 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 406 netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MCX); 407 netCap.setNetworkSpecifier(new MatchAllNetworkSpecifier()); 408 409 NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context, 410 netCap, this); 411 // we want to see all requests 412 networkFactory.setScoreFilter(101); 413 networkFactory.register(); 414 415 log("PhoneSwitcher started"); 416 } 417 418 private final BroadcastReceiver mDefaultDataChangedReceiver = new BroadcastReceiver() { 419 @Override 420 public void onReceive(Context context, Intent intent) { 421 Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PRIMARY_DATA_SUB_CHANGED); 422 msg.sendToTarget(); 423 } 424 }; 425 426 private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener = 427 new SubscriptionManager.OnSubscriptionsChangedListener() { 428 @Override 429 public void onSubscriptionsChanged() { 430 Message msg = PhoneSwitcher.this.obtainMessage(EVENT_SUBSCRIPTION_CHANGED); 431 msg.sendToTarget(); 432 } 433 }; 434 435 @Override handleMessage(Message msg)436 public void handleMessage(Message msg) { 437 switch (msg.what) { 438 case EVENT_SUBSCRIPTION_CHANGED: { 439 onEvaluate(REQUESTS_UNCHANGED, "subChanged"); 440 break; 441 } 442 case EVENT_PRIMARY_DATA_SUB_CHANGED: { 443 if (onEvaluate(REQUESTS_UNCHANGED, "primary data subId changed")) { 444 logDataSwitchEvent(mPreferredDataSubId, 445 TelephonyEvent.EventState.EVENT_STATE_START, 446 DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); 447 registerDefaultNetworkChangeCallback(mPreferredDataSubId, 448 DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL); 449 } 450 break; 451 } 452 case EVENT_REQUEST_NETWORK: { 453 onRequestNetwork((NetworkRequest)msg.obj); 454 break; 455 } 456 case EVENT_RELEASE_NETWORK: { 457 onReleaseNetwork((NetworkRequest)msg.obj); 458 break; 459 } 460 case EVENT_EMERGENCY_TOGGLE: { 461 boolean isInEcm = isInEmergencyCallbackMode(); 462 if (mEmergencyOverride != null) { 463 log("Emergency override - ecbm status = " + isInEcm); 464 if (isInEcm) { 465 // The device has gone into ECBM. Wait until it's out. 466 removeMessages(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 467 mEmergencyOverride.mRequiresEcmFinish = true; 468 } else if (mEmergencyOverride.mRequiresEcmFinish) { 469 // we have exited ECM! Start the timer to exit DDS override. 470 Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 471 sendMessageDelayed(msg2, mEmergencyOverride.mGnssOverrideTimeMs); 472 } 473 } 474 onEvaluate(REQUESTS_CHANGED, "emergencyToggle"); 475 break; 476 } 477 case EVENT_RADIO_CAPABILITY_CHANGED: { 478 final int phoneId = msg.arg1; 479 sendRilCommands(phoneId); 480 break; 481 } 482 case EVENT_OPPT_DATA_SUB_CHANGED: { 483 int subId = msg.arg1; 484 boolean needValidation = (msg.arg2 == 1); 485 ISetOpportunisticDataCallback callback = 486 (ISetOpportunisticDataCallback) msg.obj; 487 setOpportunisticDataSubscription(subId, needValidation, callback); 488 break; 489 } 490 case EVENT_RADIO_AVAILABLE: { 491 updateHalCommandToUse(); 492 onEvaluate(REQUESTS_UNCHANGED, "EVENT_RADIO_AVAILABLE"); 493 break; 494 } 495 case EVENT_PRECISE_CALL_STATE_CHANGED: { 496 // If the phoneId in voice call didn't change, do nothing. 497 if (!isPhoneInVoiceCallChanged()) break; 498 499 // Only handle this event if we are currently waiting for the emergency call 500 // associated with the override request to start or end. 501 if (mEmergencyOverride != null && mEmergencyOverride.mPendingOriginatingCall) { 502 removeMessages(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 503 if (mPhoneIdInVoiceCall == SubscriptionManager.INVALID_PHONE_INDEX) { 504 // not in a call anymore. 505 Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 506 sendMessageDelayed(msg2, mEmergencyOverride.mGnssOverrideTimeMs 507 + ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS); 508 // Do not extend the emergency override by waiting for other calls to end. 509 // If it needs to be extended, a new request will come in and replace the 510 // current override. 511 mEmergencyOverride.mPendingOriginatingCall = false; 512 } 513 } 514 } 515 // fall through 516 case EVENT_DATA_ENABLED_CHANGED: 517 if (onEvaluate(REQUESTS_UNCHANGED, "EVENT_PRECISE_CALL_STATE_CHANGED")) { 518 logDataSwitchEvent(mPreferredDataSubId, 519 TelephonyEvent.EventState.EVENT_STATE_START, 520 DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); 521 registerDefaultNetworkChangeCallback(mPreferredDataSubId, 522 DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL); 523 } 524 break; 525 case EVENT_NETWORK_VALIDATION_DONE: { 526 int subId = msg.arg1; 527 boolean passed = (msg.arg2 == 1); 528 onValidationDone(subId, passed); 529 break; 530 } 531 case EVENT_NETWORK_AVAILABLE: { 532 int subId = msg.arg1; 533 Network network = (Network) msg.obj; 534 onNetworkAvailable(subId, network); 535 break; 536 } 537 case EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK: { 538 removeDefaultNetworkChangeCallback(); 539 break; 540 } 541 case EVENT_MODEM_COMMAND_DONE: { 542 AsyncResult ar = (AsyncResult) msg.obj; 543 boolean commandSuccess = ar != null && ar.exception == null; 544 if (mEmergencyOverride != null) { 545 log("Emergency override result sent = " + commandSuccess); 546 mEmergencyOverride.sendOverrideCompleteCallbackResultAndClear(commandSuccess); 547 // Do not retry , as we do not allow changes in onEvaluate during an emergency 548 // call. When the call ends, we will start the countdown to remove the override. 549 } else if (!commandSuccess) { 550 int phoneId = (int) ar.userObj; 551 log("Modem command failed. with exception " + ar.exception); 552 sendMessageDelayed(Message.obtain(this, EVENT_MODEM_COMMAND_RETRY, 553 phoneId), MODEM_COMMAND_RETRY_PERIOD_MS); 554 } 555 break; 556 } 557 case EVENT_MODEM_COMMAND_RETRY: { 558 int phoneId = (int) msg.obj; 559 log("Resend modem command on phone " + phoneId); 560 sendRilCommands(phoneId); 561 break; 562 } 563 case EVENT_OVERRIDE_DDS_FOR_EMERGENCY: { 564 EmergencyOverrideRequest req = (EmergencyOverrideRequest) msg.obj; 565 if (mEmergencyOverride != null) { 566 // If an override request comes in for a different phone ID than what is already 567 // being overridden, ignore. We should not try to switch DDS while already 568 // waiting for SUPL. 569 if (mEmergencyOverride.mPhoneId != req.mPhoneId) { 570 log("emergency override requested for phone id " + req.mPhoneId + " when " 571 + "there is already an override in place for phone id " 572 + mEmergencyOverride.mPhoneId + ". Ignoring."); 573 if (req.isCallbackAvailable()) { 574 // Send failed result 575 req.mOverrideCompleteFuture.complete(false); 576 } 577 break; 578 } else { 579 if (mEmergencyOverride.isCallbackAvailable()) { 580 // Unblock any waiting overrides if a new request comes in before the 581 // previous one is processed. 582 mEmergencyOverride.mOverrideCompleteFuture.complete(false); 583 } 584 } 585 mEmergencyOverride = req; 586 } else { 587 mEmergencyOverride = req; 588 } 589 590 log("new emergency override - " + mEmergencyOverride); 591 // a new request has been created, remove any previous override complete scheduled. 592 removeMessages(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 593 Message msg2 = obtainMessage(EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE); 594 // Make sure that if we never get an incall indication that we remove the override. 595 sendMessageDelayed(msg2, DEFAULT_DATA_OVERRIDE_TIMEOUT_MS); 596 // Wait for call to end and EVENT_PRECISE_CALL_STATE_CHANGED to be called, then 597 // start timer to remove DDS emergency override. 598 if (!onEvaluate(REQUESTS_UNCHANGED, "emer_override_dds")) { 599 // Nothing changed as a result of override, so no modem command was sent. Treat 600 // as success. 601 mEmergencyOverride.sendOverrideCompleteCallbackResultAndClear(true); 602 // Do not clear mEmergencyOverride here, as we still want to keep the override 603 // active for the time specified in case the user tries to switch default data. 604 } 605 break; 606 } 607 case EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE: { 608 log("Emergency override removed - " + mEmergencyOverride); 609 mEmergencyOverride = null; 610 onEvaluate(REQUESTS_UNCHANGED, "emer_rm_override_dds"); 611 break; 612 } 613 case EVENT_MULTI_SIM_CONFIG_CHANGED: { 614 int activeModemCount = (int) ((AsyncResult) msg.obj).result; 615 onMultiSimConfigChanged(activeModemCount); 616 break; 617 } 618 } 619 } 620 onMultiSimConfigChanged(int activeModemCount)621 private synchronized void onMultiSimConfigChanged(int activeModemCount) { 622 // No change. 623 if (mActiveModemCount == activeModemCount) return; 624 int oldActiveModemCount = mActiveModemCount; 625 mActiveModemCount = activeModemCount; 626 627 mPhoneSubscriptions = copyOf(mPhoneSubscriptions, mActiveModemCount); 628 mPhoneStates = copyOf(mPhoneStates, mActiveModemCount); 629 630 // Single SIM -> dual SIM switch. 631 for (int phoneId = oldActiveModemCount; phoneId < mActiveModemCount; phoneId++) { 632 mPhoneStates[phoneId] = new PhoneState(); 633 Phone phone = PhoneFactory.getPhone(phoneId); 634 if (phone == null) continue; 635 636 phone.registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null); 637 // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone. 638 phone.registerForPreciseCallStateChanged(this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 639 if (phone.getImsPhone() != null) { 640 phone.getImsPhone().registerForPreciseCallStateChanged( 641 this, EVENT_PRECISE_CALL_STATE_CHANGED, null); 642 } 643 phone.getDataEnabledSettings().registerForDataEnabledChanged( 644 this, EVENT_DATA_ENABLED_CHANGED, null); 645 } 646 } 647 isInEmergencyCallbackMode()648 private boolean isInEmergencyCallbackMode() { 649 for (Phone p : PhoneFactory.getPhones()) { 650 if (p == null) continue; 651 if (p.isInEcm()) return true; 652 Phone imsPhone = p.getImsPhone(); 653 if (imsPhone != null && imsPhone.isInEcm()) { 654 return true; 655 } 656 } 657 return false; 658 } 659 660 private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory { 661 private final PhoneSwitcher mPhoneSwitcher; PhoneSwitcherNetworkRequestListener(Looper l, Context c, NetworkCapabilities nc, PhoneSwitcher ps)662 public PhoneSwitcherNetworkRequestListener (Looper l, Context c, 663 NetworkCapabilities nc, PhoneSwitcher ps) { 664 super(l, c, "PhoneSwitcherNetworkRequstListener", nc); 665 mPhoneSwitcher = ps; 666 } 667 668 @Override needNetworkFor(NetworkRequest networkRequest, int score)669 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 670 if (VDBG) log("needNetworkFor " + networkRequest + ", " + score); 671 Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK); 672 msg.obj = networkRequest; 673 msg.sendToTarget(); 674 } 675 676 @Override releaseNetworkFor(NetworkRequest networkRequest)677 protected void releaseNetworkFor(NetworkRequest networkRequest) { 678 if (VDBG) log("releaseNetworkFor " + networkRequest); 679 Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK); 680 msg.obj = networkRequest; 681 msg.sendToTarget(); 682 } 683 } 684 onRequestNetwork(NetworkRequest networkRequest)685 private void onRequestNetwork(NetworkRequest networkRequest) { 686 final DcRequest dcRequest = 687 DcRequest.create(networkRequest, createApnRepository(networkRequest)); 688 if (dcRequest != null) { 689 if (!mPrioritizedDcRequests.contains(dcRequest)) { 690 collectRequestNetworkMetrics(networkRequest); 691 mPrioritizedDcRequests.add(dcRequest); 692 Collections.sort(mPrioritizedDcRequests); 693 onEvaluate(REQUESTS_CHANGED, "netRequest"); 694 log("Added DcRequest, size: " + mPrioritizedDcRequests.size()); 695 } 696 } 697 } 698 onReleaseNetwork(NetworkRequest networkRequest)699 private void onReleaseNetwork(NetworkRequest networkRequest) { 700 final DcRequest dcRequest = 701 DcRequest.create(networkRequest, createApnRepository(networkRequest)); 702 if (dcRequest != null) { 703 if (mPrioritizedDcRequests.remove(dcRequest)) { 704 onEvaluate(REQUESTS_CHANGED, "netReleased"); 705 collectReleaseNetworkMetrics(networkRequest); 706 log("Removed DcRequest, size: " + mPrioritizedDcRequests.size()); 707 } 708 } 709 } 710 createApnRepository(NetworkRequest networkRequest)711 private ApnConfigTypeRepository createApnRepository(NetworkRequest networkRequest) { 712 int phoneIdForRequest = phoneIdForRequest(networkRequest); 713 int subId = mSubscriptionController.getSubIdUsingPhoneId(phoneIdForRequest); 714 CarrierConfigManager configManager = (CarrierConfigManager) mContext 715 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 716 717 PersistableBundle carrierConfig; 718 if (configManager != null) { 719 carrierConfig = configManager.getConfigForSubId(subId); 720 } else { 721 carrierConfig = null; 722 } 723 return new ApnConfigTypeRepository(carrierConfig); 724 } 725 removeDefaultNetworkChangeCallback()726 private void removeDefaultNetworkChangeCallback() { 727 removeMessages(EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK); 728 mDefaultNetworkCallback.mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 729 mDefaultNetworkCallback.mSwitchReason = 730 TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN; 731 mConnectivityManager.unregisterNetworkCallback(mDefaultNetworkCallback); 732 } 733 registerDefaultNetworkChangeCallback(int expectedSubId, int reason)734 private void registerDefaultNetworkChangeCallback(int expectedSubId, int reason) { 735 mDefaultNetworkCallback.mExpectedSubId = expectedSubId; 736 mDefaultNetworkCallback.mSwitchReason = reason; 737 mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this); 738 sendMessageDelayed( 739 obtainMessage(EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK), 740 DEFAULT_NETWORK_CHANGE_TIMEOUT_MS); 741 } 742 collectRequestNetworkMetrics(NetworkRequest networkRequest)743 private void collectRequestNetworkMetrics(NetworkRequest networkRequest) { 744 // Request network for MMS will temporary disable the network on default data subscription, 745 // this only happen on multi-sim device. 746 if (mActiveModemCount > 1 && networkRequest.hasCapability( 747 NetworkCapabilities.NET_CAPABILITY_MMS)) { 748 OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch(); 749 onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS; 750 onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_START; 751 TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch); 752 } 753 } 754 collectReleaseNetworkMetrics(NetworkRequest networkRequest)755 private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) { 756 // Release network for MMS will recover the network on default data subscription, this only 757 // happen on multi-sim device. 758 if (mActiveModemCount > 1 && networkRequest.hasCapability( 759 NetworkCapabilities.NET_CAPABILITY_MMS)) { 760 OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch(); 761 onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS; 762 onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_END; 763 TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch); 764 } 765 } 766 getTm()767 private TelephonyManager getTm() { 768 return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 769 } 770 771 protected static final boolean REQUESTS_CHANGED = true; 772 protected static final boolean REQUESTS_UNCHANGED = false; 773 /** 774 * Re-evaluate things. Do nothing if nothing's changed. 775 * 776 * Otherwise, go through the requests in priority order adding their phone until we've added up 777 * to the max allowed. Then go through shutting down phones that aren't in the active phone 778 * list. Finally, activate all phones in the active phone list. 779 * 780 * @return {@code True} if the default data subscription need to be changed. 781 */ onEvaluate(boolean requestsChanged, String reason)782 protected boolean onEvaluate(boolean requestsChanged, String reason) { 783 StringBuilder sb = new StringBuilder(reason); 784 785 // If we use HAL_COMMAND_PREFERRED_DATA, 786 boolean diffDetected = mHalCommandToUse != HAL_COMMAND_PREFERRED_DATA && requestsChanged; 787 788 // Check if user setting of default non-opportunistic data sub is changed. 789 final int primaryDataSubId = mSubscriptionController.getDefaultDataSubId(); 790 if (primaryDataSubId != mPrimaryDataSubId) { 791 sb.append(" mPrimaryDataSubId ").append(mPrimaryDataSubId).append("->") 792 .append(primaryDataSubId); 793 mPrimaryDataSubId = primaryDataSubId; 794 } 795 796 // Check to see if there is any active subscription on any phone 797 boolean hasAnyActiveSubscription = false; 798 799 // Check if phoneId to subId mapping is changed. 800 for (int i = 0; i < mActiveModemCount; i++) { 801 int sub = mSubscriptionController.getSubIdUsingPhoneId(i); 802 803 if (SubscriptionManager.isValidSubscriptionId(sub)) hasAnyActiveSubscription = true; 804 805 if (sub != mPhoneSubscriptions[i]) { 806 sb.append(" phone[").append(i).append("] ").append(mPhoneSubscriptions[i]); 807 sb.append("->").append(sub); 808 mPhoneSubscriptions[i] = sub; 809 diffDetected = true; 810 } 811 } 812 813 if (!hasAnyActiveSubscription) { 814 transitionToEmergencyPhone(); 815 } else { 816 if (VDBG) log("Found an active subscription"); 817 } 818 819 // Check if phoneId for preferred data is changed. 820 int oldPreferredDataPhoneId = mPreferredDataPhoneId; 821 822 // When there are no subscriptions, the preferred data phone ID is invalid, but we want 823 // to keep a valid phoneId for Emergency, so skip logic that updates for preferred data 824 // phone ID. Ideally there should be a single set of checks that evaluate the correct 825 // phoneId on a service-by-service basis (EIMS being one), but for now... just bypass 826 // this logic in the no-SIM case. 827 if (hasAnyActiveSubscription) updatePreferredDataPhoneId(); 828 829 if (oldPreferredDataPhoneId != mPreferredDataPhoneId) { 830 sb.append(" preferred phoneId ").append(oldPreferredDataPhoneId) 831 .append("->").append(mPreferredDataPhoneId); 832 diffDetected = true; 833 } 834 835 if (diffDetected) { 836 log("evaluating due to " + sb.toString()); 837 if (mHalCommandToUse == HAL_COMMAND_PREFERRED_DATA) { 838 // With HAL_COMMAND_PREFERRED_DATA, all phones are assumed to allow PS attach. 839 // So marking all phone as active, and the phone with mPreferredDataPhoneId 840 // will send radioConfig command. 841 for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) { 842 mPhoneStates[phoneId].active = true; 843 } 844 sendRilCommands(mPreferredDataPhoneId); 845 } else { 846 List<Integer> newActivePhones = new ArrayList<Integer>(); 847 848 /** 849 * If all phones can have PS attached, activate all. 850 * Otherwise, choose to activate phones according to requests. And 851 * if list is not full, add mPreferredDataPhoneId. 852 */ 853 if (mMaxDataAttachModemCount == mActiveModemCount) { 854 for (int i = 0; i < mMaxDataAttachModemCount; i++) { 855 newActivePhones.add(i); 856 } 857 } else { 858 // First try to activate phone in voice call. 859 if (mPhoneIdInVoiceCall != SubscriptionManager.INVALID_PHONE_INDEX) { 860 newActivePhones.add(mPhoneIdInVoiceCall); 861 } 862 863 if (newActivePhones.size() < mMaxDataAttachModemCount) { 864 for (DcRequest dcRequest : mPrioritizedDcRequests) { 865 int phoneIdForRequest = phoneIdForRequest(dcRequest.networkRequest); 866 if (phoneIdForRequest == INVALID_PHONE_INDEX) continue; 867 if (newActivePhones.contains(phoneIdForRequest)) continue; 868 newActivePhones.add(phoneIdForRequest); 869 if (newActivePhones.size() >= mMaxDataAttachModemCount) break; 870 } 871 } 872 873 if (newActivePhones.size() < mMaxDataAttachModemCount 874 && newActivePhones.contains(mPreferredDataPhoneId) 875 && SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) { 876 newActivePhones.add(mPreferredDataPhoneId); 877 } 878 } 879 880 if (VDBG) { 881 log("mPrimaryDataSubId = " + mPrimaryDataSubId); 882 log("mOpptDataSubId = " + mOpptDataSubId); 883 for (int i = 0; i < mActiveModemCount; i++) { 884 log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]"); 885 } 886 log(" newActivePhones:"); 887 for (Integer i : newActivePhones) log(" " + i); 888 } 889 890 for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) { 891 if (!newActivePhones.contains(phoneId)) { 892 deactivate(phoneId); 893 } 894 } 895 896 // only activate phones up to the limit 897 for (int phoneId : newActivePhones) { 898 activate(phoneId); 899 } 900 } 901 902 notifyPreferredDataSubIdChanged(); 903 904 // Notify all registrants. 905 mActivePhoneRegistrants.notifyRegistrants(); 906 } 907 return diffDetected; 908 } 909 910 protected static class PhoneState { 911 public volatile boolean active = false; 912 public long lastRequested = 0; 913 } 914 915 @UnsupportedAppUsage activate(int phoneId)916 protected void activate(int phoneId) { 917 switchPhone(phoneId, true); 918 } 919 920 @UnsupportedAppUsage deactivate(int phoneId)921 protected void deactivate(int phoneId) { 922 switchPhone(phoneId, false); 923 } 924 switchPhone(int phoneId, boolean active)925 private void switchPhone(int phoneId, boolean active) { 926 PhoneState state = mPhoneStates[phoneId]; 927 if (state.active == active) return; 928 state.active = active; 929 log((active ? "activate " : "deactivate ") + phoneId); 930 state.lastRequested = System.currentTimeMillis(); 931 sendRilCommands(phoneId); 932 } 933 934 /** 935 * Used when the modem may have been rebooted and we 936 * want to resend setDataAllowed or setPreferredDataSubscriptionId 937 */ onRadioCapChanged(int phoneId)938 public void onRadioCapChanged(int phoneId) { 939 if (!SubscriptionManager.isValidPhoneId(phoneId)) return; 940 Message msg = obtainMessage(EVENT_RADIO_CAPABILITY_CHANGED); 941 msg.arg1 = phoneId; 942 msg.sendToTarget(); 943 } 944 945 /** 946 * Switch the Default data for the context of an outgoing emergency call. 947 * 948 * In some cases, we need to try to switch the Default Data subscription before placing the 949 * emergency call on DSDS devices. This includes the following situation: 950 * - The modem does not support processing GNSS SUPL requests on the non-default data 951 * subscription. For some carriers that do not provide a control plane fallback mechanism, the 952 * SUPL request will be dropped and we will not be able to get the user's location for the 953 * emergency call. In this case, we need to swap default data temporarily. 954 * @param phoneId The phone to use to evaluate whether or not the default data should be moved 955 * to this subscription. 956 * @param overrideTimeSec The amount of time to override the default data setting for after the 957 * emergency call ends. 958 * @param dataSwitchResult A {@link CompletableFuture} to be called with a {@link Boolean} 959 * result when the default data switch has either completed (true) or 960 * failed (false). 961 */ overrideDefaultDataForEmergency(int phoneId, int overrideTimeSec, CompletableFuture<Boolean> dataSwitchResult)962 public void overrideDefaultDataForEmergency(int phoneId, int overrideTimeSec, 963 CompletableFuture<Boolean> dataSwitchResult) { 964 if (!SubscriptionManager.isValidPhoneId(phoneId)) return; 965 Message msg = obtainMessage(EVENT_OVERRIDE_DDS_FOR_EMERGENCY); 966 EmergencyOverrideRequest request = new EmergencyOverrideRequest(); 967 request.mPhoneId = phoneId; 968 request.mGnssOverrideTimeMs = overrideTimeSec * 1000; 969 request.mOverrideCompleteFuture = dataSwitchResult; 970 msg.obj = request; 971 msg.sendToTarget(); 972 } 973 sendRilCommands(int phoneId)974 protected void sendRilCommands(int phoneId) { 975 if (!SubscriptionManager.isValidPhoneId(phoneId)) return; 976 977 Message message = Message.obtain(this, EVENT_MODEM_COMMAND_DONE, phoneId); 978 if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) { 979 // Skip ALLOW_DATA for single SIM device 980 if (mActiveModemCount > 1) { 981 PhoneFactory.getPhone(phoneId).mCi.setDataAllowed(isPhoneActive(phoneId), message); 982 } 983 } else if (phoneId == mPreferredDataPhoneId) { 984 // Only setPreferredDataModem if the phoneId equals to current mPreferredDataPhoneId. 985 mRadioConfig.setPreferredDataModem(mPreferredDataPhoneId, message); 986 } 987 } 988 onPhoneCapabilityChangedInternal(PhoneCapability capability)989 private void onPhoneCapabilityChangedInternal(PhoneCapability capability) { 990 int newMaxDataAttachModemCount = TelephonyManager.getDefault() 991 .getNumberOfModemsWithSimultaneousDataConnections(); 992 if (mMaxDataAttachModemCount != newMaxDataAttachModemCount) { 993 mMaxDataAttachModemCount = newMaxDataAttachModemCount; 994 log("Max active phones changed to " + mMaxDataAttachModemCount); 995 onEvaluate(REQUESTS_UNCHANGED, "phoneCfgChanged"); 996 } 997 } 998 phoneIdForRequest(NetworkRequest netRequest)999 private int phoneIdForRequest(NetworkRequest netRequest) { 1000 int subId = getSubIdFromNetworkSpecifier(netRequest.getNetworkSpecifier()); 1001 1002 if (subId == DEFAULT_SUBSCRIPTION_ID) return mPreferredDataPhoneId; 1003 if (subId == INVALID_SUBSCRIPTION_ID) return INVALID_PHONE_INDEX; 1004 1005 int preferredDataSubId = (mPreferredDataPhoneId >= 0 1006 && mPreferredDataPhoneId < mActiveModemCount) 1007 ? mPhoneSubscriptions[mPreferredDataPhoneId] : INVALID_SUBSCRIPTION_ID; 1008 1009 // Currently we assume multi-SIM devices will only support one Internet PDN connection. So 1010 // if Internet PDN is established on the non-preferred phone, it will interrupt 1011 // Internet connection on the preferred phone. So we only accept Internet request with 1012 // preferred data subscription or no specified subscription. 1013 // One exception is, if it's restricted request (doesn't have NET_CAPABILITY_NOT_RESTRICTED) 1014 // it will be accepted, which is used temporary data usage from system. 1015 if (netRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 1016 && netRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 1017 && subId != preferredDataSubId && subId != mValidator.getSubIdInValidation()) { 1018 // Returning INVALID_PHONE_INDEX will result in netRequest not being handled. 1019 return INVALID_PHONE_INDEX; 1020 } 1021 1022 // Try to find matching phone ID. If it doesn't exist, we'll end up returning INVALID. 1023 int phoneId = INVALID_PHONE_INDEX; 1024 for (int i = 0; i < mActiveModemCount; i++) { 1025 if (mPhoneSubscriptions[i] == subId) { 1026 phoneId = i; 1027 break; 1028 } 1029 } 1030 return phoneId; 1031 } 1032 getSubIdFromNetworkSpecifier(NetworkSpecifier specifier)1033 protected int getSubIdFromNetworkSpecifier(NetworkSpecifier specifier) { 1034 if (specifier == null) { 1035 return DEFAULT_SUBSCRIPTION_ID; 1036 } 1037 if (specifier instanceof TelephonyNetworkSpecifier) { 1038 return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId(); 1039 } 1040 return INVALID_SUBSCRIPTION_ID; 1041 } 1042 getSubIdForDefaultNetworkRequests()1043 private int getSubIdForDefaultNetworkRequests() { 1044 if (mSubscriptionController.isActiveSubId(mOpptDataSubId)) { 1045 return mOpptDataSubId; 1046 } else { 1047 return mPrimaryDataSubId; 1048 } 1049 } 1050 1051 // This updates mPreferredDataPhoneId which decides which phone should handle default network 1052 // requests. updatePreferredDataPhoneId()1053 protected void updatePreferredDataPhoneId() { 1054 Phone voicePhone = findPhoneById(mPhoneIdInVoiceCall); 1055 if (mEmergencyOverride != null && findPhoneById(mEmergencyOverride.mPhoneId) != null) { 1056 // Override DDS for emergency even if user data is not enabled, since it is an 1057 // emergency. 1058 // TODO: Provide a notification to the user that metered data is currently being 1059 // used during this period. 1060 log("updatePreferredDataPhoneId: preferred data overridden for emergency." 1061 + " phoneId = " + mEmergencyOverride.mPhoneId); 1062 mPreferredDataPhoneId = mEmergencyOverride.mPhoneId; 1063 } else if (voicePhone != null && voicePhone.getDataEnabledSettings().isDataEnabled( 1064 ApnSetting.TYPE_DEFAULT)) { 1065 // If a phone is in call and user enabled its mobile data, we 1066 // should switch internet connection to it. Because the other modem 1067 // will lose data connection anyway. 1068 // TODO: validate network first. 1069 mPreferredDataPhoneId = mPhoneIdInVoiceCall; 1070 } else { 1071 int subId = getSubIdForDefaultNetworkRequests(); 1072 int phoneId = SubscriptionManager.INVALID_PHONE_INDEX; 1073 1074 if (SubscriptionManager.isUsableSubIdValue(subId)) { 1075 for (int i = 0; i < mActiveModemCount; i++) { 1076 if (mPhoneSubscriptions[i] == subId) { 1077 phoneId = i; 1078 break; 1079 } 1080 } 1081 } 1082 1083 mPreferredDataPhoneId = phoneId; 1084 } 1085 1086 mPreferredDataSubId = mSubscriptionController.getSubIdUsingPhoneId(mPreferredDataPhoneId); 1087 } 1088 transitionToEmergencyPhone()1089 protected void transitionToEmergencyPhone() { 1090 if (mActiveModemCount <= 0) { 1091 log("No phones: unable to reset preferred phone for emergency"); 1092 return; 1093 } 1094 1095 if (mPreferredDataPhoneId != DEFAULT_EMERGENCY_PHONE_ID) { 1096 log("No active subscriptions: resetting preferred phone to 0 for emergency"); 1097 mPreferredDataPhoneId = DEFAULT_EMERGENCY_PHONE_ID; 1098 } 1099 1100 if (mPreferredDataSubId != INVALID_SUBSCRIPTION_ID) { 1101 mPreferredDataSubId = INVALID_SUBSCRIPTION_ID; 1102 notifyPreferredDataSubIdChanged(); 1103 } 1104 } 1105 findPhoneById(final int phoneId)1106 private Phone findPhoneById(final int phoneId) { 1107 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1108 return null; 1109 } 1110 return PhoneFactory.getPhone(phoneId); 1111 } 1112 shouldApplyNetworkRequest( NetworkRequest networkRequest, int phoneId)1113 public synchronized boolean shouldApplyNetworkRequest( 1114 NetworkRequest networkRequest, int phoneId) { 1115 if (!SubscriptionManager.isValidPhoneId(phoneId)) return false; 1116 1117 // In any case, if phone state is inactive, don't apply the network request. 1118 if (!isPhoneActive(phoneId) || ( 1119 mSubscriptionController.getSubIdUsingPhoneId(phoneId) == INVALID_SUBSCRIPTION_ID 1120 && !isEmergencyNetworkRequest(networkRequest))) { 1121 return false; 1122 } 1123 1124 int phoneIdToHandle = phoneIdForRequest(networkRequest); 1125 1126 return phoneId == phoneIdToHandle; 1127 } 1128 isEmergencyNetworkRequest(NetworkRequest networkRequest)1129 boolean isEmergencyNetworkRequest(NetworkRequest networkRequest) { 1130 return networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS); 1131 } 1132 1133 @VisibleForTesting isPhoneActive(int phoneId)1134 protected boolean isPhoneActive(int phoneId) { 1135 if (phoneId >= mActiveModemCount) 1136 return false; 1137 return mPhoneStates[phoneId].active; 1138 } 1139 1140 /** 1141 * If preferred phone changes, or phone activation status changes, registrants 1142 * will be notified. 1143 */ registerForActivePhoneSwitch(Handler h, int what, Object o)1144 public void registerForActivePhoneSwitch(Handler h, int what, Object o) { 1145 Registrant r = new Registrant(h, what, o); 1146 mActivePhoneRegistrants.add(r); 1147 r.notifyRegistrant(); 1148 } 1149 unregisterForActivePhoneSwitch(Handler h)1150 public void unregisterForActivePhoneSwitch(Handler h) { 1151 mActivePhoneRegistrants.remove(h); 1152 } 1153 1154 /** 1155 * Set opportunistic data subscription. It's an indication to switch Internet data to this 1156 * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate 1157 * it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting 1158 * opportunistic data sub and switch data back to primary sub. 1159 * 1160 * @param subId the opportunistic data subscription to switch to. pass DEFAULT_SUBSCRIPTION_ID 1161 * if un-setting it. 1162 * @param needValidation whether Telephony will wait until the network is validated by 1163 * connectivity service before switching data to it. More details see 1164 * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. 1165 * @param callback Callback will be triggered once it succeeds or failed. 1166 * Pass null if don't care about the result. 1167 */ setOpportunisticDataSubscription(int subId, boolean needValidation, ISetOpportunisticDataCallback callback)1168 private void setOpportunisticDataSubscription(int subId, boolean needValidation, 1169 ISetOpportunisticDataCallback callback) { 1170 if (!mSubscriptionController.isActiveSubId(subId) 1171 && subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 1172 log("Can't switch data to inactive subId " + subId); 1173 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION); 1174 return; 1175 } 1176 1177 // Remove EVENT_NETWORK_VALIDATION_DONE. Don't handle validation result of previously subId 1178 // if queued. 1179 removeMessages(EVENT_NETWORK_VALIDATION_DONE); 1180 removeMessages(EVENT_NETWORK_AVAILABLE); 1181 1182 int subIdToValidate = (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) 1183 ? mPrimaryDataSubId : subId; 1184 1185 mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 1186 1187 if (mValidator.isValidating()) { 1188 mValidator.stopValidation(); 1189 sendSetOpptCallbackHelper(mSetOpptSubCallback, SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED); 1190 mSetOpptSubCallback = null; 1191 } 1192 1193 if (subId == mOpptDataSubId) { 1194 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS); 1195 return; 1196 } 1197 1198 logDataSwitchEvent(subId == DEFAULT_SUBSCRIPTION_ID ? mPrimaryDataSubId : subId, 1199 TelephonyEvent.EventState.EVENT_STATE_START, 1200 DataSwitch.Reason.DATA_SWITCH_REASON_CBRS); 1201 registerDefaultNetworkChangeCallback( 1202 subId == DEFAULT_SUBSCRIPTION_ID ? mPrimaryDataSubId : subId, 1203 DataSwitch.Reason.DATA_SWITCH_REASON_CBRS); 1204 1205 // If validation feature is not supported, set it directly. Otherwise, 1206 // start validation on the subscription first. 1207 if (!mValidator.isValidationFeatureSupported()) { 1208 setOpportunisticSubscriptionInternal(subId); 1209 sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS); 1210 return; 1211 } 1212 1213 // Even if needValidation is false, we still send request to validator. The reason is we 1214 // want to delay data switch until network is available on the target sub, to have a 1215 // smoothest transition possible. 1216 // In this case, even if data connection eventually failed in 2 seconds, we still 1217 // confirm the switch, to maximally respect the request. 1218 mPendingSwitchSubId = subIdToValidate; 1219 mPendingSwitchNeedValidation = needValidation; 1220 mSetOpptSubCallback = callback; 1221 long validationTimeout = getValidationTimeout(subIdToValidate, needValidation); 1222 mValidator.validate(subIdToValidate, validationTimeout, false, mValidationCallback); 1223 } 1224 getValidationTimeout(int subId, boolean needValidation)1225 private long getValidationTimeout(int subId, boolean needValidation) { 1226 if (!needValidation) return DEFAULT_VALIDATION_EXPIRATION_TIME; 1227 1228 long validationTimeout = DEFAULT_VALIDATION_EXPIRATION_TIME; 1229 CarrierConfigManager configManager = (CarrierConfigManager) 1230 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1231 if (configManager != null) { 1232 PersistableBundle b = configManager.getConfigForSubId(subId); 1233 if (b != null) { 1234 validationTimeout = b.getLong(KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG); 1235 } 1236 } 1237 return validationTimeout; 1238 } 1239 sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result)1240 private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) { 1241 if (callback == null) return; 1242 try { 1243 callback.onComplete(result); 1244 } catch (RemoteException exception) { 1245 log("RemoteException " + exception); 1246 } 1247 } 1248 1249 /** 1250 * Set opportunistic data subscription. 1251 */ setOpportunisticSubscriptionInternal(int subId)1252 private void setOpportunisticSubscriptionInternal(int subId) { 1253 if (mOpptDataSubId != subId) { 1254 mOpptDataSubId = subId; 1255 onEvaluate(REQUESTS_UNCHANGED, "oppt data subId changed"); 1256 } 1257 } 1258 confirmSwitch(int subId, boolean confirm)1259 private void confirmSwitch(int subId, boolean confirm) { 1260 log("confirmSwitch: subId " + subId + (confirm ? " confirmed." : " cancelled.")); 1261 int resultForCallBack; 1262 if (!mSubscriptionController.isActiveSubId(subId)) { 1263 log("confirmSwitch: subId " + subId + " is no longer active"); 1264 resultForCallBack = SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION; 1265 } else if (!confirm) { 1266 resultForCallBack = SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED; 1267 } else { 1268 if (mSubscriptionController.isOpportunistic(subId)) { 1269 setOpportunisticSubscriptionInternal(subId); 1270 } else { 1271 // Switching data back to primary subscription. 1272 setOpportunisticSubscriptionInternal(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); 1273 } 1274 resultForCallBack = SET_OPPORTUNISTIC_SUB_SUCCESS; 1275 } 1276 1277 // Trigger callback if needed 1278 sendSetOpptCallbackHelper(mSetOpptSubCallback, resultForCallBack); 1279 mSetOpptSubCallback = null; 1280 mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID; 1281 } 1282 onNetworkAvailable(int subId, Network network)1283 private void onNetworkAvailable(int subId, Network network) { 1284 log("onNetworkAvailable: on subId " + subId); 1285 // Do nothing unless pending switch matches target subId and it doesn't require 1286 // validation pass. 1287 if (mPendingSwitchSubId == INVALID_SUBSCRIPTION_ID || mPendingSwitchSubId != subId 1288 || mPendingSwitchNeedValidation) { 1289 return; 1290 } 1291 confirmSwitch(subId, true); 1292 } 1293 onValidationDone(int subId, boolean passed)1294 private void onValidationDone(int subId, boolean passed) { 1295 log("onValidationDone: " + (passed ? "passed" : "failed") + " on subId " + subId); 1296 if (mPendingSwitchSubId == INVALID_SUBSCRIPTION_ID || mPendingSwitchSubId != subId) return; 1297 1298 // If validation failed and mPendingSwitch.mNeedValidation is false, we still confirm 1299 // the switch. 1300 confirmSwitch(subId, passed || !mPendingSwitchNeedValidation); 1301 } 1302 1303 /** 1304 * Notify PhoneSwitcher to try to switch data to an opportunistic subscription. 1305 * 1306 * Set opportunistic data subscription. It's an indication to switch Internet data to this 1307 * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate 1308 * it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting 1309 * opportunistic data sub and switch data back to primary sub. 1310 * 1311 * @param subId the opportunistic data subscription to switch to. pass DEFAULT_SUBSCRIPTION_ID 1312 * if un-setting it. 1313 * @param needValidation whether Telephony will wait until the network is validated by 1314 * connectivity service before switching data to it. More details see 1315 * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. 1316 * @param callback Callback will be triggered once it succeeds or failed. 1317 * Pass null if don't care about the result. 1318 */ trySetOpportunisticDataSubscription(int subId, boolean needValidation, ISetOpportunisticDataCallback callback)1319 public void trySetOpportunisticDataSubscription(int subId, boolean needValidation, 1320 ISetOpportunisticDataCallback callback) { 1321 log("Try set opportunistic data subscription to subId " + subId 1322 + (needValidation ? " with " : " without ") + "validation"); 1323 PhoneSwitcher.this.obtainMessage(EVENT_OPPT_DATA_SUB_CHANGED, 1324 subId, needValidation ? 1 : 0, callback).sendToTarget(); 1325 } 1326 isPhoneInVoiceCall(Phone phone)1327 protected boolean isPhoneInVoiceCall(Phone phone) { 1328 if (phone == null) { 1329 return false; 1330 } 1331 1332 // A phone in voice call might trigger data being switched to it. 1333 // We only report true if its precise call state is ACTIVE, ALERTING or HOLDING. 1334 // The reason is data switching is interrupting, so we only switch when necessary and 1335 // acknowledged by the users. For incoming call, we don't switch until answered 1336 // (RINGING -> ACTIVE), for outgoing call we don't switch until call is connected 1337 // in network (DIALING -> ALERTING). 1338 return (phone.getForegroundCall().getState() == Call.State.ACTIVE 1339 || phone.getForegroundCall().getState() == Call.State.ALERTING 1340 || phone.getBackgroundCall().getState() == Call.State.HOLDING); 1341 } 1342 updateHalCommandToUse()1343 private void updateHalCommandToUse() { 1344 mHalCommandToUse = mRadioConfig.isSetPreferredDataCommandSupported() 1345 ? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA; 1346 } 1347 getOpportunisticDataSubscriptionId()1348 public int getOpportunisticDataSubscriptionId() { 1349 return mOpptDataSubId; 1350 } 1351 getPreferredDataPhoneId()1352 public int getPreferredDataPhoneId() { 1353 return mPreferredDataPhoneId; 1354 } 1355 1356 @UnsupportedAppUsage log(String l)1357 protected void log(String l) { 1358 Rlog.d(LOG_TAG, l); 1359 mLocalLog.log(l); 1360 } 1361 logDataSwitchEvent(int subId, int state, int reason)1362 private void logDataSwitchEvent(int subId, int state, int reason) { 1363 log("logDataSwitchEvent subId " + subId + " state " + state + " reason " + reason); 1364 DataSwitch dataSwitch = new DataSwitch(); 1365 dataSwitch.state = state; 1366 dataSwitch.reason = reason; 1367 TelephonyMetrics.getInstance().writeDataSwitch(subId, dataSwitch); 1368 } 1369 1370 /** 1371 * See {@link PhoneStateListener#LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE}. 1372 */ notifyPreferredDataSubIdChanged()1373 protected void notifyPreferredDataSubIdChanged() { 1374 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) mContext 1375 .getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1376 log("notifyPreferredDataSubIdChanged to " + mPreferredDataSubId); 1377 telephonyRegistryManager.notifyActiveDataSubIdChanged(mPreferredDataSubId); 1378 } 1379 1380 /** 1381 * @return The active data subscription id 1382 */ getActiveDataSubId()1383 public int getActiveDataSubId() { 1384 return mPreferredDataSubId; 1385 } 1386 1387 // TODO (b/148396668): add an internal callback method to monitor phone capability change, 1388 // and hook this call to that callback. onPhoneCapabilityChanged(PhoneCapability capability)1389 private void onPhoneCapabilityChanged(PhoneCapability capability) { 1390 onPhoneCapabilityChangedInternal(capability); 1391 } 1392 dump(FileDescriptor fd, PrintWriter writer, String[] args)1393 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1394 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 1395 pw.println("PhoneSwitcher:"); 1396 Calendar c = Calendar.getInstance(); 1397 for (int i = 0; i < mActiveModemCount; i++) { 1398 PhoneState ps = mPhoneStates[i]; 1399 c.setTimeInMillis(ps.lastRequested); 1400 pw.println("PhoneId(" + i + ") active=" + ps.active + ", lastRequest=" + 1401 (ps.lastRequested == 0 ? "never" : 1402 String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c))); 1403 } 1404 pw.increaseIndent(); 1405 mLocalLog.dump(fd, pw, args); 1406 pw.decreaseIndent(); 1407 } 1408 } 1409