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