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