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