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