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