1 /*
2  * Copyright (C) 2006 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.dataconnection;
18 
19 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
20 import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
21 import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;
22 import static android.telephony.data.ApnSetting.PROTOCOL_IPV4V6;
23 import static android.telephony.data.ApnSetting.TYPE_DEFAULT;
24 import static android.telephony.data.ApnSetting.TYPE_IA;
25 
26 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT;
27 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID;
28 
29 import android.annotation.IntDef;
30 import android.annotation.NonNull;
31 import android.annotation.Nullable;
32 import android.app.AlarmManager;
33 import android.app.PendingIntent;
34 import android.app.ProgressDialog;
35 import android.content.ActivityNotFoundException;
36 import android.content.BroadcastReceiver;
37 import android.content.ContentResolver;
38 import android.content.ContentValues;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.IntentFilter;
42 import android.content.SharedPreferences;
43 import android.content.res.Resources;
44 import android.database.ContentObserver;
45 import android.database.Cursor;
46 import android.net.ConnectivityManager;
47 import android.net.LinkProperties;
48 import android.net.NetworkAgent;
49 import android.net.NetworkCapabilities;
50 import android.net.NetworkPolicyManager;
51 import android.net.NetworkRequest;
52 import android.net.TrafficStats;
53 import android.net.Uri;
54 import android.os.AsyncResult;
55 import android.os.Bundle;
56 import android.os.Handler;
57 import android.os.HandlerThread;
58 import android.os.Message;
59 import android.os.PersistableBundle;
60 import android.os.RegistrantList;
61 import android.os.ServiceManager;
62 import android.os.SystemClock;
63 import android.os.SystemProperties;
64 import android.preference.PreferenceManager;
65 import android.provider.Settings;
66 import android.provider.Settings.SettingNotFoundException;
67 import android.provider.Telephony;
68 import android.telephony.AccessNetworkConstants;
69 import android.telephony.AccessNetworkConstants.TransportType;
70 import android.telephony.Annotation.ApnType;
71 import android.telephony.Annotation.DataFailureCause;
72 import android.telephony.Annotation.NetworkType;
73 import android.telephony.CarrierConfigManager;
74 import android.telephony.CellLocation;
75 import android.telephony.DataFailCause;
76 import android.telephony.NetworkRegistrationInfo;
77 import android.telephony.PcoData;
78 import android.telephony.PreciseDataConnectionState;
79 import android.telephony.ServiceState;
80 import android.telephony.ServiceState.RilRadioTechnology;
81 import android.telephony.SubscriptionManager;
82 import android.telephony.SubscriptionPlan;
83 import android.telephony.TelephonyDisplayInfo;
84 import android.telephony.TelephonyManager;
85 import android.telephony.TelephonyManager.SimState;
86 import android.telephony.cdma.CdmaCellLocation;
87 import android.telephony.data.ApnSetting;
88 import android.telephony.data.DataProfile;
89 import android.telephony.gsm.GsmCellLocation;
90 import android.text.TextUtils;
91 import android.util.EventLog;
92 import android.util.LocalLog;
93 import android.util.Pair;
94 import android.util.SparseArray;
95 import android.view.WindowManager;
96 
97 import com.android.internal.annotations.VisibleForTesting;
98 import com.android.internal.telephony.DctConstants;
99 import com.android.internal.telephony.EventLogTags;
100 import com.android.internal.telephony.GsmCdmaPhone;
101 import com.android.internal.telephony.ITelephony;
102 import com.android.internal.telephony.Phone;
103 import com.android.internal.telephony.PhoneConstants;
104 import com.android.internal.telephony.PhoneFactory;
105 import com.android.internal.telephony.PhoneSwitcher;
106 import com.android.internal.telephony.RILConstants;
107 import com.android.internal.telephony.SettingsObserver;
108 import com.android.internal.telephony.SubscriptionInfoUpdater;
109 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataAllowedReasonType;
110 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;
111 import com.android.internal.telephony.dataconnection.DataEnabledSettings.DataEnabledChangedReason;
112 import com.android.internal.telephony.metrics.TelephonyMetrics;
113 import com.android.internal.telephony.util.ArrayUtils;
114 import com.android.internal.telephony.util.TelephonyUtils;
115 import com.android.internal.util.AsyncChannel;
116 import com.android.telephony.Rlog;
117 
118 import java.io.FileDescriptor;
119 import java.io.PrintWriter;
120 import java.lang.annotation.Retention;
121 import java.lang.annotation.RetentionPolicy;
122 import java.util.ArrayList;
123 import java.util.Arrays;
124 import java.util.Collection;
125 import java.util.Comparator;
126 import java.util.HashMap;
127 import java.util.List;
128 import java.util.Map;
129 import java.util.Map.Entry;
130 import java.util.Set;
131 import java.util.concurrent.ConcurrentHashMap;
132 import java.util.concurrent.atomic.AtomicBoolean;
133 import java.util.concurrent.atomic.AtomicInteger;
134 import java.util.stream.Collectors;
135 
136 /**
137  * {@hide}
138  */
139 public class DcTracker extends Handler {
140     protected static final boolean DBG = true;
141     private static final boolean VDBG = false; // STOPSHIP if true
142     private static final boolean VDBG_STALL = false; // STOPSHIP if true
143     private static final boolean RADIO_TESTS = false;
144 
145     @IntDef(value = {
146             REQUEST_TYPE_NORMAL,
147             REQUEST_TYPE_HANDOVER,
148     })
149     @Retention(RetentionPolicy.SOURCE)
150     public @interface RequestNetworkType {}
151 
152     /**
153      * Normal request for {@link #requestNetwork(NetworkRequest, int, Message)}. For request
154      * network, this adds the request to the {@link ApnContext}. If there were no network request
155      * attached to the {@link ApnContext} earlier, this request setups a data connection.
156      */
157     public static final int REQUEST_TYPE_NORMAL = 1;
158 
159     /**
160      * Handover request for {@link #requestNetwork(NetworkRequest, int, Message)} or
161      * {@link #releaseNetwork(NetworkRequest, int)}. For request network, this
162      * initiates the handover data setup process. The existing data connection will be seamlessly
163      * handover to the new network. For release network, this performs a data connection softly
164      * clean up at the underlying layer (versus normal data release).
165      */
166     public static final int REQUEST_TYPE_HANDOVER = 2;
167 
168     @IntDef(value = {
169             RELEASE_TYPE_NORMAL,
170             RELEASE_TYPE_DETACH,
171             RELEASE_TYPE_HANDOVER,
172     })
173     @Retention(RetentionPolicy.SOURCE)
174     public @interface ReleaseNetworkType {}
175 
176     /**
177      * For release network, this is just removing the network request from the {@link ApnContext}.
178      * Note this does not tear down the physical data connection. Normally the data connection is
179      * torn down by connectivity service directly calling {@link NetworkAgent#unwanted()}.
180      */
181     public static final int RELEASE_TYPE_NORMAL = 1;
182 
183     /**
184      * Detach request for {@link #releaseNetwork(NetworkRequest, int)} only. This
185      * forces the APN context detach from the data connection. If this {@link ApnContext} is the
186      * last one attached to the data connection, the data connection will be torn down, otherwise
187      * the data connection remains active.
188      */
189     public static final int RELEASE_TYPE_DETACH = 2;
190 
191     /**
192      * Handover request for {@link #releaseNetwork(NetworkRequest, int)}. For release
193      * network, this performs a data connection softly clean up at the underlying layer (versus
194      * normal data release).
195      */
196     public static final int RELEASE_TYPE_HANDOVER = 3;
197 
198     /** The extras for request network completion message */
199     static final String DATA_COMPLETE_MSG_EXTRA_NETWORK_REQUEST = "extra_network_request";
200     static final String DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE = "extra_transport_type";
201     static final String DATA_COMPLETE_MSG_EXTRA_REQUEST_TYPE = "extra_request_type";
202     static final String DATA_COMPLETE_MSG_EXTRA_SUCCESS = "extra_success";
203     /**
204      * The flag indicates whether after handover failure, the data connection should remain on the
205      * original transport.
206      */
207     static final String DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK =
208             "extra_handover_failure_fallback";
209 
210     private final String mLogTag;
211     private final String mLogTagSuffix;
212 
213     public AtomicBoolean isCleanupRequired = new AtomicBoolean(false);
214 
215     private final TelephonyManager mTelephonyManager;
216 
217     private final AlarmManager mAlarmManager;
218 
219     /* Currently requested APN type (TODO: This should probably be a parameter not a member) */
220     private int mRequestedApnType = ApnSetting.TYPE_DEFAULT;
221 
222     // All data enabling/disabling related settings
223     private final DataEnabledSettings mDataEnabledSettings;
224 
225     /**
226      * After detecting a potential connection problem, this is the max number
227      * of subsequent polls before attempting recovery.
228      */
229     // 1 sec. default polling interval when screen is on.
230     private static final int POLL_NETSTAT_MILLIS = 1000;
231     // 10 min. default polling interval when screen is off.
232     private static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
233     // Default sent packets without ack which triggers initial recovery steps
234     private static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
235 
236     // Default for the data stall alarm while non-aggressive stall detection
237     private static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6;
238     // Default for the data stall alarm for aggressive stall detection
239     private static final int DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60;
240 
241     private static final boolean DATA_STALL_SUSPECTED = true;
242     protected static final boolean DATA_STALL_NOT_SUSPECTED = false;
243 
244     private static final String INTENT_DATA_STALL_ALARM =
245             "com.android.internal.telephony.data-stall";
246     // Tag for tracking stale alarms
247     private static final String INTENT_DATA_STALL_ALARM_EXTRA_TAG = "data_stall_alarm_extra_tag";
248     private static final String INTENT_DATA_STALL_ALARM_EXTRA_TRANSPORT_TYPE =
249             "data_stall_alarm_extra_transport_type";
250 
251     /** The higher index has higher priority. */
252     private static final DctConstants.State[] DATA_CONNECTION_STATE_PRIORITIES = {
253             DctConstants.State.IDLE,
254             DctConstants.State.DISCONNECTING,
255             DctConstants.State.CONNECTING,
256             DctConstants.State.CONNECTED,
257     };
258 
259     private DcTesterFailBringUpAll mDcTesterFailBringUpAll;
260     private DcController mDcc;
261 
262     /** kept in sync with mApnContexts
263      * Higher numbers are higher priority and sorted so highest priority is first */
264     private ArrayList<ApnContext> mPrioritySortedApnContexts = new ArrayList<>();
265 
266     /** all APN settings applicable to the current carrier */
267     private ArrayList<ApnSetting> mAllApnSettings = new ArrayList<>();
268 
269     /** preferred apn */
270     private ApnSetting mPreferredApn = null;
271 
272     /** Is packet service restricted by network */
273     private boolean mIsPsRestricted = false;
274 
275     /** emergency apn Setting*/
276     private ApnSetting mEmergencyApn = null;
277 
278     /* Once disposed dont handle any messages */
279     private boolean mIsDisposed = false;
280 
281     private ContentResolver mResolver;
282 
283     /* Set to true with CMD_ENABLE_MOBILE_PROVISIONING */
284     private boolean mIsProvisioning = false;
285 
286     /* The Url passed as object parameter in CMD_ENABLE_MOBILE_PROVISIONING */
287     private String mProvisioningUrl = null;
288 
289     /* Indicating data service is bound or not */
290     private boolean mDataServiceBound = false;
291 
292     /* Intent for the provisioning apn alarm */
293     private static final String INTENT_PROVISIONING_APN_ALARM =
294             "com.android.internal.telephony.provisioning_apn_alarm";
295 
296     /* Tag for tracking stale alarms */
297     private static final String PROVISIONING_APN_ALARM_TAG_EXTRA = "provisioning.apn.alarm.tag";
298 
299     /* Debug property for overriding the PROVISIONING_APN_ALARM_DELAY_IN_MS */
300     private static final String DEBUG_PROV_APN_ALARM = "persist.debug.prov_apn_alarm";
301 
302     /* Default for the provisioning apn alarm timeout */
303     private static final int PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 15;
304 
305     /* The provision apn alarm intent used to disable the provisioning apn */
306     private PendingIntent mProvisioningApnAlarmIntent = null;
307 
308     /* Used to track stale provisioning apn alarms */
309     private int mProvisioningApnAlarmTag = (int) SystemClock.elapsedRealtime();
310 
311     private AsyncChannel mReplyAc = new AsyncChannel();
312 
313     private final LocalLog mDataRoamingLeakageLog = new LocalLog(50);
314     private final LocalLog mApnSettingsInitializationLog = new LocalLog(50);
315 
316     /* 5G connection reevaluation watchdog alarm constants */
317     private long mWatchdogTimeMs = 1000 * 60 * 60;
318     private boolean mWatchdog = false;
319 
320     /* Default for whether 5G frequencies are considered unmetered */
321     private boolean mNrNsaAllUnmetered = false;
322     private boolean mNrNsaMmwaveUnmetered = false;
323     private boolean mNrNsaSub6Unmetered = false;
324     private boolean mNrSaAllUnmetered = false;
325     private boolean mNrSaMmwaveUnmetered = false;
326     private boolean mNrSaSub6Unmetered = false;
327     private boolean mRoamingUnmetered = false;
328 
329     /* List of SubscriptionPlans, updated on SubscriptionManager.setSubscriptionPlans */
330     private List<SubscriptionPlan> mSubscriptionPlans = null;
331 
332     @SimState
333     private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
334 
335     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver () {
336         @Override
337         public void onReceive(Context context, Intent intent) {
338             String action = intent.getAction();
339 
340             if (action.equals(Intent.ACTION_SCREEN_ON)) {
341                 // TODO: Evaluate hooking this up with DeviceStateMonitor
342                 if (DBG) log("screen on");
343                 mIsScreenOn = true;
344                 stopNetStatPoll();
345                 startNetStatPoll();
346                 restartDataStallAlarm();
347             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
348                 if (DBG) log("screen off");
349                 mIsScreenOn = false;
350                 stopNetStatPoll();
351                 startNetStatPoll();
352                 restartDataStallAlarm();
353             } else if (action.equals(INTENT_DATA_STALL_ALARM)) {
354                 onActionIntentDataStallAlarm(intent);
355             } else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) {
356                 if (DBG) log("Provisioning apn alarm");
357                 onActionIntentProvisioningApnAlarm(intent);
358             } else if (action.equals(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)
359                     || action.equals(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)) {
360                 if (mPhone.getPhoneId() == intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
361                         SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
362                     int simState = intent.getIntExtra(TelephonyManager.EXTRA_SIM_STATE,
363                             TelephonyManager.SIM_STATE_UNKNOWN);
364                     sendMessage(obtainMessage(DctConstants.EVENT_SIM_STATE_UPDATED, simState, 0));
365                 }
366             } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
367                 if (mPhone.getPhoneId() == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX,
368                         SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
369                     if (intent.getBooleanExtra(
370                             CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
371                         // Ignore the rebroadcast one to prevent multiple carrier config changed
372                         // event during boot up.
373                         return;
374                     }
375                     int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
376                             SubscriptionManager.INVALID_SUBSCRIPTION_ID);
377                     if (SubscriptionManager.isValidSubscriptionId(subId)) {
378                         sendEmptyMessage(DctConstants.EVENT_CARRIER_CONFIG_CHANGED);
379                     }
380                 }
381             } else {
382                 if (DBG) log("onReceive: Unknown action=" + action);
383             }
384         }
385     };
386 
387     private final Runnable mPollNetStat = new Runnable() {
388         @Override
389         public void run() {
390             updateDataActivity();
391 
392             if (mIsScreenOn) {
393                 mNetStatPollPeriod = Settings.Global.getInt(mResolver,
394                         Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS);
395             } else {
396                 mNetStatPollPeriod = Settings.Global.getInt(mResolver,
397                         Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
398                         POLL_NETSTAT_SCREEN_OFF_MILLIS);
399             }
400 
401             if (mNetStatPollEnabled) {
402                 mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod);
403             }
404         }
405     };
406 
407     private NetworkPolicyManager mNetworkPolicyManager;
408     private final NetworkPolicyManager.SubscriptionCallback mSubscriptionCallback =
409             new NetworkPolicyManager.SubscriptionCallback() {
410         @Override
411         public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
412             if (mPhone == null || mPhone.getSubId() != subId) return;
413 
414             for (DataConnection dataConnection : mDataConnections.values()) {
415                 dataConnection.onSubscriptionOverride(overrideMask, overrideValue);
416             }
417         }
418 
419         @Override
420         public void onSubscriptionPlansChanged(int subId, SubscriptionPlan[] plans) {
421             if (mPhone == null || mPhone.getSubId() != subId) return;
422 
423             mSubscriptionPlans = plans == null ? null : Arrays.asList(plans);
424             reevaluateUnmeteredConnections();
425         }
426     };
427 
428     private final SettingsObserver mSettingsObserver;
429 
registerSettingsObserver()430     private void registerSettingsObserver() {
431         mSettingsObserver.unobserve();
432         String simSuffix = "";
433         if (TelephonyManager.getDefault().getSimCount() > 1) {
434             simSuffix = Integer.toString(mPhone.getSubId());
435         }
436 
437         mSettingsObserver.observe(
438                 Settings.Global.getUriFor(Settings.Global.DATA_ROAMING + simSuffix),
439                 DctConstants.EVENT_ROAMING_SETTING_CHANGE);
440         mSettingsObserver.observe(
441                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
442                 DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE);
443     }
444 
445     /**
446      * Maintain the sum of transmit and receive packets.
447      *
448      * The packet counts are initialized and reset to -1 and
449      * remain -1 until they can be updated.
450      */
451     public static class TxRxSum {
452         public long txPkts;
453         public long rxPkts;
454 
TxRxSum()455         public TxRxSum() {
456             reset();
457         }
458 
TxRxSum(long txPkts, long rxPkts)459         public TxRxSum(long txPkts, long rxPkts) {
460             this.txPkts = txPkts;
461             this.rxPkts = rxPkts;
462         }
463 
TxRxSum(TxRxSum sum)464         public TxRxSum(TxRxSum sum) {
465             txPkts = sum.txPkts;
466             rxPkts = sum.rxPkts;
467         }
468 
reset()469         public void reset() {
470             txPkts = -1;
471             rxPkts = -1;
472         }
473 
474         @Override
toString()475         public String toString() {
476             return "{txSum=" + txPkts + " rxSum=" + rxPkts + "}";
477         }
478 
479         /**
480          * Get total Tx/Rx packet count from TrafficStats
481          */
updateTotalTxRxSum()482         public void updateTotalTxRxSum() {
483             this.txPkts = TrafficStats.getMobileTxPackets();
484             this.rxPkts = TrafficStats.getMobileRxPackets();
485         }
486     }
487 
onDataReconnect(ApnContext apnContextforRetry, int subId)488     private void onDataReconnect(ApnContext apnContextforRetry, int subId) {
489         int phoneSubId = mPhone.getSubId();
490         String apnType = apnContextforRetry.getApnType();
491         String reason =  apnContextforRetry.getReason();
492 
493         if (!SubscriptionManager.isValidSubscriptionId(subId) || (subId != phoneSubId)) {
494             log("onDataReconnect: invalid subId");
495             return;
496         }
497 
498         ApnContext apnContext = mApnContexts.get(apnType);
499 
500         if (DBG) {
501             log("onDataReconnect: mState=" + mState + " reason=" + reason + " apnType=" + apnType
502                     + " apnContext=" + apnContext);
503         }
504 
505         if ((apnContext != null) && (apnContext.isEnabled())) {
506             apnContext.setReason(reason);
507             DctConstants.State apnContextState = apnContext.getState();
508             if (DBG) {
509                 log("onDataReconnect: apnContext state=" + apnContextState);
510             }
511             if ((apnContextState == DctConstants.State.FAILED)
512                     || (apnContextState == DctConstants.State.IDLE)) {
513                 if (DBG) {
514                     log("onDataReconnect: state is FAILED|IDLE, disassociate");
515                 }
516                 apnContext.releaseDataConnection("");
517             } else {
518                 if (DBG) log("onDataReconnect: keep associated");
519             }
520             // TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA???
521             sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
522         }
523     }
524 
onActionIntentDataStallAlarm(Intent intent)525     private void onActionIntentDataStallAlarm(Intent intent) {
526         if (VDBG_STALL) log("onActionIntentDataStallAlarm: action=" + intent.getAction());
527 
528         int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
529                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
530         if (!SubscriptionManager.isValidSubscriptionId(subId) || (subId != mPhone.getSubId())) {
531             return;
532         }
533 
534         int transportType = intent.getIntExtra(INTENT_DATA_STALL_ALARM_EXTRA_TRANSPORT_TYPE, 0);
535         if (transportType != mTransportType) {
536             return;
537         }
538 
539         Message msg = obtainMessage(DctConstants.EVENT_DATA_STALL_ALARM,
540                 intent.getAction());
541         msg.arg1 = intent.getIntExtra(INTENT_DATA_STALL_ALARM_EXTRA_TAG, 0);
542         sendMessage(msg);
543     }
544 
545     private RegistrantList mAllDataDisconnectedRegistrants = new RegistrantList();
546 
547     // member variables
548     protected final Phone mPhone;
549     private DctConstants.Activity mActivity = DctConstants.Activity.NONE;
550     private DctConstants.State mState = DctConstants.State.IDLE;
551     private final Handler mDataConnectionTracker;
552 
553     private long mTxPkts;
554     private long mRxPkts;
555     private int mNetStatPollPeriod;
556     private boolean mNetStatPollEnabled = false;
557 
558     private TxRxSum mDataStallTxRxSum = new TxRxSum(0, 0);
559     // Used to track stale data stall alarms.
560     private int mDataStallAlarmTag = (int) SystemClock.elapsedRealtime();
561     // The current data stall alarm intent
562     private PendingIntent mDataStallAlarmIntent = null;
563     // Number of packets sent since the last received packet
564     private long mSentSinceLastRecv;
565     // Controls when a simple recovery attempt it to be tried
566     private int mNoRecvPollCount = 0;
567     // Reference counter for enabling fail fast
568     private static int sEnableFailFastRefCounter = 0;
569     // True if data stall detection is enabled
570     private volatile boolean mDataStallNoRxEnabled = true;
571 
572     protected volatile boolean mFailFast = false;
573 
574     // True when in voice call
575     protected boolean mInVoiceCall = false;
576 
577     /** Intent sent when the reconnect alarm fires. */
578     private PendingIntent mReconnectIntent = null;
579 
580     // When false we will not auto attach and manually attaching is required.
581     protected boolean mAutoAttachOnCreationConfig = false;
582     private AtomicBoolean mAutoAttachEnabled = new AtomicBoolean(false);
583 
584     // State of screen
585     // (TODO: Reconsider tying directly to screen, maybe this is
586     //        really a lower power mode")
587     private boolean mIsScreenOn = true;
588 
589     /** Allows the generation of unique Id's for DataConnection objects */
590     private AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
591 
592     /** The data connections. */
593     private HashMap<Integer, DataConnection> mDataConnections =
594             new HashMap<Integer, DataConnection>();
595 
596     /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
597     private HashMap<String, Integer> mApnToDataConnectionId = new HashMap<String, Integer>();
598 
599     /** Phone.APN_TYPE_* ===> ApnContext */
600     protected ConcurrentHashMap<String, ApnContext> mApnContexts =
601             new ConcurrentHashMap<String, ApnContext>();
602 
603     private SparseArray<ApnContext> mApnContextsByType = new SparseArray<ApnContext>();
604 
605     private int mDisconnectPendingCount = 0;
606 
607     private ArrayList<DataProfile> mLastDataProfileList = new ArrayList<>();
608 
609     /** RAT name ===> (downstream, upstream) bandwidth values from carrier config. */
610     private ConcurrentHashMap<String, Pair<Integer, Integer>> mBandwidths =
611             new ConcurrentHashMap<>();
612 
613     private boolean mConfigReady = false;
614 
615     /**
616      * Handles changes to the APN db.
617      */
618     private class ApnChangeObserver extends ContentObserver {
ApnChangeObserver()619         public ApnChangeObserver () {
620             super(mDataConnectionTracker);
621         }
622 
623         @Override
onChange(boolean selfChange)624         public void onChange(boolean selfChange) {
625             sendMessage(obtainMessage(DctConstants.EVENT_APN_CHANGED));
626         }
627     }
628 
629     //***** Instance Variables
630 
631     private boolean mReregisterOnReconnectFailure = false;
632 
633 
634     //***** Constants
635 
636     private static final int PROVISIONING_SPINNER_TIMEOUT_MILLIS = 120 * 1000;
637 
638     static final Uri PREFERAPN_NO_UPDATE_URI_USING_SUBID =
639                         Uri.parse("content://telephony/carriers/preferapn_no_update/subId/");
640     static final String APN_ID = "apn_id";
641 
642     private boolean mCanSetPreferApn = false;
643 
644     private AtomicBoolean mAttached = new AtomicBoolean(false);
645 
646     /** Watches for changes to the APN db. */
647     private ApnChangeObserver mApnObserver;
648 
649     private final String mProvisionActionName;
650     private BroadcastReceiver mProvisionBroadcastReceiver;
651     private ProgressDialog mProvisioningSpinner;
652 
653     private final DataServiceManager mDataServiceManager;
654 
655     private final int mTransportType;
656 
657     private DataStallRecoveryHandler mDsRecoveryHandler;
658     private HandlerThread mHandlerThread;
659 
660     /**
661      * Request network completion message map. Key is the APN type, value is the list of completion
662      * messages to be sent. Using a list because there might be multiple network requests for
663      * the same APN type.
664      */
665     private final Map<Integer, List<Message>> mRequestNetworkCompletionMsgs = new HashMap<>();
666 
667     //***** Constructor
DcTracker(Phone phone, @TransportType int transportType)668     public DcTracker(Phone phone, @TransportType int transportType) {
669         super();
670         mPhone = phone;
671         if (DBG) log("DCT.constructor");
672         mTelephonyManager = TelephonyManager.from(phone.getContext())
673                 .createForSubscriptionId(phone.getSubId());
674         // The 'C' in tag indicates cellular, and 'I' indicates IWLAN. This is to distinguish
675         // between two DcTrackers, one for each.
676         mLogTagSuffix = "-" + ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
677                 ? "C" : "I") + "-" + mPhone.getPhoneId();
678         mLogTag = "DCT" + mLogTagSuffix;
679 
680         mTransportType = transportType;
681         mDataServiceManager = new DataServiceManager(phone, transportType, mLogTagSuffix);
682 
683         mResolver = mPhone.getContext().getContentResolver();
684         mAlarmManager =
685                 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
686 
687         mDsRecoveryHandler = new DataStallRecoveryHandler();
688 
689         IntentFilter filter = new IntentFilter();
690         filter.addAction(Intent.ACTION_SCREEN_ON);
691         filter.addAction(Intent.ACTION_SCREEN_OFF);
692         filter.addAction(INTENT_DATA_STALL_ALARM);
693         filter.addAction(INTENT_PROVISIONING_APN_ALARM);
694         filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
695         filter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
696         filter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
697 
698         mDataEnabledSettings = mPhone.getDataEnabledSettings();
699 
700         mDataEnabledSettings.registerForDataEnabledChanged(this,
701                 DctConstants.EVENT_DATA_ENABLED_CHANGED, null);
702         mDataEnabledSettings.registerForDataEnabledOverrideChanged(this,
703                 DctConstants.EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED);
704 
705         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
706 
707         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
708         mAutoAttachEnabled.set(sp.getBoolean(Phone.DATA_DISABLED_ON_BOOT_KEY, false));
709 
710         mNetworkPolicyManager = (NetworkPolicyManager) mPhone.getContext()
711                 .getSystemService(Context.NETWORK_POLICY_SERVICE);
712         mNetworkPolicyManager.registerSubscriptionCallback(mSubscriptionCallback);
713 
714         mHandlerThread = new HandlerThread("DcHandlerThread");
715         mHandlerThread.start();
716         Handler dcHandler = new Handler(mHandlerThread.getLooper());
717         mDcc = DcController.makeDcc(mPhone, this, mDataServiceManager, dcHandler, mLogTagSuffix);
718         mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler);
719 
720         mDataConnectionTracker = this;
721         registerForAllEvents();
722         mApnObserver = new ApnChangeObserver();
723         phone.getContext().getContentResolver().registerContentObserver(
724                 Telephony.Carriers.CONTENT_URI, true, mApnObserver);
725 
726         initApnContexts();
727 
728         initEmergencyApnSetting();
729         addEmergencyApnSetting();
730 
731         mProvisionActionName = "com.android.internal.telephony.PROVISION" + phone.getPhoneId();
732 
733         mSettingsObserver = new SettingsObserver(mPhone.getContext(), this);
734         registerSettingsObserver();
735     }
736 
737     @VisibleForTesting
DcTracker()738     public DcTracker() {
739         mLogTag = "DCT";
740         mLogTagSuffix = null;
741         mTelephonyManager = null;
742         mAlarmManager = null;
743         mPhone = null;
744         mDataConnectionTracker = null;
745         mProvisionActionName = null;
746         mSettingsObserver = new SettingsObserver(null, this);
747         mDataEnabledSettings = null;
748         mTransportType = 0;
749         mDataServiceManager = null;
750     }
751 
registerServiceStateTrackerEvents()752     public void registerServiceStateTrackerEvents() {
753         mPhone.getServiceStateTracker().registerForDataConnectionAttached(mTransportType, this,
754                 DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null);
755         mPhone.getServiceStateTracker().registerForDataConnectionDetached(mTransportType, this,
756                 DctConstants.EVENT_DATA_CONNECTION_DETACHED, null);
757         mPhone.getServiceStateTracker().registerForDataRoamingOn(this,
758                 DctConstants.EVENT_ROAMING_ON, null);
759         mPhone.getServiceStateTracker().registerForDataRoamingOff(this,
760                 DctConstants.EVENT_ROAMING_OFF, null, true);
761         mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this,
762                 DctConstants.EVENT_PS_RESTRICT_ENABLED, null);
763         mPhone.getServiceStateTracker().registerForPsRestrictedDisabled(this,
764                 DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
765         mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this,
766                 DctConstants.EVENT_DATA_RAT_CHANGED, null);
767     }
768 
unregisterServiceStateTrackerEvents()769     public void unregisterServiceStateTrackerEvents() {
770         mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(mTransportType, this);
771         mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(mTransportType, this);
772         mPhone.getServiceStateTracker().unregisterForDataRoamingOn(this);
773         mPhone.getServiceStateTracker().unregisterForDataRoamingOff(this);
774         mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this);
775         mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
776         mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType, this);
777     }
778 
registerForAllEvents()779     private void registerForAllEvents() {
780         if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
781             mPhone.mCi.registerForAvailable(this, DctConstants.EVENT_RADIO_AVAILABLE, null);
782             mPhone.mCi.registerForOffOrNotAvailable(this,
783                     DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
784             mPhone.mCi.registerForPcoData(this, DctConstants.EVENT_PCO_DATA_RECEIVED, null);
785         }
786 
787         // Note, this is fragile - the Phone is now presenting a merged picture
788         // of PS (volte) & CS and by diving into its internals you're just seeing
789         // the CS data.  This works well for the purposes this is currently used for
790         // but that may not always be the case.  Should probably be redesigned to
791         // accurately reflect what we're really interested in (registerForCSVoiceCallEnded).
792         mPhone.getCallTracker().registerForVoiceCallEnded(this,
793                 DctConstants.EVENT_VOICE_CALL_ENDED, null);
794         mPhone.getCallTracker().registerForVoiceCallStarted(this,
795                 DctConstants.EVENT_VOICE_CALL_STARTED, null);
796         mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(this,
797                 DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED, null);
798         registerServiceStateTrackerEvents();
799         mDataServiceManager.registerForServiceBindingChanged(this,
800                 DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED, null);
801     }
802 
dispose()803     public void dispose() {
804         if (DBG) log("DCT.dispose");
805 
806         if (mProvisionBroadcastReceiver != null) {
807             mPhone.getContext().unregisterReceiver(mProvisionBroadcastReceiver);
808             mProvisionBroadcastReceiver = null;
809         }
810         if (mProvisioningSpinner != null) {
811             mProvisioningSpinner.dismiss();
812             mProvisioningSpinner = null;
813         }
814 
815         cleanUpAllConnectionsInternal(true, null);
816 
817         mIsDisposed = true;
818         mPhone.getContext().unregisterReceiver(mIntentReceiver);
819         mSettingsObserver.unobserve();
820 
821         mNetworkPolicyManager.unregisterSubscriptionCallback(mSubscriptionCallback);
822         mDcc.dispose();
823         mDcTesterFailBringUpAll.dispose();
824 
825         mPhone.getContext().getContentResolver().unregisterContentObserver(mApnObserver);
826         mApnContexts.clear();
827         mApnContextsByType.clear();
828         mPrioritySortedApnContexts.clear();
829         unregisterForAllEvents();
830 
831         destroyDataConnections();
832     }
833 
834     /**
835      * Stop the internal handler thread
836      *
837      * TESTING ONLY
838      */
839     @VisibleForTesting
stopHandlerThread()840     public void stopHandlerThread() {
841         mHandlerThread.quit();
842     }
843 
unregisterForAllEvents()844     private void unregisterForAllEvents() {
845          //Unregister for all events
846         if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
847             mPhone.mCi.unregisterForAvailable(this);
848             mPhone.mCi.unregisterForOffOrNotAvailable(this);
849             mPhone.mCi.unregisterForPcoData(this);
850         }
851 
852         mPhone.getCallTracker().unregisterForVoiceCallEnded(this);
853         mPhone.getCallTracker().unregisterForVoiceCallStarted(this);
854         mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(this);
855         unregisterServiceStateTrackerEvents();
856         mDataServiceManager.unregisterForServiceBindingChanged(this);
857         mDataEnabledSettings.unregisterForDataEnabledChanged(this);
858         mDataEnabledSettings.unregisterForDataEnabledOverrideChanged(this);
859     }
860 
861     /**
862      * Reevaluate existing data connections when conditions change.
863      *
864      * For example, handle reverting restricted networks back to unrestricted. If we're changing
865      * user data to enabled and this makes data truly enabled (not disabled by other factors) we
866      * need to reevaluate and possibly add NET_CAPABILITY_NOT_RESTRICTED capability to the data
867      * connection. This allows non-privilege apps to use the network.
868      *
869      * Or when we brought up a unmetered data connection while data is off, we only limit this
870      * data connection for unmetered use only. When data is turned back on, we need to tear that
871      * down so a full capable data connection can be re-established.
872      */
reevaluateDataConnections()873     private void reevaluateDataConnections() {
874         for (DataConnection dataConnection : mDataConnections.values()) {
875             dataConnection.reevaluateRestrictedState();
876         }
877     }
878 
getSubId()879     public long getSubId() {
880         return mPhone.getSubId();
881     }
882 
getActivity()883     public DctConstants.Activity getActivity() {
884         return mActivity;
885     }
886 
setActivity(DctConstants.Activity activity)887     private void setActivity(DctConstants.Activity activity) {
888         log("setActivity = " + activity);
889         mActivity = activity;
890         mPhone.notifyDataActivity();
891     }
892 
requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type, Message onCompleteMsg)893     public void requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type,
894                                Message onCompleteMsg) {
895         final int apnType = ApnContext.getApnTypeFromNetworkRequest(networkRequest);
896         final ApnContext apnContext = mApnContextsByType.get(apnType);
897         if (apnContext != null) {
898             apnContext.requestNetwork(networkRequest, type, onCompleteMsg);
899         }
900     }
901 
releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type)902     public void releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type) {
903         final int apnType = ApnContext.getApnTypeFromNetworkRequest(networkRequest);
904         final ApnContext apnContext = mApnContextsByType.get(apnType);
905         if (apnContext != null) {
906             apnContext.releaseNetwork(networkRequest, type);
907         }
908     }
909 
910     // Turn telephony radio on or off.
setRadio(boolean on)911     private void setRadio(boolean on) {
912         final ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
913         try {
914             phone.setRadio(on);
915         } catch (Exception e) {
916             // Ignore.
917         }
918     }
919 
920     // Class to handle Intent dispatched with user selects the "Sign-in to network"
921     // notification.
922     private class ProvisionNotificationBroadcastReceiver extends BroadcastReceiver {
923         private final String mNetworkOperator;
924         // Mobile provisioning URL.  Valid while provisioning notification is up.
925         // Set prior to notification being posted as URL contains ICCID which
926         // disappears when radio is off (which is the case when notification is up).
927         private final String mProvisionUrl;
928 
ProvisionNotificationBroadcastReceiver(String provisionUrl, String networkOperator)929         public ProvisionNotificationBroadcastReceiver(String provisionUrl, String networkOperator) {
930             mNetworkOperator = networkOperator;
931             mProvisionUrl = provisionUrl;
932         }
933 
setEnableFailFastMobileData(int enabled)934         private void setEnableFailFastMobileData(int enabled) {
935             sendMessage(obtainMessage(DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA, enabled, 0));
936         }
937 
enableMobileProvisioning()938         private void enableMobileProvisioning() {
939             final Message msg = obtainMessage(DctConstants.CMD_ENABLE_MOBILE_PROVISIONING);
940             Bundle bundle = new Bundle(1);
941             bundle.putString(DctConstants.PROVISIONING_URL_KEY, mProvisionUrl);
942             msg.setData(bundle);
943             sendMessage(msg);
944         }
945 
946         @Override
onReceive(Context context, Intent intent)947         public void onReceive(Context context, Intent intent) {
948             // Turning back on the radio can take time on the order of a minute, so show user a
949             // spinner so they know something is going on.
950             log("onReceive : ProvisionNotificationBroadcastReceiver");
951             mProvisioningSpinner = new ProgressDialog(context);
952             mProvisioningSpinner.setTitle(mNetworkOperator);
953             mProvisioningSpinner.setMessage(
954                     // TODO: Don't borrow "Connecting..." i18n string; give Telephony a version.
955                     context.getText(com.android.internal.R.string.media_route_status_connecting));
956             mProvisioningSpinner.setIndeterminate(true);
957             mProvisioningSpinner.setCancelable(true);
958             // Allow non-Activity Service Context to create a View.
959             mProvisioningSpinner.getWindow().setType(
960                     WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
961             mProvisioningSpinner.show();
962             // After timeout, hide spinner so user can at least use their device.
963             // TODO: Indicate to user that it is taking an unusually long time to connect?
964             sendMessageDelayed(obtainMessage(DctConstants.CMD_CLEAR_PROVISIONING_SPINNER,
965                     mProvisioningSpinner), PROVISIONING_SPINNER_TIMEOUT_MILLIS);
966             // This code is almost identical to the old
967             // ConnectivityService.handleMobileProvisioningAction code.
968             setRadio(true);
969             setEnableFailFastMobileData(DctConstants.ENABLED);
970             enableMobileProvisioning();
971         }
972     }
973 
974     @Override
finalize()975     protected void finalize() {
976         if(DBG && mPhone != null) log("finalize");
977     }
978 
initApnContexts()979     private void initApnContexts() {
980         PersistableBundle carrierConfig;
981         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
982                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
983         if (configManager != null) {
984             carrierConfig = configManager.getConfigForSubId(mPhone.getSubId());
985         } else {
986             carrierConfig = null;
987         }
988         initApnContexts(carrierConfig);
989     }
990 
991     //Blows away any existing apncontexts that may exist, only use in ctor.
initApnContexts(PersistableBundle carrierConfig)992     private void initApnContexts(PersistableBundle carrierConfig) {
993         if (!mTelephonyManager.isDataCapable()) {
994             log("initApnContexts: isDataCapable == false.  No Apn Contexts loaded");
995             return;
996         }
997 
998         log("initApnContexts: E");
999         // Load device network attributes from resources
1000         final Collection<ApnConfigType> types =
1001                 new ApnConfigTypeRepository(carrierConfig).getTypes();
1002 
1003         for (ApnConfigType apnConfigType : types) {
1004             ApnContext apnContext = new ApnContext(mPhone, apnConfigType.getType(), mLogTag, this,
1005                     apnConfigType.getPriority());
1006             mPrioritySortedApnContexts.add(apnContext);
1007             mApnContexts.put(apnContext.getApnType(), apnContext);
1008             mApnContextsByType.put(ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType()),
1009                     apnContext);
1010 
1011             log("initApnContexts: apnContext=" + ApnSetting.getApnTypeString(
1012                     apnConfigType.getType()));
1013         }
1014         mPrioritySortedApnContexts.sort((c1, c2) -> c2.getPriority() - c1.getPriority());
1015         logSortedApnContexts();
1016     }
1017 
sortApnContextByPriority()1018     private void sortApnContextByPriority() {
1019         if (!mTelephonyManager.isDataCapable()) {
1020             log("sortApnContextByPriority: isDataCapable == false.  No Apn Contexts loaded");
1021             return;
1022         }
1023 
1024         PersistableBundle carrierConfig;
1025         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
1026                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
1027         if (configManager != null) {
1028             carrierConfig = configManager.getConfigForSubId(mPhone.getSubId());
1029         } else {
1030             carrierConfig = null;
1031         }
1032 
1033         log("sortApnContextByPriority: E");
1034         // Load device network attributes from resources
1035         final Collection<ApnConfigType> types =
1036                 new ApnConfigTypeRepository(carrierConfig).getTypes();
1037         for (ApnConfigType apnConfigType : types) {
1038             if (mApnContextsByType.get(apnConfigType.getType()) != null) {
1039                 ApnContext apnContext = mApnContextsByType.get(apnConfigType.getType());
1040                 apnContext.setPriority(apnConfigType.getPriority());
1041             }
1042         }
1043 
1044         //Doing sorted in a different list to keep thread safety
1045         ArrayList<ApnContext> prioritySortedApnContexts =
1046                 new ArrayList<>(mPrioritySortedApnContexts);
1047         prioritySortedApnContexts.sort((c1, c2) -> c2.getPriority() - c1.getPriority());
1048         mPrioritySortedApnContexts = prioritySortedApnContexts;
1049         logSortedApnContexts();
1050     }
1051 
getLinkProperties(String apnType)1052     public LinkProperties getLinkProperties(String apnType) {
1053         ApnContext apnContext = mApnContexts.get(apnType);
1054         if (apnContext != null) {
1055             DataConnection dataConnection = apnContext.getDataConnection();
1056             if (dataConnection != null) {
1057                 if (DBG) log("return link properties for " + apnType);
1058                 return dataConnection.getLinkProperties();
1059             }
1060         }
1061         if (DBG) log("return new LinkProperties");
1062         return new LinkProperties();
1063     }
1064 
getNetworkCapabilities(String apnType)1065     public NetworkCapabilities getNetworkCapabilities(String apnType) {
1066         ApnContext apnContext = mApnContexts.get(apnType);
1067         if (apnContext!=null) {
1068             DataConnection dataConnection = apnContext.getDataConnection();
1069             if (dataConnection != null) {
1070                 if (DBG) {
1071                     log("get active pdp is not null, return NetworkCapabilities for " + apnType);
1072                 }
1073                 return dataConnection.getNetworkCapabilities();
1074             }
1075         }
1076         if (DBG) log("return new NetworkCapabilities");
1077         return new NetworkCapabilities();
1078     }
1079 
1080     // Return all active apn types
getActiveApnTypes()1081     public String[] getActiveApnTypes() {
1082         if (DBG) log("get all active apn types");
1083         ArrayList<String> result = new ArrayList<String>();
1084 
1085         for (ApnContext apnContext : mApnContexts.values()) {
1086             if (mAttached.get() && apnContext.isReady()) {
1087                 result.add(apnContext.getApnType());
1088             }
1089         }
1090 
1091         return result.toArray(new String[0]);
1092     }
1093 
1094     /**
1095      * Get ApnTypes with connected data connections.  This is different than getActiveApnTypes()
1096      * which returns apn types that with active apn contexts.
1097      * @return apn types
1098      */
getConnectedApnTypes()1099     public String[] getConnectedApnTypes() {
1100         return mApnContexts.values().stream()
1101                 .filter(ac -> ac.getState() == DctConstants.State.CONNECTED)
1102                 .map(ApnContext::getApnType)
1103                 .toArray(String[]::new);
1104     }
1105 
1106     @VisibleForTesting
getApnContexts()1107     public Collection<ApnContext> getApnContexts() {
1108         return mPrioritySortedApnContexts;
1109     }
1110 
1111     /** Return active ApnSetting of a specific apnType */
getActiveApnSetting(String apnType)1112     public ApnSetting getActiveApnSetting(String apnType) {
1113         if (VDBG) log("get active ApnSetting for type:" + apnType);
1114         ApnContext apnContext = mApnContexts.get(apnType);
1115         return (apnContext != null) ? apnContext.getApnSetting() : null;
1116     }
1117 
1118     // Return active apn of specific apn type
getActiveApnString(String apnType)1119     public String getActiveApnString(String apnType) {
1120         if (VDBG) log( "get active apn string for type:" + apnType);
1121         ApnSetting setting = getActiveApnSetting(apnType);
1122         return (setting != null) ? setting.getApnName() : null;
1123     }
1124 
1125     /**
1126      * Returns {@link DctConstants.State} based on the state of the {@link DataConnection} that
1127      * contains a {@link ApnSetting} that supported the given apn type {@code anpType}.
1128      *
1129      * <p>
1130      * Assumes there is less than one {@link ApnSetting} can support the given apn type.
1131      */
getState(String apnType)1132     public DctConstants.State getState(String apnType) {
1133         DctConstants.State state = DctConstants.State.IDLE;
1134         final int apnTypeBitmask = ApnSetting.getApnTypesBitmaskFromString(apnType);
1135         for (DataConnection dc : mDataConnections.values()) {
1136             ApnSetting apnSetting = dc.getApnSetting();
1137             if (apnSetting != null && apnSetting.canHandleType(apnTypeBitmask)) {
1138                 if (dc.isActive()) {
1139                     state = getBetterConnectionState(state, DctConstants.State.CONNECTED);
1140                 } else if (dc.isActivating()) {
1141                     state = getBetterConnectionState(state, DctConstants.State.CONNECTING);
1142                 } else if (dc.isInactive()) {
1143                     state = getBetterConnectionState(state, DctConstants.State.IDLE);
1144                 } else if (dc.isDisconnecting()) {
1145                     state = getBetterConnectionState(state, DctConstants.State.DISCONNECTING);
1146                 }
1147             }
1148         }
1149         return state;
1150     }
1151 
1152     /** Convert the internal DctConstants enum state to the TelephonyManager DATA_*  state.
1153      * @param state the DctConstants.State
1154      * @return a corresponding TelephonyManager.DataState
1155      */
1156     @TelephonyManager.DataState
convertDctStateToTelephonyDataState(DctConstants.State state)1157     public static int convertDctStateToTelephonyDataState(DctConstants.State state) {
1158         switch(state) {
1159             case CONNECTING: // fall through
1160             case RETRYING:
1161                 return TelephonyManager.DATA_CONNECTING;
1162             case CONNECTED:
1163                 return TelephonyManager.DATA_CONNECTED;
1164             case DISCONNECTING:
1165                 return TelephonyManager.DATA_DISCONNECTING;
1166             case IDLE: // fall through
1167             case FAILED: // fall through
1168             default:
1169                 return TelephonyManager.DATA_DISCONNECTED;
1170         }
1171     }
1172 
1173     /** Return the Precise Data Connection State information */
getPreciseDataConnectionState( String apnType, boolean isSuspended, int networkType)1174     public @NonNull PreciseDataConnectionState getPreciseDataConnectionState(
1175             String apnType, boolean isSuspended, int networkType) {
1176 
1177         int telState = convertDctStateToTelephonyDataState(getState(apnType));
1178         // Since suspended isn't actually reported by the DCT, do a fixup based on current
1179         // voice call state and device + rat capability
1180         if ((telState == TelephonyManager.DATA_CONNECTED
1181                 || telState == TelephonyManager.DATA_DISCONNECTING)
1182                 && isSuspended) {
1183             telState = TelephonyManager.DATA_SUSPENDED;
1184         }
1185 
1186         ApnSetting apnSetting = getActiveApnSetting(apnType);
1187         int apnTypesBitmask = ApnSetting.getApnTypesBitmaskFromString(apnType);
1188 
1189         // TODO: should the data fail cause be populated?
1190         return new PreciseDataConnectionState(
1191                 telState, networkType, apnTypesBitmask, apnType,
1192                 getLinkProperties(apnType),
1193                 DataFailCause.NONE, apnSetting);
1194     }
1195 
1196     /**
1197      * Return a better connection state between {@code stateA} and {@code stateB}. Check
1198      * {@link #DATA_CONNECTION_STATE_PRIORITIES} for the details.
1199      * @return the better connection state between {@code stateA} and {@code stateB}.
1200      */
getBetterConnectionState( DctConstants.State stateA, DctConstants.State stateB)1201     private static DctConstants.State getBetterConnectionState(
1202             DctConstants.State stateA, DctConstants.State stateB) {
1203         int idxA = ArrayUtils.indexOf(DATA_CONNECTION_STATE_PRIORITIES, stateA);
1204         int idxB = ArrayUtils.indexOf(DATA_CONNECTION_STATE_PRIORITIES, stateB);
1205         return idxA >= idxB ? stateA : stateB;
1206     }
1207 
1208     // Return if apn type is a provisioning apn.
isProvisioningApn(String apnType)1209     private boolean isProvisioningApn(String apnType) {
1210         ApnContext apnContext = mApnContexts.get(apnType);
1211         if (apnContext != null) {
1212             return apnContext.isProvisioningApn();
1213         }
1214         return false;
1215     }
1216 
1217     //****** Called from ServiceStateTracker
1218     /**
1219      * Invoked when ServiceStateTracker observes a transition from GPRS
1220      * attach to detach.
1221      */
onDataConnectionDetached()1222     private void onDataConnectionDetached() {
1223         /*
1224          * We presently believe it is unnecessary to tear down the PDP context
1225          * when GPRS detaches, but we should stop the network polling.
1226          */
1227         if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
1228         stopNetStatPoll();
1229         stopDataStallAlarm();
1230         mPhone.notifyAllActiveDataConnections();
1231         mAttached.set(false);
1232     }
1233 
onDataConnectionAttached()1234     private void onDataConnectionAttached() {
1235         if (DBG) log("onDataConnectionAttached");
1236         mAttached.set(true);
1237         if (isAnyDataConnected()) {
1238             if (DBG) log("onDataConnectionAttached: start polling notify attached");
1239             startNetStatPoll();
1240             startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
1241             mPhone.notifyAllActiveDataConnections();
1242         }
1243         if (mAutoAttachOnCreationConfig) {
1244             mAutoAttachEnabled.set(true);
1245         }
1246         setupDataOnAllConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS);
1247     }
1248 
1249     /**
1250      * Check if it is allowed to make a data connection (without checking APN context specific
1251      * conditions).
1252      *
1253      * @param dataConnectionReasons Data connection allowed or disallowed reasons as the output
1254      *                              param. It's okay to pass null here and no reasons will be
1255      *                              provided.
1256      * @return True if data connection is allowed, otherwise false.
1257      */
isDataAllowed(DataConnectionReasons dataConnectionReasons)1258     public boolean isDataAllowed(DataConnectionReasons dataConnectionReasons) {
1259         return isDataAllowed(null, REQUEST_TYPE_NORMAL, dataConnectionReasons);
1260     }
1261 
1262     /**
1263      * Check if it is allowed to make a data connection for a given APN type.
1264      *
1265      * @param apnContext APN context. If passing null, then will only check general but not APN
1266      *                   specific conditions (e.g. APN state, metered/unmetered APN).
1267      * @param requestType Setup data request type.
1268      * @param dataConnectionReasons Data connection allowed or disallowed reasons as the output
1269      *                              param. It's okay to pass null here and no reasons will be
1270      *                              provided.
1271      * @return True if data connection is allowed, otherwise false.
1272      */
isDataAllowed(ApnContext apnContext, @RequestNetworkType int requestType, DataConnectionReasons dataConnectionReasons)1273     public boolean isDataAllowed(ApnContext apnContext, @RequestNetworkType int requestType,
1274                                  DataConnectionReasons dataConnectionReasons) {
1275         // Step 1: Get all environment conditions.
1276         // Step 2: Special handling for emergency APN.
1277         // Step 3. Build disallowed reasons.
1278         // Step 4: Determine if data should be allowed in some special conditions.
1279 
1280         DataConnectionReasons reasons = new DataConnectionReasons();
1281 
1282         int requestApnType = 0;
1283         if (apnContext != null) {
1284             requestApnType = apnContext.getApnTypeBitmask();
1285         }
1286 
1287         // Step 1: Get all environment conditions.
1288         final boolean internalDataEnabled = mDataEnabledSettings.isInternalDataEnabled();
1289         boolean attachedState = mAttached.get();
1290         boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
1291         boolean radioStateFromCarrier = mPhone.getServiceStateTracker().getPowerStateFromCarrier();
1292         // TODO: Remove this hack added by ag/641832.
1293         int dataRat = getDataRat();
1294         if (dataRat == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
1295             desiredPowerState = true;
1296             radioStateFromCarrier = true;
1297         }
1298 
1299         boolean defaultDataSelected = SubscriptionManager.isValidSubscriptionId(
1300                 SubscriptionManager.getDefaultDataSubscriptionId());
1301 
1302         boolean isMeteredApnType = apnContext == null
1303                 || ApnSettingUtils.isMeteredApnType(requestApnType, mPhone);
1304 
1305         PhoneConstants.State phoneState = PhoneConstants.State.IDLE;
1306         // Note this is explicitly not using mPhone.getState.  See b/19090488.
1307         // mPhone.getState reports the merge of CS and PS (volte) voice call state
1308         // but we only care about CS calls here for data/voice concurrency issues.
1309         // Calling getCallTracker currently gives you just the CS side where the
1310         // ImsCallTracker is held internally where applicable.
1311         // This should be redesigned to ask explicitly what we want:
1312         // voiceCallStateAllowDataCall, or dataCallAllowed or something similar.
1313         if (mPhone.getCallTracker() != null) {
1314             phoneState = mPhone.getCallTracker().getState();
1315         }
1316 
1317         // Step 2: Special handling for emergency APN.
1318         if (apnContext != null
1319                 && requestApnType == ApnSetting.TYPE_EMERGENCY
1320                 && apnContext.isConnectable()) {
1321             // If this is an emergency APN, as long as the APN is connectable, we
1322             // should allow it.
1323             if (dataConnectionReasons != null) {
1324                 dataConnectionReasons.add(DataAllowedReasonType.EMERGENCY_APN);
1325             }
1326             // Bail out without further checks.
1327             return true;
1328         }
1329 
1330         // Step 3. Build disallowed reasons.
1331         if (apnContext != null && !apnContext.isConnectable()) {
1332             DctConstants.State state = apnContext.getState();
1333             if (state == DctConstants.State.CONNECTED) {
1334                 reasons.add(DataDisallowedReasonType.DATA_ALREADY_CONNECTED);
1335             } else if (state == DctConstants.State.DISCONNECTING) {
1336                 reasons.add(DataDisallowedReasonType.DATA_IS_DISCONNECTING);
1337             } else if (state == DctConstants.State.CONNECTING) {
1338                 reasons.add(DataDisallowedReasonType.DATA_IS_CONNECTING);
1339             } else {
1340                 reasons.add(DataDisallowedReasonType.APN_NOT_CONNECTABLE);
1341             }
1342         }
1343 
1344         // In legacy mode, if RAT is IWLAN then don't allow default/IA PDP at all.
1345         // Rest of APN types can be evaluated for remaining conditions.
1346         if ((apnContext != null && requestApnType == TYPE_DEFAULT
1347                 || requestApnType == TYPE_IA)
1348                 && mPhone.getTransportManager().isInLegacyMode()
1349                 && dataRat == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
1350             reasons.add(DataDisallowedReasonType.ON_IWLAN);
1351         }
1352 
1353         if (shouldRestrictDataForEcbm() || mPhone.isInEmergencyCall()) {
1354             reasons.add(DataDisallowedReasonType.IN_ECBM);
1355         }
1356 
1357         if (!attachedState && !shouldAutoAttach() && requestType != REQUEST_TYPE_HANDOVER) {
1358             reasons.add(DataDisallowedReasonType.NOT_ATTACHED);
1359         }
1360         if (mPhone.getSubId() == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1361             reasons.add(DataDisallowedReasonType.SIM_NOT_READY);
1362         }
1363         if (phoneState != PhoneConstants.State.IDLE
1364                 && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
1365             reasons.add(DataDisallowedReasonType.INVALID_PHONE_STATE);
1366             reasons.add(DataDisallowedReasonType.CONCURRENT_VOICE_DATA_NOT_ALLOWED);
1367         }
1368         if (!internalDataEnabled) {
1369             reasons.add(DataDisallowedReasonType.INTERNAL_DATA_DISABLED);
1370         }
1371         if (!defaultDataSelected) {
1372             reasons.add(DataDisallowedReasonType.DEFAULT_DATA_UNSELECTED);
1373         }
1374         if (mPhone.getServiceState().getDataRoaming() && !getDataRoamingEnabled()) {
1375             reasons.add(DataDisallowedReasonType.ROAMING_DISABLED);
1376         }
1377         if (mIsPsRestricted) {
1378             reasons.add(DataDisallowedReasonType.PS_RESTRICTED);
1379         }
1380         if (!desiredPowerState) {
1381             reasons.add(DataDisallowedReasonType.UNDESIRED_POWER_STATE);
1382         }
1383         if (!radioStateFromCarrier) {
1384             reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER);
1385         }
1386 
1387         if (apnContext != null) {
1388             // If the transport has been already switched to the other transport, we should not
1389             // allow the data setup. The only exception is the handover case, where we setup
1390             // handover data connection before switching the transport.
1391             if (mTransportType != mPhone.getTransportManager().getCurrentTransport(
1392                     apnContext.getApnTypeBitmask()) && requestType != REQUEST_TYPE_HANDOVER) {
1393                 reasons.add(DataDisallowedReasonType.ON_OTHER_TRANSPORT);
1394             }
1395         }
1396 
1397         boolean isDataEnabled = apnContext == null ? mDataEnabledSettings.isDataEnabled()
1398                 : mDataEnabledSettings.isDataEnabled(requestApnType);
1399 
1400         if (!isDataEnabled) {
1401             reasons.add(DataDisallowedReasonType.DATA_DISABLED);
1402         }
1403 
1404         // If there are hard disallowed reasons, we should not allow data connection no matter what.
1405         if (reasons.containsHardDisallowedReasons()) {
1406             if (dataConnectionReasons != null) {
1407                 dataConnectionReasons.copyFrom(reasons);
1408             }
1409             return false;
1410         }
1411 
1412         // Step 4: Determine if data should be allowed in some special conditions.
1413 
1414         // At this point, if data is not allowed, it must be because of the soft reasons. We
1415         // should start to check some special conditions that data will be allowed.
1416         if (!reasons.allowed()) {
1417             // Check if the transport is WLAN ie wifi (for AP-assisted mode devices)
1418             if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
1419                 reasons.add(DataAllowedReasonType.UNMETERED_APN);
1420             // Or if the data is on cellular, and the APN type is determined unmetered by the
1421             // configuration.
1422             } else if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
1423                     && !isMeteredApnType && requestApnType != TYPE_DEFAULT) {
1424                 reasons.add(DataAllowedReasonType.UNMETERED_APN);
1425             }
1426 
1427             // If the request is restricted and there are only soft disallowed reasons (e.g. data
1428             // disabled, data roaming disabled) existing, we should allow the data.
1429             if (apnContext != null
1430                     && apnContext.hasRestrictedRequests(true)
1431                     && !reasons.allowed()) {
1432                 reasons.add(DataAllowedReasonType.RESTRICTED_REQUEST);
1433             }
1434         } else {
1435             // If there is no disallowed reasons, then we should allow the data request with
1436             // normal reason.
1437             reasons.add(DataAllowedReasonType.NORMAL);
1438         }
1439 
1440         if (dataConnectionReasons != null) {
1441             dataConnectionReasons.copyFrom(reasons);
1442         }
1443 
1444         return reasons.allowed();
1445     }
1446 
1447     // arg for setupDataOnAllConnectableApns
1448     protected enum RetryFailures {
1449         // retry failed networks always (the old default)
1450         ALWAYS,
1451         // retry only when a substantial change has occurred.  Either:
1452         // 1) we were restricted by voice/data concurrency and aren't anymore
1453         // 2) our apn list has change
1454         ONLY_ON_CHANGE
1455     };
1456 
setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures)1457     protected void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) {
1458         if (VDBG) log("setupDataOnAllConnectableApns: " + reason);
1459 
1460         if (DBG && !VDBG) {
1461             StringBuilder sb = new StringBuilder(120);
1462             for (ApnContext apnContext : mPrioritySortedApnContexts) {
1463                 sb.append(apnContext.getApnType());
1464                 sb.append(":[state=");
1465                 sb.append(apnContext.getState());
1466                 sb.append(",enabled=");
1467                 sb.append(apnContext.isEnabled());
1468                 sb.append("] ");
1469             }
1470             log("setupDataOnAllConnectableApns: " + reason + " " + sb);
1471         }
1472 
1473         for (ApnContext apnContext : mPrioritySortedApnContexts) {
1474             setupDataOnConnectableApn(apnContext, reason, retryFailures);
1475         }
1476     }
1477 
setupDataOnConnectableApn(ApnContext apnContext, String reason, RetryFailures retryFailures)1478     protected void setupDataOnConnectableApn(ApnContext apnContext, String reason,
1479             RetryFailures retryFailures) {
1480         if (VDBG) log("setupDataOnAllConnectableApns: apnContext " + apnContext);
1481 
1482         if (apnContext.getState() == DctConstants.State.FAILED
1483                 || apnContext.getState() == DctConstants.State.RETRYING) {
1484             if (retryFailures == RetryFailures.ALWAYS) {
1485                 apnContext.releaseDataConnection(reason);
1486             } else if (!apnContext.isConcurrentVoiceAndDataAllowed()
1487                     && mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
1488                 // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed
1489                 apnContext.releaseDataConnection(reason);
1490             }
1491         }
1492         if (apnContext.isConnectable()) {
1493             log("isConnectable() call trySetupData");
1494             apnContext.setReason(reason);
1495             trySetupData(apnContext, REQUEST_TYPE_NORMAL);
1496         }
1497     }
1498 
shouldRestrictDataForEcbm()1499     private boolean shouldRestrictDataForEcbm() {
1500         boolean isInEcm = mPhone.isInEcm();
1501         boolean isInImsEcm = mPhone.getImsPhone() != null && mPhone.getImsPhone().isInImsEcm();
1502         log("shouldRestrictDataForEcbm: isInEcm=" + isInEcm + " isInImsEcm=" + isInImsEcm);
1503         return isInEcm && !isInImsEcm;
1504     }
1505 
trySetupData(ApnContext apnContext, @RequestNetworkType int requestType)1506     private boolean trySetupData(ApnContext apnContext, @RequestNetworkType int requestType) {
1507 
1508         if (mPhone.getSimulatedRadioControl() != null) {
1509             // Assume data is connected on the simulator
1510             // FIXME  this can be improved
1511             apnContext.setState(DctConstants.State.CONNECTED);
1512             mPhone.notifyDataConnection(apnContext.getApnType());
1513 
1514             log("trySetupData: X We're on the simulator; assuming connected retValue=true");
1515             return true;
1516         }
1517 
1518         DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
1519         boolean isDataAllowed = isDataAllowed(apnContext, requestType, dataConnectionReasons);
1520         String logStr = "trySetupData for APN type " + apnContext.getApnType() + ", reason: "
1521                 + apnContext.getReason() + ", requestType=" + requestTypeToString(requestType)
1522                 + ". " + dataConnectionReasons.toString();
1523         if (DBG) log(logStr);
1524         apnContext.requestLog(logStr);
1525         if (isDataAllowed) {
1526             if (apnContext.getState() == DctConstants.State.FAILED) {
1527                 String str = "trySetupData: make a FAILED ApnContext IDLE so its reusable";
1528                 if (DBG) log(str);
1529                 apnContext.requestLog(str);
1530                 apnContext.setState(DctConstants.State.IDLE);
1531             }
1532             int radioTech = getDataRat();
1533             if (radioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN && mPhone.getServiceState()
1534                     .getState() == ServiceState.STATE_IN_SERVICE) {
1535                 radioTech = getVoiceRat();
1536             }
1537             log("service state=" + mPhone.getServiceState());
1538             apnContext.setConcurrentVoiceAndDataAllowed(mPhone.getServiceStateTracker()
1539                     .isConcurrentVoiceAndDataAllowed());
1540             if (apnContext.getState() == DctConstants.State.IDLE) {
1541                 ArrayList<ApnSetting> waitingApns =
1542                         buildWaitingApns(apnContext.getApnType(), radioTech);
1543                 if (waitingApns.isEmpty()) {
1544                     ApnSetting apn = apnContext != null ? apnContext.getApnSetting() : null;
1545                     mPhone.notifyDataConnectionFailed(apnContext.getApnType(),
1546                             apn != null ? apn.getApnName() : null,
1547                             DataFailCause.MISSING_UNKNOWN_APN);
1548                     String str = "trySetupData: X No APN found retValue=false";
1549                     if (DBG) log(str);
1550                     apnContext.requestLog(str);
1551                     return false;
1552                 } else {
1553                     apnContext.setWaitingApns(waitingApns);
1554                     if (DBG) {
1555                         log ("trySetupData: Create from mAllApnSettings : "
1556                                     + apnListToString(mAllApnSettings));
1557                     }
1558                 }
1559             }
1560 
1561             boolean retValue = setupData(apnContext, radioTech, requestType);
1562 
1563             if (DBG) log("trySetupData: X retValue=" + retValue);
1564             return retValue;
1565         } else {
1566             StringBuilder str = new StringBuilder();
1567 
1568             str.append("trySetupData failed. apnContext = [type=" + apnContext.getApnType()
1569                     + ", mState=" + apnContext.getState() + ", apnEnabled="
1570                     + apnContext.isEnabled() + ", mDependencyMet="
1571                     + apnContext.isDependencyMet() + "] ");
1572 
1573             if (!mDataEnabledSettings.isDataEnabled()) {
1574                 str.append("isDataEnabled() = false. " + mDataEnabledSettings);
1575             }
1576 
1577             // If this is a data retry, we should set the APN state to FAILED so it won't stay
1578             // in RETRYING forever.
1579             if (apnContext.getState() == DctConstants.State.RETRYING) {
1580                 apnContext.setState(DctConstants.State.FAILED);
1581                 str.append(" Stop retrying.");
1582             }
1583 
1584             if (DBG) log(str.toString());
1585             apnContext.requestLog(str.toString());
1586             return false;
1587         }
1588     }
1589 
1590     /**
1591      * Clean up all data connections. Note this is just detach the APN context from the data
1592      * connection. After all APN contexts are detached from the data connection, the data
1593      * connection will be torn down.
1594      *
1595      * @param reason Reason for the clean up.
1596      */
cleanUpAllConnections(String reason)1597     public void cleanUpAllConnections(String reason) {
1598         log("cleanUpAllConnections");
1599         Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_ALL_CONNECTIONS);
1600         msg.obj = reason;
1601         sendMessage(msg);
1602     }
1603 
1604     /**
1605      * Clean up all data connections by detaching the APN contexts from the data connections, which
1606      * eventually tearing down all data connections after all APN contexts are detached from the
1607      * data connections.
1608      *
1609      * @param detach {@code true} if detaching APN context from the underlying data connection (when
1610      * no other APN context is attached to the data connection, the data connection will be torn
1611      * down.) {@code false} to only reset the data connection's state machine.
1612      *
1613      * @param reason reason for the clean up.
1614      * @return boolean - true if we did cleanup any connections, false if they
1615      *                   were already all disconnected.
1616      */
cleanUpAllConnectionsInternal(boolean detach, String reason)1617     private boolean cleanUpAllConnectionsInternal(boolean detach, String reason) {
1618         if (DBG) log("cleanUpAllConnectionsInternal: detach=" + detach + " reason=" + reason);
1619         boolean didDisconnect = false;
1620         boolean disableMeteredOnly = false;
1621 
1622         // reasons that only metered apn will be torn down
1623         if (!TextUtils.isEmpty(reason)) {
1624             disableMeteredOnly = reason.equals(Phone.REASON_DATA_SPECIFIC_DISABLED) ||
1625                     reason.equals(Phone.REASON_ROAMING_ON) ||
1626                     reason.equals(Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN);
1627         }
1628 
1629         for (ApnContext apnContext : mApnContexts.values()) {
1630             // Exclude the IMS APN from single data connection case.
1631             if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION)
1632                     && apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) {
1633                 continue;
1634             }
1635 
1636             if (shouldCleanUpConnection(apnContext, disableMeteredOnly,
1637                     reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION))) {
1638                 // TODO - only do cleanup if not disconnected
1639                 if (apnContext.isDisconnected() == false) didDisconnect = true;
1640                 apnContext.setReason(reason);
1641                 cleanUpConnectionInternal(detach, RELEASE_TYPE_DETACH, apnContext);
1642             } else if (DBG) {
1643                 log("cleanUpAllConnectionsInternal: APN type " + apnContext.getApnType()
1644                         + " shouldn't be cleaned up.");
1645             }
1646         }
1647 
1648         stopNetStatPoll();
1649         stopDataStallAlarm();
1650 
1651         // TODO: Do we need mRequestedApnType?
1652         mRequestedApnType = ApnSetting.TYPE_DEFAULT;
1653 
1654         log("cleanUpAllConnectionsInternal: mDisconnectPendingCount = "
1655                 + mDisconnectPendingCount);
1656         if (detach && mDisconnectPendingCount == 0) {
1657             notifyAllDataDisconnected();
1658         }
1659 
1660         return didDisconnect;
1661     }
1662 
shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly, boolean singlePdn)1663     boolean shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly,
1664             boolean singlePdn) {
1665         if (apnContext == null) return false;
1666 
1667         // If APN setting is not null and the reason is single PDN arbitration, clean up connection.
1668         ApnSetting apnSetting = apnContext.getApnSetting();
1669         if (apnSetting != null && singlePdn) return true;
1670 
1671         // If meteredOnly is false, clean up all connections.
1672         if (!disableMeteredOnly) return true;
1673 
1674         // If meteredOnly is true, and apnSetting is null or it's un-metered, no need to clean up.
1675         if (apnSetting == null || !ApnSettingUtils.isMetered(apnSetting, mPhone)) return false;
1676 
1677         boolean isRoaming = mPhone.getServiceState().getDataRoaming();
1678         boolean isDataRoamingDisabled = !getDataRoamingEnabled();
1679         boolean isDataDisabled = !mDataEnabledSettings.isDataEnabled(
1680                 apnSetting.getApnTypeBitmask());
1681 
1682         // Should clean up if its data is disabled, or data roaming is disabled while roaming.
1683         return isDataDisabled || (isRoaming && isDataRoamingDisabled);
1684     }
1685 
1686     /**
1687      * Detach the APN context from the associated data connection. This data connection might be
1688      * torn down if no other APN context is attached to it.
1689      *
1690      * @param apnContext The APN context to be detached
1691      */
cleanUpConnection(ApnContext apnContext)1692     void cleanUpConnection(ApnContext apnContext) {
1693         if (DBG) log("cleanUpConnection: apnContext=" + apnContext);
1694         Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_CONNECTION);
1695         msg.arg2 = 0;
1696         msg.obj = apnContext;
1697         sendMessage(msg);
1698     }
1699 
1700     /**
1701      * Detach the APN context from the associated data connection. This data connection will be
1702      * torn down if no other APN context is attached to it.
1703      *
1704      * @param detach {@code true} if detaching APN context from the underlying data connection (when
1705      * no other APN context is attached to the data connection, the data connection will be torn
1706      * down.) {@code false} to only reset the data connection's state machine.
1707      * @param releaseType Data release type.
1708      * @param apnContext The APN context to be detached.
1709      */
cleanUpConnectionInternal(boolean detach, @ReleaseNetworkType int releaseType, ApnContext apnContext)1710     private void cleanUpConnectionInternal(boolean detach, @ReleaseNetworkType int releaseType,
1711                                            ApnContext apnContext) {
1712         if (apnContext == null) {
1713             if (DBG) log("cleanUpConnectionInternal: apn context is null");
1714             return;
1715         }
1716 
1717         DataConnection dataConnection = apnContext.getDataConnection();
1718         String str = "cleanUpConnectionInternal: detach=" + detach + " reason="
1719                 + apnContext.getReason();
1720         if (VDBG) log(str + " apnContext=" + apnContext);
1721         apnContext.requestLog(str);
1722         if (detach) {
1723             if (apnContext.isDisconnected()) {
1724                 // The request is detach and but ApnContext is not connected.
1725                 // If apnContext is not enabled anymore, break the linkage to the data connection.
1726                 apnContext.releaseDataConnection("");
1727             } else {
1728                 // Connection is still there. Try to clean up.
1729                 if (dataConnection != null) {
1730                     if (apnContext.getState() != DctConstants.State.DISCONNECTING) {
1731                         boolean disconnectAll = false;
1732                         if (PhoneConstants.APN_TYPE_DUN.equals(apnContext.getApnType())
1733                                 && ServiceState.isCdma(getDataRat())) {
1734                             if (DBG) {
1735                                 log("cleanUpConnectionInternal: disconnectAll DUN connection");
1736                             }
1737                             // For CDMA DUN, we need to tear it down immediately. A new data
1738                             // connection will be reestablished with correct profile id.
1739                             disconnectAll = true;
1740                         }
1741                         final int generation = apnContext.getConnectionGeneration();
1742                         str = "cleanUpConnectionInternal: tearing down"
1743                                 + (disconnectAll ? " all" : "") + " using gen#" + generation;
1744                         if (DBG) log(str + "apnContext=" + apnContext);
1745                         apnContext.requestLog(str);
1746                         Pair<ApnContext, Integer> pair = new Pair<>(apnContext, generation);
1747                         Message msg = obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair);
1748 
1749                         if (disconnectAll || releaseType == RELEASE_TYPE_HANDOVER) {
1750                             dataConnection.tearDownAll(apnContext.getReason(), releaseType, msg);
1751                         } else {
1752                             dataConnection.tearDown(apnContext, apnContext.getReason(), msg);
1753                         }
1754 
1755                         apnContext.setState(DctConstants.State.DISCONNECTING);
1756                         mDisconnectPendingCount++;
1757                     }
1758                 } else {
1759                     // apn is connected but no reference to the data connection.
1760                     // Should not be happen, but reset the state in case.
1761                     apnContext.setState(DctConstants.State.IDLE);
1762                     apnContext.requestLog("cleanUpConnectionInternal: connected, bug no dc");
1763                     mPhone.notifyDataConnection(apnContext.getApnType());
1764                 }
1765             }
1766         } else {
1767             // force clean up the data connection.
1768             if (dataConnection != null) dataConnection.reset();
1769             apnContext.setState(DctConstants.State.IDLE);
1770             mPhone.notifyDataConnection(apnContext.getApnType());
1771             apnContext.setDataConnection(null);
1772         }
1773 
1774         // Make sure reconnection alarm is cleaned up if there is no ApnContext
1775         // associated to the connection.
1776         if (dataConnection != null) {
1777             cancelReconnect(apnContext);
1778         }
1779         str = "cleanUpConnectionInternal: X detach=" + detach + " reason="
1780                 + apnContext.getReason();
1781         if (DBG) log(str + " apnContext=" + apnContext + " dc=" + apnContext.getDataConnection());
1782     }
1783 
1784     /**
1785      * Fetch the DUN apns
1786      * @return a list of DUN ApnSetting objects
1787      */
1788     @VisibleForTesting
fetchDunApns()1789     public @NonNull ArrayList<ApnSetting> fetchDunApns() {
1790         int bearer = getDataRat();
1791         ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>();
1792         ArrayList<ApnSetting> retDunSettings = new ArrayList<ApnSetting>();
1793 
1794         if (mPhone.getServiceState().getRoaming()) {
1795             CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
1796                     .getSystemService(Context.CARRIER_CONFIG_SERVICE);
1797             if (configManager != null) {
1798                 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
1799                 if (b != null) {
1800                     if (b.getBoolean(CarrierConfigManager.KEY_DISABLE_DUN_APN_WHILE_ROAMING)) {
1801                         return new ArrayList<>();
1802                     }
1803                 }
1804             }
1805         }
1806 
1807         // Places to look for tether APN in order: TETHER_DUN_APN setting (to be deprecated soon),
1808         // APN database
1809         String apnData = Settings.Global.getString(mResolver, Settings.Global.TETHER_DUN_APN);
1810         if (!TextUtils.isEmpty(apnData)) {
1811             dunCandidates.addAll(ApnSetting.arrayFromString(apnData));
1812             if (VDBG) log("fetchDunApns: dunCandidates from Setting: " + dunCandidates);
1813         }
1814 
1815         if (dunCandidates.isEmpty()) {
1816             if (!ArrayUtils.isEmpty(mAllApnSettings)) {
1817                 for (ApnSetting apn : mAllApnSettings) {
1818                     if (apn.canHandleType(ApnSetting.TYPE_DUN)) {
1819                         dunCandidates.add(apn);
1820                     }
1821                 }
1822                 if (VDBG) log("fetchDunApns: dunCandidates from database: " + dunCandidates);
1823             }
1824         }
1825 
1826         for (ApnSetting dunSetting : dunCandidates) {
1827             if (!dunSetting.canSupportNetworkType(
1828                     ServiceState.rilRadioTechnologyToNetworkType(bearer))) {
1829                 continue;
1830             }
1831             retDunSettings.add(dunSetting);
1832         }
1833 
1834         if (VDBG) log("fetchDunApns: dunSettings=" + retDunSettings);
1835         return retDunSettings;
1836     }
1837 
getPreferredApnSetId()1838     private int getPreferredApnSetId() {
1839         Cursor c = mPhone.getContext().getContentResolver()
1840                 .query(Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI,
1841                     "preferapnset/subId/" + mPhone.getSubId()),
1842                         new String[] {Telephony.Carriers.APN_SET_ID}, null, null, null);
1843         if (c == null) {
1844             loge("getPreferredApnSetId: cursor is null");
1845             return Telephony.Carriers.NO_APN_SET_ID;
1846         }
1847 
1848         int setId;
1849         if (c.getCount() < 1) {
1850             loge("getPreferredApnSetId: no APNs found");
1851             setId = Telephony.Carriers.NO_APN_SET_ID;
1852         } else {
1853             c.moveToFirst();
1854             setId = c.getInt(0 /* index of Telephony.Carriers.APN_SET_ID */);
1855         }
1856 
1857         if (!c.isClosed()) {
1858             c.close();
1859         }
1860         return setId;
1861     }
1862 
hasMatchedTetherApnSetting()1863     public boolean hasMatchedTetherApnSetting() {
1864         ArrayList<ApnSetting> matches = fetchDunApns();
1865         log("hasMatchedTetherApnSetting: APNs=" + matches);
1866         return matches.size() > 0;
1867     }
1868 
1869     /**
1870      * @return the {@link DataConnection} with the given context id {@code cid}.
1871      */
getDataConnectionByContextId(int cid)1872     public DataConnection getDataConnectionByContextId(int cid) {
1873         return mDcc.getActiveDcByCid(cid);
1874     }
1875 
1876     /**
1877      * @return the {@link DataConnection} with the given APN context. Null if no data connection
1878      * is found.
1879      */
getDataConnectionByApnType(String apnType)1880     public @Nullable DataConnection getDataConnectionByApnType(String apnType) {
1881         // TODO: Clean up all APN type in string usage
1882         ApnContext apnContext = mApnContexts.get(apnType);
1883         if (apnContext != null) {
1884             return apnContext.getDataConnection();
1885         }
1886         return null;
1887     }
1888 
isPermanentFailure(@ataFailureCause int dcFailCause)1889     boolean isPermanentFailure(@DataFailureCause int dcFailCause) {
1890         return (DataFailCause.isPermanentFailure(mPhone.getContext(), dcFailCause,
1891                 mPhone.getSubId())
1892                 && (mAttached.get() == false || dcFailCause != DataFailCause.SIGNAL_LOST));
1893     }
1894 
findFreeDataConnection()1895     private DataConnection findFreeDataConnection() {
1896         for (DataConnection dataConnection : mDataConnections.values()) {
1897             boolean inUse = false;
1898             for (ApnContext apnContext : mApnContexts.values()) {
1899                 if (apnContext.getDataConnection() == dataConnection) {
1900                     inUse = true;
1901                     break;
1902                 }
1903             }
1904             if (!inUse) {
1905                 if (DBG) {
1906                     log("findFreeDataConnection: found free DataConnection=" + dataConnection);
1907                 }
1908                 return dataConnection;
1909             }
1910         }
1911         log("findFreeDataConnection: NO free DataConnection");
1912         return null;
1913     }
1914 
1915     /**
1916      * Setup a data connection based on given APN type.
1917      *
1918      * @param apnContext APN context
1919      * @param radioTech RAT of the data connection
1920      * @param requestType Data request type
1921      * @return True if successful, otherwise false.
1922      */
setupData(ApnContext apnContext, int radioTech, @RequestNetworkType int requestType)1923     private boolean setupData(ApnContext apnContext, int radioTech,
1924                               @RequestNetworkType int requestType) {
1925         if (DBG) {
1926             log("setupData: apnContext=" + apnContext + ", requestType="
1927                     + requestTypeToString(requestType));
1928         }
1929         apnContext.requestLog("setupData. requestType=" + requestTypeToString(requestType));
1930         ApnSetting apnSetting;
1931         DataConnection dataConnection = null;
1932 
1933         apnSetting = apnContext.getNextApnSetting();
1934 
1935         if (apnSetting == null) {
1936             if (DBG) log("setupData: return for no apn found!");
1937             return false;
1938         }
1939 
1940         // profile id is only meaningful when the profile is persistent on the modem.
1941         int profileId = DATA_PROFILE_INVALID;
1942         if (apnSetting.isPersistent()) {
1943             profileId = apnSetting.getProfileId();
1944             if (profileId == DATA_PROFILE_DEFAULT) {
1945                 profileId = getApnProfileID(apnContext.getApnType());
1946             }
1947         }
1948 
1949         // On CDMA, if we're explicitly asking for DUN, we need have
1950         // a dun-profiled connection so we can't share an existing one
1951         // On GSM/LTE we can share existing apn connections provided they support
1952         // this type.
1953         if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DUN)
1954                 || ServiceState.isGsm(getDataRat())) {
1955             dataConnection = checkForCompatibleDataConnection(apnContext);
1956             if (dataConnection != null) {
1957                 // Get the apn setting used by the data connection
1958                 ApnSetting dataConnectionApnSetting = dataConnection.getApnSetting();
1959                 if (dataConnectionApnSetting != null) {
1960                     // Setting is good, so use it.
1961                     apnSetting = dataConnectionApnSetting;
1962                 }
1963             }
1964         }
1965         if (dataConnection == null) {
1966             if (isOnlySingleDcAllowed(radioTech)) {
1967                 if (isHigherPriorityApnContextActive(apnContext)) {
1968                     if (DBG) {
1969                         log("setupData: Higher priority ApnContext active.  Ignoring call");
1970                     }
1971                     return false;
1972                 }
1973 
1974                 // Should not start cleanUp if the setupData is for IMS APN
1975                 // or retry of same APN(State==RETRYING).
1976                 if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)
1977                         && (apnContext.getState() != DctConstants.State.RETRYING)) {
1978                     // Only lower priority calls left.  Disconnect them all in this single PDP case
1979                     // so that we can bring up the requested higher priority call (once we receive
1980                     // response for deactivate request for the calls we are about to disconnect
1981                     if (cleanUpAllConnectionsInternal(true, Phone.REASON_SINGLE_PDN_ARBITRATION)) {
1982                         // If any call actually requested to be disconnected, means we can't
1983                         // bring up this connection yet as we need to wait for those data calls
1984                         // to be disconnected.
1985                         if (DBG) log("setupData: Some calls are disconnecting first."
1986                                 + " Wait and retry");
1987                         return false;
1988                     }
1989                 }
1990 
1991                 // No other calls are active, so proceed
1992                 if (DBG) log("setupData: Single pdp. Continue setting up data call.");
1993             }
1994 
1995             dataConnection = findFreeDataConnection();
1996 
1997             if (dataConnection == null) {
1998                 dataConnection = createDataConnection();
1999             }
2000 
2001             if (dataConnection == null) {
2002                 if (DBG) log("setupData: No free DataConnection and couldn't create one, WEIRD");
2003                 return false;
2004             }
2005         }
2006         final int generation = apnContext.incAndGetConnectionGeneration();
2007         if (DBG) {
2008             log("setupData: dc=" + dataConnection + " apnSetting=" + apnSetting + " gen#="
2009                     + generation);
2010         }
2011 
2012         apnContext.setDataConnection(dataConnection);
2013         apnContext.setApnSetting(apnSetting);
2014         apnContext.setState(DctConstants.State.CONNECTING);
2015         mPhone.notifyDataConnection(apnContext.getApnType());
2016 
2017         Message msg = obtainMessage();
2018         msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
2019         msg.obj = new Pair<ApnContext, Integer>(apnContext, generation);
2020 
2021         ApnSetting preferredApn = getPreferredApn();
2022         boolean isPreferredApn = apnSetting.equals(preferredApn);
2023         dataConnection.bringUp(apnContext, profileId, radioTech, msg, generation, requestType,
2024                 mPhone.getSubId(), isPreferredApn);
2025 
2026         if (DBG) {
2027             if (isPreferredApn) {
2028                 log("setupData: initing! isPreferredApn=" + isPreferredApn
2029                         + ", apnSetting={" + apnSetting.toString() + "}");
2030             } else {
2031                 String preferredApnStr = preferredApn == null ? "null" : preferredApn.toString();
2032                 log("setupData: initing! isPreferredApn=" + isPreferredApn
2033                         + ", apnSetting={" + apnSetting + "}"
2034                         + ", preferredApn={" + preferredApnStr + "}");
2035             }
2036         }
2037         return true;
2038     }
2039 
setInitialAttachApn()2040     protected void setInitialAttachApn() {
2041         ApnSetting iaApnSetting = null;
2042         ApnSetting defaultApnSetting = null;
2043         ApnSetting firstNonEmergencyApnSetting = null;
2044 
2045         log("setInitialApn: E mPreferredApn=" + mPreferredApn);
2046 
2047         if (mPreferredApn != null && mPreferredApn.canHandleType(ApnSetting.TYPE_IA)) {
2048               iaApnSetting = mPreferredApn;
2049         } else if (!mAllApnSettings.isEmpty()) {
2050             // Search for Initial APN setting and the first apn that can handle default
2051             for (ApnSetting apn : mAllApnSettings) {
2052                 if (firstNonEmergencyApnSetting == null
2053                         && !apn.isEmergencyApn()) {
2054                     firstNonEmergencyApnSetting = apn;
2055                     log("setInitialApn: firstNonEmergencyApnSetting="
2056                             + firstNonEmergencyApnSetting);
2057                 }
2058                 if (apn.canHandleType(ApnSetting.TYPE_IA)) {
2059                     // The Initial Attach APN is highest priority so use it if there is one
2060                     log("setInitialApn: iaApnSetting=" + apn);
2061                     iaApnSetting = apn;
2062                     break;
2063                 } else if ((defaultApnSetting == null)
2064                         && (apn.canHandleType(ApnSetting.TYPE_DEFAULT))) {
2065                     // Use the first default apn if no better choice
2066                     log("setInitialApn: defaultApnSetting=" + apn);
2067                     defaultApnSetting = apn;
2068                 }
2069             }
2070         }
2071 
2072         if ((iaApnSetting == null) && (defaultApnSetting == null) &&
2073                 !allowInitialAttachForOperator()) {
2074             log("Abort Initial attach");
2075             return;
2076         }
2077 
2078         // The priority of apn candidates from highest to lowest is:
2079         //   1) APN_TYPE_IA (Initial Attach)
2080         //   2) mPreferredApn, i.e. the current preferred apn
2081         //   3) The first apn that than handle APN_TYPE_DEFAULT
2082         //   4) The first APN we can find.
2083 
2084         ApnSetting initialAttachApnSetting = null;
2085         if (iaApnSetting != null) {
2086             if (DBG) log("setInitialAttachApn: using iaApnSetting");
2087             initialAttachApnSetting = iaApnSetting;
2088         } else if (mPreferredApn != null) {
2089             if (DBG) log("setInitialAttachApn: using mPreferredApn");
2090             initialAttachApnSetting = mPreferredApn;
2091         } else if (defaultApnSetting != null) {
2092             if (DBG) log("setInitialAttachApn: using defaultApnSetting");
2093             initialAttachApnSetting = defaultApnSetting;
2094         } else if (firstNonEmergencyApnSetting != null) {
2095             if (DBG) log("setInitialAttachApn: using firstNonEmergencyApnSetting");
2096             initialAttachApnSetting = firstNonEmergencyApnSetting;
2097         }
2098 
2099         if (initialAttachApnSetting == null) {
2100             if (DBG) log("setInitialAttachApn: X There in no available apn");
2101         } else {
2102             if (DBG) log("setInitialAttachApn: X selected Apn=" + initialAttachApnSetting);
2103 
2104             mDataServiceManager.setInitialAttachApn(createDataProfile(initialAttachApnSetting,
2105                             initialAttachApnSetting.equals(getPreferredApn())),
2106                     mPhone.getServiceState().getDataRoamingFromRegistration(), null);
2107         }
2108     }
2109 
allowInitialAttachForOperator()2110     protected boolean allowInitialAttachForOperator() {
2111         return true;
2112     }
2113 
2114     /**
2115      * Handles changes to the APN database.
2116      */
onApnChanged()2117     private void onApnChanged() {
2118         if (mPhone instanceof GsmCdmaPhone) {
2119             // The "current" may no longer be valid.  MMS depends on this to send properly. TBD
2120             ((GsmCdmaPhone)mPhone).updateCurrentCarrierInProvider();
2121         }
2122 
2123         // TODO: It'd be nice to only do this if the changed entrie(s)
2124         // match the current operator.
2125         if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
2126         createAllApnList();
2127         setDataProfilesAsNeeded();
2128         setInitialAttachApn();
2129         cleanUpConnectionsOnUpdatedApns(isAnyDataConnected(), Phone.REASON_APN_CHANGED);
2130 
2131         // FIXME: See bug 17426028 maybe no conditional is needed.
2132         if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
2133             setupDataOnAllConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS);
2134         }
2135     }
2136 
2137     /**
2138      * "Active" here means ApnContext isEnabled() and not in FAILED state
2139      * @param apnContext to compare with
2140      * @return true if higher priority active apn found
2141      */
isHigherPriorityApnContextActive(ApnContext apnContext)2142     private boolean isHigherPriorityApnContextActive(ApnContext apnContext) {
2143         if (apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) {
2144             return false;
2145         }
2146 
2147         for (ApnContext otherContext : mPrioritySortedApnContexts) {
2148             if (otherContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) {
2149                 continue;
2150             }
2151             if (apnContext.getApnType().equalsIgnoreCase(otherContext.getApnType())) return false;
2152             if (otherContext.isEnabled() && otherContext.getState() != DctConstants.State.FAILED) {
2153                 return true;
2154             }
2155         }
2156         return false;
2157     }
2158 
2159     /**
2160      * Reports if we support multiple connections or not.
2161      * This is a combination of factors, based on carrier and RAT.
2162      * @param rilRadioTech the RIL Radio Tech currently in use
2163      * @return true if only single DataConnection is allowed
2164      */
isOnlySingleDcAllowed(int rilRadioTech)2165     private boolean isOnlySingleDcAllowed(int rilRadioTech) {
2166         // Default single dc rats with no knowledge of carrier
2167         int[] singleDcRats = null;
2168         // get the carrier specific value, if it exists, from CarrierConfigManager.
2169         // generally configManager and bundle should not be null, but if they are it should be okay
2170         // to leave singleDcRats null as well
2171         CarrierConfigManager configManager = (CarrierConfigManager)
2172                 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
2173         if (configManager != null) {
2174             PersistableBundle bundle = configManager.getConfigForSubId(mPhone.getSubId());
2175             if (bundle != null) {
2176                 singleDcRats = bundle.getIntArray(
2177                         CarrierConfigManager.KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY);
2178             }
2179         }
2180         boolean onlySingleDcAllowed = false;
2181         if (TelephonyUtils.IS_DEBUGGABLE
2182                 && SystemProperties.getBoolean("persist.telephony.test.singleDc", false)) {
2183             onlySingleDcAllowed = true;
2184         }
2185         if (singleDcRats != null) {
2186             for (int i=0; i < singleDcRats.length && onlySingleDcAllowed == false; i++) {
2187                 if (rilRadioTech == singleDcRats[i]) onlySingleDcAllowed = true;
2188             }
2189         }
2190 
2191         if (DBG) log("isOnlySingleDcAllowed(" + rilRadioTech + "): " + onlySingleDcAllowed);
2192         return onlySingleDcAllowed;
2193     }
2194 
sendRestartRadio()2195     void sendRestartRadio() {
2196         if (DBG)log("sendRestartRadio:");
2197         Message msg = obtainMessage(DctConstants.EVENT_RESTART_RADIO);
2198         sendMessage(msg);
2199     }
2200 
restartRadio()2201     private void restartRadio() {
2202         if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
2203         cleanUpAllConnectionsInternal(true, Phone.REASON_RADIO_TURNED_OFF);
2204         mPhone.getServiceStateTracker().powerOffRadioSafely();
2205         /* Note: no need to call setRadioPower(true).  Assuming the desired
2206          * radio power state is still ON (as tracked by ServiceStateTracker),
2207          * ServiceStateTracker will call setRadioPower when it receives the
2208          * RADIO_STATE_CHANGED notification for the power off.  And if the
2209          * desired power state has changed in the interim, we don't want to
2210          * override it with an unconditional power on.
2211          */
2212     }
2213 
2214     /**
2215      * Return true if data connection need to be setup after disconnected due to
2216      * reason.
2217      *
2218      * @param apnContext APN context
2219      * @return true if try setup data connection is need for this reason
2220      */
retryAfterDisconnected(ApnContext apnContext)2221     private boolean retryAfterDisconnected(ApnContext apnContext) {
2222         boolean retry = true;
2223         String reason = apnContext.getReason();
2224 
2225         if (Phone.REASON_RADIO_TURNED_OFF.equals(reason) || (isOnlySingleDcAllowed(getDataRat())
2226                 && isHigherPriorityApnContextActive(apnContext))) {
2227             retry = false;
2228         }
2229         return retry;
2230     }
2231 
startReconnect(long delay, ApnContext apnContext)2232     protected void startReconnect(long delay, ApnContext apnContext) {
2233         Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
2234                        mPhone.getSubId(), mTransportType, apnContext);
2235         cancelReconnect(apnContext);
2236         sendMessageDelayed(msg, delay);
2237 
2238         if (DBG) {
2239             log("startReconnect: delay=" + delay + " apn="
2240                     + apnContext + "reason: " + apnContext.getReason()
2241                     + " subId: " + mPhone.getSubId());
2242         }
2243     }
2244 
2245     /**
2246      * Cancels the alarm associated with apnContext.
2247      *
2248      * @param apnContext on which the alarm should be stopped.
2249      */
cancelReconnect(ApnContext apnContext)2250     protected void cancelReconnect(ApnContext apnContext) {
2251         if (apnContext == null) return;
2252 
2253         if (DBG) {
2254             log("cancelReconnect: apn=" + apnContext);
2255         }
2256         removeMessages(DctConstants.EVENT_DATA_RECONNECT, apnContext);
2257     }
2258 
2259     /**
2260      * Read configuration. Note this must be called after carrier config is ready.
2261      */
readConfiguration()2262     private void readConfiguration() {
2263         log("readConfiguration");
2264         if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
2265             // Auto attach is for cellular only.
2266             mAutoAttachOnCreationConfig = mPhone.getContext().getResources()
2267                     .getBoolean(com.android.internal.R.bool.config_auto_attach_data_on_creation);
2268         }
2269 
2270         mAutoAttachEnabled.set(false);
2271         setDefaultDataRoamingEnabled();
2272         read5GConfiguration();
2273         registerSettingsObserver();
2274         mConfigReady = true;
2275     }
2276 
2277     /**
2278      * @return {@code true} if carrier config has been applied.
2279      */
isCarrierConfigApplied()2280     private boolean isCarrierConfigApplied() {
2281         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
2282                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
2283         if (configManager != null) {
2284             PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
2285             if (b != null) {
2286                 return CarrierConfigManager.isConfigForIdentifiedCarrier(b);
2287             }
2288         }
2289         return false;
2290     }
2291 
onCarrierConfigChanged()2292     private void onCarrierConfigChanged() {
2293         if (DBG) log("onCarrierConfigChanged");
2294 
2295         if (!isCarrierConfigApplied()) {
2296             log("onCarrierConfigChanged: Carrier config is not ready yet.");
2297             return;
2298         }
2299 
2300         readConfiguration();
2301 
2302         if (mSimState == TelephonyManager.SIM_STATE_LOADED) {
2303             createAllApnList();
2304             setDataProfilesAsNeeded();
2305             setInitialAttachApn();
2306             sortApnContextByPriority();
2307             cleanUpConnectionsOnUpdatedApns(true, Phone.REASON_CARRIER_CHANGE);
2308             setupDataOnAllConnectableApns(Phone.REASON_CARRIER_CHANGE, RetryFailures.ALWAYS);
2309         } else {
2310             log("onCarrierConfigChanged: SIM is not loaded yet.");
2311         }
2312     }
2313 
onSimAbsent()2314     private void onSimAbsent() {
2315         if (DBG) log("onSimAbsent");
2316 
2317         mConfigReady = false;
2318         cleanUpAllConnectionsInternal(true, Phone.REASON_SIM_NOT_READY);
2319         mAllApnSettings.clear();
2320         mAutoAttachOnCreationConfig = false;
2321         // Clear auto attach as modem is expected to do a new attach once SIM is ready
2322         mAutoAttachEnabled.set(false);
2323         // In no-sim case, we should still send the emergency APN to the modem, if there is any.
2324         createAllApnList();
2325         setDataProfilesAsNeeded();
2326     }
2327 
onSimStateUpdated(@imState int simState)2328     private void onSimStateUpdated(@SimState int simState) {
2329         mSimState = simState;
2330 
2331         if (DBG) {
2332             log("onSimStateUpdated: state=" + SubscriptionInfoUpdater.simStateString(mSimState));
2333         }
2334 
2335         if (mSimState == TelephonyManager.SIM_STATE_ABSENT) {
2336             onSimAbsent();
2337         } else if (mSimState == TelephonyManager.SIM_STATE_LOADED) {
2338             if (mConfigReady) {
2339                 createAllApnList();
2340                 setDataProfilesAsNeeded();
2341                 setInitialAttachApn();
2342                 setupDataOnAllConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS);
2343             } else {
2344                 log("onSimStateUpdated: config not ready yet.");
2345             }
2346         }
2347     }
2348 
checkForCompatibleDataConnection(ApnContext apnContext)2349     private DataConnection checkForCompatibleDataConnection(ApnContext apnContext) {
2350         int apnType = apnContext.getApnTypeBitmask();
2351         ArrayList<ApnSetting> dunSettings = null;
2352 
2353         if (ApnSetting.TYPE_DUN == apnType) {
2354             dunSettings = sortApnListByPreferred(fetchDunApns());
2355         }
2356         if (DBG) {
2357             log("checkForCompatibleDataConnection: apnContext=" + apnContext);
2358         }
2359 
2360         DataConnection potentialDc = null;
2361         for (DataConnection curDc : mDataConnections.values()) {
2362             if (curDc != null) {
2363                 ApnSetting apnSetting = curDc.getApnSetting();
2364                 log("apnSetting: " + apnSetting);
2365                 if (dunSettings != null && dunSettings.size() > 0) {
2366                     for (ApnSetting dunSetting : dunSettings) {
2367                         if (dunSetting.equals(apnSetting)) {
2368                             if (curDc.isActive()) {
2369                                 if (DBG) {
2370                                     log("checkForCompatibleDataConnection:"
2371                                             + " found dun conn=" + curDc);
2372                                 }
2373                                 return curDc;
2374                             } else if (curDc.isActivating()) {
2375                                 potentialDc = curDc;
2376                             }
2377                         }
2378                     }
2379                 } else if (apnSetting != null && apnSetting.canHandleType(apnType)) {
2380                     if (curDc.isActive()) {
2381                         if (DBG) {
2382                             log("checkForCompatibleDataConnection:"
2383                                     + " found canHandle conn=" + curDc);
2384                         }
2385                         return curDc;
2386                     } else if (curDc.isActivating()) {
2387                         potentialDc = curDc;
2388                     }
2389                 }
2390             }
2391         }
2392 
2393         if (DBG) {
2394             log("checkForCompatibleDataConnection: potential dc=" + potentialDc);
2395         }
2396         return potentialDc;
2397     }
2398 
addRequestNetworkCompleteMsg(Message onCompleteMsg, @ApnType int apnType)2399     private void addRequestNetworkCompleteMsg(Message onCompleteMsg,
2400                                               @ApnType int apnType) {
2401         if (onCompleteMsg != null) {
2402             List<Message> messageList = mRequestNetworkCompletionMsgs.get(apnType);
2403             if (messageList == null) messageList = new ArrayList<>();
2404             messageList.add(onCompleteMsg);
2405             mRequestNetworkCompletionMsgs.put(apnType, messageList);
2406         }
2407     }
2408 
sendRequestNetworkCompleteMsg(Message message, boolean success, @TransportType int transport, @RequestNetworkType int requestType, @DataFailureCause int cause)2409     private void sendRequestNetworkCompleteMsg(Message message, boolean success,
2410                                                @TransportType int transport,
2411                                                @RequestNetworkType int requestType,
2412                                                @DataFailureCause int cause) {
2413         if (message == null) return;
2414 
2415         Bundle b = message.getData();
2416         b.putBoolean(DATA_COMPLETE_MSG_EXTRA_SUCCESS, success);
2417         b.putInt(DATA_COMPLETE_MSG_EXTRA_REQUEST_TYPE, requestType);
2418         b.putInt(DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE, transport);
2419         // TODO: For now this is the only fail cause that we know modem keeps data connection on
2420         // original transport. Might add more complicated logic or mapping in the future.
2421         b.putBoolean(DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK,
2422                 (requestType == REQUEST_TYPE_HANDOVER
2423                         && cause == DataFailCause.HANDOFF_PREFERENCE_CHANGED));
2424         message.sendToTarget();
2425     }
2426 
enableApn(@pnType int apnType, @RequestNetworkType int requestType, Message onCompleteMsg)2427     public void enableApn(@ApnType int apnType, @RequestNetworkType int requestType,
2428                           Message onCompleteMsg) {
2429         sendMessage(obtainMessage(DctConstants.EVENT_ENABLE_APN, apnType, requestType,
2430                 onCompleteMsg));
2431     }
2432 
onEnableApn(@pnType int apnType, @RequestNetworkType int requestType, Message onCompleteMsg)2433     private void onEnableApn(@ApnType int apnType, @RequestNetworkType int requestType,
2434                              Message onCompleteMsg) {
2435         ApnContext apnContext = mApnContextsByType.get(apnType);
2436         if (apnContext == null) {
2437             loge("onEnableApn(" + apnType + "): NO ApnContext");
2438             sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType, requestType,
2439                     DataFailCause.NONE);
2440             return;
2441         }
2442 
2443         String str = "onEnableApn: apnType=" + ApnSetting.getApnTypeString(apnType)
2444                 + ", request type=" + requestTypeToString(requestType);
2445         if (DBG) log(str);
2446         apnContext.requestLog(str);
2447 
2448         if (!apnContext.isDependencyMet()) {
2449             apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_UNMET);
2450             apnContext.setEnabled(true);
2451             str = "onEnableApn: dependency is not met.";
2452             if (DBG) log(str);
2453             apnContext.requestLog(str);
2454             sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType, requestType,
2455                     DataFailCause.NONE);
2456             return;
2457         }
2458 
2459         if (apnContext.isReady()) {
2460             DctConstants.State state = apnContext.getState();
2461             switch(state) {
2462                 case CONNECTING:
2463                     if (DBG) log("onEnableApn: 'CONNECTING' so return");
2464                     apnContext.requestLog("onEnableApn state=CONNECTING, so return");
2465                     addRequestNetworkCompleteMsg(onCompleteMsg, apnType);
2466                     return;
2467                 case CONNECTED:
2468                     if (DBG) log("onEnableApn: 'CONNECTED' so return");
2469                     // Don't add to local log since this is so common
2470                     sendRequestNetworkCompleteMsg(onCompleteMsg, true, mTransportType,
2471                             requestType, DataFailCause.NONE);
2472                     return;
2473                 case DISCONNECTING:
2474                     if (DBG) log("onEnableApn: 'DISCONNECTING' so return");
2475                     apnContext.requestLog("onEnableApn state=DISCONNECTING, so return");
2476                     sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType,
2477                             requestType, DataFailCause.NONE);
2478                     return;
2479                 case IDLE:
2480                     // fall through: this is unexpected but if it happens cleanup and try setup
2481                 case FAILED:
2482                 case RETRYING:
2483                     // We're "READY" but not active so disconnect (cleanup = true) and
2484                     // connect (trySetup = true) to be sure we retry the connection.
2485                     apnContext.setReason(Phone.REASON_DATA_ENABLED);
2486                     break;
2487             }
2488         } else {
2489             if (apnContext.isEnabled()) {
2490                 apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_MET);
2491             } else {
2492                 apnContext.setReason(Phone.REASON_DATA_ENABLED);
2493             }
2494             if (apnContext.getState() == DctConstants.State.FAILED) {
2495                 apnContext.setState(DctConstants.State.IDLE);
2496             }
2497         }
2498         apnContext.setEnabled(true);
2499         apnContext.resetErrorCodeRetries();
2500 
2501         if (mConfigReady || apnContext.getApnTypeBitmask() == ApnSetting.TYPE_EMERGENCY) {
2502             if (trySetupData(apnContext, requestType)) {
2503                 addRequestNetworkCompleteMsg(onCompleteMsg, apnType);
2504             } else {
2505                 sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType,
2506                         requestType, DataFailCause.NONE);
2507             }
2508         } else {
2509             log("onEnableApn: config not ready yet.");
2510         }
2511     }
2512 
disableApn(@pnType int apnType, @ReleaseNetworkType int releaseType)2513     public void disableApn(@ApnType int apnType, @ReleaseNetworkType int releaseType) {
2514         sendMessage(obtainMessage(DctConstants.EVENT_DISABLE_APN, apnType, releaseType));
2515     }
2516 
onDisableApn(@pnType int apnType, @ReleaseNetworkType int releaseType)2517     private void onDisableApn(@ApnType int apnType,
2518                               @ReleaseNetworkType int releaseType) {
2519         ApnContext apnContext = mApnContextsByType.get(apnType);
2520         if (apnContext == null) {
2521             loge("disableApn(" + apnType + "): NO ApnContext");
2522             return;
2523         }
2524 
2525         boolean cleanup = false;
2526         String str = "onDisableApn: apnType=" + ApnSetting.getApnTypeString(apnType)
2527                 + ", release type=" + releaseTypeToString(releaseType);
2528         if (DBG) log(str);
2529         apnContext.requestLog(str);
2530 
2531         if (apnContext.isReady()) {
2532             cleanup = (releaseType == RELEASE_TYPE_DETACH
2533                     || releaseType == RELEASE_TYPE_HANDOVER);
2534             if (apnContext.isDependencyMet()) {
2535                 apnContext.setReason(Phone.REASON_DATA_DISABLED_INTERNAL);
2536                 // If ConnectivityService has disabled this network, stop trying to bring
2537                 // it up, but do not tear it down - ConnectivityService will do that
2538                 // directly by talking with the DataConnection.
2539                 //
2540                 // This doesn't apply to DUN. When the user disable tethering, we would like to
2541                 // detach the APN context from the data connection so the data connection can be
2542                 // torn down if no other APN context attached to it.
2543                 if (PhoneConstants.APN_TYPE_DUN.equals(apnContext.getApnType())
2544                         || apnContext.getState() != DctConstants.State.CONNECTED) {
2545                     str = "Clean up the connection. Apn type = " + apnContext.getApnType()
2546                             + ", state = " + apnContext.getState();
2547                     if (DBG) log(str);
2548                     apnContext.requestLog(str);
2549                     cleanup = true;
2550                 }
2551             } else {
2552                 apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_UNMET);
2553             }
2554         }
2555 
2556         apnContext.setEnabled(false);
2557         if (cleanup) {
2558             cleanUpConnectionInternal(true, releaseType, apnContext);
2559         }
2560 
2561         if (isOnlySingleDcAllowed(getDataRat()) && !isHigherPriorityApnContextActive(apnContext)) {
2562             if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled");
2563             // If the highest priority APN is disabled and only single
2564             // data call is allowed, try to setup data call on other connectable APN.
2565             setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION,
2566                     RetryFailures.ALWAYS);
2567         }
2568     }
2569 
2570     /**
2571      * Modify {@link android.provider.Settings.Global#DATA_ROAMING} value for user modification only
2572      */
setDataRoamingEnabledByUser(boolean enabled)2573     public void setDataRoamingEnabledByUser(boolean enabled) {
2574         mDataEnabledSettings.setDataRoamingEnabled(enabled);
2575         setDataRoamingFromUserAction(true);
2576         if (DBG) {
2577             log("setDataRoamingEnabledByUser: set phoneSubId=" + mPhone.getSubId()
2578                     + " isRoaming=" + enabled);
2579         }
2580     }
2581 
2582     /**
2583      * Return current {@link android.provider.Settings.Global#DATA_ROAMING} value.
2584      */
getDataRoamingEnabled()2585     public boolean getDataRoamingEnabled() {
2586         boolean isDataRoamingEnabled = mDataEnabledSettings.getDataRoamingEnabled();
2587 
2588         if (VDBG) {
2589             log("getDataRoamingEnabled: phoneSubId=" + mPhone.getSubId()
2590                     + " isDataRoamingEnabled=" + isDataRoamingEnabled);
2591         }
2592         return isDataRoamingEnabled;
2593     }
2594 
2595     /**
2596      * Set default value for {@link android.provider.Settings.Global#DATA_ROAMING}
2597      * if the setting is not from user actions. default value is based on carrier config and system
2598      * properties.
2599      */
setDefaultDataRoamingEnabled()2600     private void setDefaultDataRoamingEnabled() {
2601         // For single SIM phones, this is a per phone property.
2602         String setting = Settings.Global.DATA_ROAMING;
2603         boolean useCarrierSpecificDefault = false;
2604         if (mTelephonyManager.getSimCount() != 1) {
2605             setting = setting + mPhone.getSubId();
2606             try {
2607                 Settings.Global.getInt(mResolver, setting);
2608             } catch (SettingNotFoundException ex) {
2609                 // For msim, update to carrier default if uninitialized.
2610                 useCarrierSpecificDefault = true;
2611             }
2612         } else if (!isDataRoamingFromUserAction()) {
2613             // for single sim device, update to carrier default if user action is not set
2614             useCarrierSpecificDefault = true;
2615         }
2616         log("setDefaultDataRoamingEnabled: useCarrierSpecificDefault "
2617                 + useCarrierSpecificDefault);
2618         if (useCarrierSpecificDefault) {
2619             boolean defaultVal = mDataEnabledSettings.getDefaultDataRoamingEnabled();
2620             mDataEnabledSettings.setDataRoamingEnabled(defaultVal);
2621         }
2622     }
2623 
isDataRoamingFromUserAction()2624     private boolean isDataRoamingFromUserAction() {
2625         final SharedPreferences sp = PreferenceManager
2626                 .getDefaultSharedPreferences(mPhone.getContext());
2627         // since we don't want to unset user preference from system update, pass true as the default
2628         // value if shared pref does not exist and set shared pref to false explicitly from factory
2629         // reset.
2630         if (!sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) {
2631             sp.edit().putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, false).commit();
2632         }
2633         return sp.getBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true);
2634     }
2635 
setDataRoamingFromUserAction(boolean isUserAction)2636     private void setDataRoamingFromUserAction(boolean isUserAction) {
2637         final SharedPreferences.Editor sp = PreferenceManager
2638                 .getDefaultSharedPreferences(mPhone.getContext()).edit();
2639         sp.putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, isUserAction).commit();
2640     }
2641 
2642     // When the data roaming status changes from roaming to non-roaming.
onDataRoamingOff()2643     private void onDataRoamingOff() {
2644         if (DBG) log("onDataRoamingOff");
2645 
2646         reevaluateDataConnections();
2647 
2648         if (!getDataRoamingEnabled()) {
2649             // TODO: Remove this once all old vendor RILs are gone. We don't need to set initial apn
2650             // attach and send the data profile again as the modem should have both roaming and
2651             // non-roaming protocol in place. Modem should choose the right protocol based on the
2652             // roaming condition.
2653             setDataProfilesAsNeeded();
2654             setInitialAttachApn();
2655 
2656             // If the user did not enable data roaming, now when we transit from roaming to
2657             // non-roaming, we should try to reestablish the data connection.
2658 
2659             setupDataOnAllConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS);
2660         } else {
2661             mPhone.notifyAllActiveDataConnections();
2662         }
2663     }
2664 
2665     // This method is called
2666     // 1. When the data roaming status changes from non-roaming to roaming.
2667     // 2. When allowed data roaming settings is changed by the user.
onDataRoamingOnOrSettingsChanged(int messageType)2668     private void onDataRoamingOnOrSettingsChanged(int messageType) {
2669         if (DBG) log("onDataRoamingOnOrSettingsChanged");
2670         // Used to differentiate data roaming turned on vs settings changed.
2671         boolean settingChanged = (messageType == DctConstants.EVENT_ROAMING_SETTING_CHANGE);
2672 
2673         // Check if the device is actually data roaming
2674         if (!mPhone.getServiceState().getDataRoaming()) {
2675             if (DBG) log("device is not roaming. ignored the request.");
2676             return;
2677         }
2678 
2679         checkDataRoamingStatus(settingChanged);
2680 
2681         if (getDataRoamingEnabled()) {
2682             // If the restricted data was brought up when data roaming is disabled, and now users
2683             // enable data roaming, we need to re-evaluate the conditions and possibly change the
2684             // network's capability.
2685             if (settingChanged) {
2686                 reevaluateDataConnections();
2687             }
2688 
2689             if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming");
2690 
2691             setupDataOnAllConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS);
2692             mPhone.notifyAllActiveDataConnections();
2693         } else {
2694             // If the user does not turn on data roaming, when we transit from non-roaming to
2695             // roaming, we need to tear down the data connection otherwise the user might be
2696             // charged for data roaming usage.
2697             if (DBG) log("onDataRoamingOnOrSettingsChanged: Tear down data connection on roaming.");
2698             cleanUpAllConnectionsInternal(true, Phone.REASON_ROAMING_ON);
2699         }
2700     }
2701 
2702     // We want to track possible roaming data leakage. Which is, if roaming setting
2703     // is disabled, yet we still setup a roaming data connection or have a connected ApnContext
2704     // switched to roaming. When this happens, we log it in a local log.
checkDataRoamingStatus(boolean settingChanged)2705     private void checkDataRoamingStatus(boolean settingChanged) {
2706         if (!settingChanged && !getDataRoamingEnabled()
2707                 && mPhone.getServiceState().getDataRoaming()) {
2708             for (ApnContext apnContext : mApnContexts.values()) {
2709                 if (apnContext.getState() == DctConstants.State.CONNECTED) {
2710                     mDataRoamingLeakageLog.log("PossibleRoamingLeakage "
2711                             + " connection params: " + (apnContext.getDataConnection() != null
2712                             ? apnContext.getDataConnection().getConnectionParams() : ""));
2713                 }
2714             }
2715         }
2716     }
2717 
onRadioAvailable()2718     private void onRadioAvailable() {
2719         if (DBG) log("onRadioAvailable");
2720         if (mPhone.getSimulatedRadioControl() != null) {
2721             // Assume data is connected on the simulator
2722             // FIXME  this can be improved
2723             // setState(DctConstants.State.CONNECTED);
2724             mPhone.notifyAllActiveDataConnections();
2725 
2726             log("onRadioAvailable: We're on the simulator; assuming data is connected");
2727         }
2728 
2729         if (!areAllDataDisconnected()) {
2730             cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, null);
2731         }
2732     }
2733 
onRadioOffOrNotAvailable()2734     private void onRadioOffOrNotAvailable() {
2735         // Make sure our reconnect delay starts at the initial value
2736         // next time the radio comes on
2737 
2738         mReregisterOnReconnectFailure = false;
2739 
2740         // Clear auto attach as modem is expected to do a new attach
2741         mAutoAttachEnabled.set(false);
2742 
2743         if (mPhone.getSimulatedRadioControl() != null) {
2744             // Assume data is connected on the simulator
2745             // FIXME  this can be improved
2746             log("We're on the simulator; assuming radio off is meaningless");
2747         } else {
2748             if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections");
2749             cleanUpAllConnectionsInternal(false, Phone.REASON_RADIO_TURNED_OFF);
2750         }
2751     }
2752 
completeConnection(ApnContext apnContext, @RequestNetworkType int type)2753     private void completeConnection(ApnContext apnContext, @RequestNetworkType int type) {
2754 
2755         if (DBG) log("completeConnection: successful, notify the world apnContext=" + apnContext);
2756 
2757         if (mIsProvisioning && !TextUtils.isEmpty(mProvisioningUrl)) {
2758             if (DBG) {
2759                 log("completeConnection: MOBILE_PROVISIONING_ACTION url="
2760                         + mProvisioningUrl);
2761             }
2762             Intent newIntent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
2763                     Intent.CATEGORY_APP_BROWSER);
2764             newIntent.setData(Uri.parse(mProvisioningUrl));
2765             newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
2766                     Intent.FLAG_ACTIVITY_NEW_TASK);
2767             try {
2768                 mPhone.getContext().startActivity(newIntent);
2769             } catch (ActivityNotFoundException e) {
2770                 loge("completeConnection: startActivityAsUser failed" + e);
2771             }
2772         }
2773         mIsProvisioning = false;
2774         mProvisioningUrl = null;
2775         if (mProvisioningSpinner != null) {
2776             sendMessage(obtainMessage(DctConstants.CMD_CLEAR_PROVISIONING_SPINNER,
2777                     mProvisioningSpinner));
2778         }
2779 
2780         mPhone.notifyDataConnection(apnContext.getApnType());
2781 
2782         startNetStatPoll();
2783         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
2784     }
2785 
2786     /**
2787      * A SETUP (aka bringUp) has completed, possibly with an error. If
2788      * there is an error this method will call {@link #onDataSetupCompleteError}.
2789      */
onDataSetupComplete(ApnContext apnContext, boolean success, int cause, @RequestNetworkType int requestType)2790     protected void onDataSetupComplete(ApnContext apnContext, boolean success, int cause,
2791                                      @RequestNetworkType int requestType) {
2792         int apnType = ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType());
2793         List<Message> messageList = mRequestNetworkCompletionMsgs.get(apnType);
2794         if (messageList != null) {
2795             for (Message msg : messageList) {
2796                 sendRequestNetworkCompleteMsg(msg, success, mTransportType, requestType, cause);
2797             }
2798             messageList.clear();
2799         }
2800 
2801         if (success) {
2802             DataConnection dataConnection = apnContext.getDataConnection();
2803 
2804             if (RADIO_TESTS) {
2805                 // Note: To change radio.test.onDSC.null.dcac from command line you need to
2806                 // adb root and adb remount and from the command line you can only change the
2807                 // value to 1 once. To change it a second time you can reboot or execute
2808                 // adb shell stop and then adb shell start. The command line to set the value is:
2809                 // adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "insert into system (name,value) values ('radio.test.onDSC.null.dcac', '1');"
2810                 ContentResolver cr = mPhone.getContext().getContentResolver();
2811                 String radioTestProperty = "radio.test.onDSC.null.dcac";
2812                 if (Settings.System.getInt(cr, radioTestProperty, 0) == 1) {
2813                     log("onDataSetupComplete: " + radioTestProperty +
2814                             " is true, set dcac to null and reset property to false");
2815                     dataConnection = null;
2816                     Settings.System.putInt(cr, radioTestProperty, 0);
2817                     log("onDataSetupComplete: " + radioTestProperty + "=" +
2818                             Settings.System.getInt(mPhone.getContext().getContentResolver(),
2819                                     radioTestProperty, -1));
2820                 }
2821             }
2822             if (dataConnection == null) {
2823                 log("onDataSetupComplete: no connection to DC, handle as error");
2824                 onDataSetupCompleteError(apnContext, requestType);
2825             } else {
2826                 ApnSetting apn = apnContext.getApnSetting();
2827                 if (DBG) {
2828                     log("onDataSetupComplete: success apn=" + (apn == null ? "unknown"
2829                             : apn.getApnName()));
2830                 }
2831 
2832                 // everything is setup
2833                 if (TextUtils.equals(apnContext.getApnType(), PhoneConstants.APN_TYPE_DEFAULT)
2834                         && mCanSetPreferApn && mPreferredApn == null) {
2835                     if (DBG) log("onDataSetupComplete: PREFERRED APN is null");
2836                     mPreferredApn = apn;
2837                     if (mPreferredApn != null) {
2838                         setPreferredApn(mPreferredApn.getId());
2839                     }
2840                 }
2841 
2842                 // A connection is setup
2843                 apnContext.setState(DctConstants.State.CONNECTED);
2844 
2845                 checkDataRoamingStatus(false);
2846 
2847                 boolean isProvApn = apnContext.isProvisioningApn();
2848                 final ConnectivityManager cm = (ConnectivityManager) mPhone.getContext()
2849                         .getSystemService(Context.CONNECTIVITY_SERVICE);
2850                 if (mProvisionBroadcastReceiver != null) {
2851                     mPhone.getContext().unregisterReceiver(mProvisionBroadcastReceiver);
2852                     mProvisionBroadcastReceiver = null;
2853                 }
2854                 if ((!isProvApn) || mIsProvisioning) {
2855                     // Hide any provisioning notification.
2856                     cm.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_MOBILE,
2857                             mProvisionActionName);
2858                     // Complete the connection normally notifying the world we're connected.
2859                     // We do this if this isn't a special provisioning apn or if we've been
2860                     // told its time to provision.
2861                     completeConnection(apnContext, requestType);
2862                 } else {
2863                     // This is a provisioning APN that we're reporting as connected. Later
2864                     // when the user desires to upgrade this to a "default" connection,
2865                     // mIsProvisioning == true, we'll go through the code path above.
2866                     // mIsProvisioning becomes true when CMD_ENABLE_MOBILE_PROVISIONING
2867                     // is sent to the DCT.
2868                     if (DBG) {
2869                         log("onDataSetupComplete: successful, BUT send connected to prov apn as"
2870                                 + " mIsProvisioning:" + mIsProvisioning + " == false"
2871                                 + " && (isProvisioningApn:" + isProvApn + " == true");
2872                     }
2873 
2874                     // While radio is up, grab provisioning URL.  The URL contains ICCID which
2875                     // disappears when radio is off.
2876                     mProvisionBroadcastReceiver = new ProvisionNotificationBroadcastReceiver(
2877                             cm.getMobileProvisioningUrl(),
2878                             mTelephonyManager.getNetworkOperatorName());
2879                     mPhone.getContext().registerReceiver(mProvisionBroadcastReceiver,
2880                             new IntentFilter(mProvisionActionName));
2881                     // Put up user notification that sign-in is required.
2882                     cm.setProvisioningNotificationVisible(true, ConnectivityManager.TYPE_MOBILE,
2883                             mProvisionActionName);
2884                     // Turn off radio to save battery and avoid wasting carrier resources.
2885                     // The network isn't usable and network validation will just fail anyhow.
2886                     setRadio(false);
2887                 }
2888                 if (DBG) {
2889                     log("onDataSetupComplete: SETUP complete type=" + apnContext.getApnType());
2890                 }
2891                 if (TelephonyUtils.IS_DEBUGGABLE) {
2892                     // adb shell setprop persist.radio.test.pco [pco_val]
2893                     String radioTestProperty = "persist.radio.test.pco";
2894                     int pcoVal = SystemProperties.getInt(radioTestProperty, -1);
2895                     if (pcoVal != -1) {
2896                         log("PCO testing: read pco value from persist.radio.test.pco " + pcoVal);
2897                         final byte[] value = new byte[1];
2898                         value[0] = (byte) pcoVal;
2899                         final Intent intent =
2900                                 new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE);
2901                         intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, "default");
2902                         intent.putExtra(TelephonyManager.EXTRA_APN_TYPE_INT, TYPE_DEFAULT);
2903                         intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, "IPV4V6");
2904                         intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL_INT, PROTOCOL_IPV4V6);
2905                         intent.putExtra(TelephonyManager.EXTRA_PCO_ID, 0xFF00);
2906                         intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, value);
2907                         mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
2908                     }
2909                 }
2910             }
2911         } else {
2912             if (DBG) {
2913                 ApnSetting apn = apnContext.getApnSetting();
2914                 log("onDataSetupComplete: error apn=" + apn.getApnName() + ", cause=" + cause
2915                         + ", requestType=" + requestTypeToString(requestType));
2916             }
2917             if (DataFailCause.isEventLoggable(cause)) {
2918                 // Log this failure to the Event Logs.
2919                 int cid = getCellLocationId();
2920                 EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
2921                         cause, cid, mTelephonyManager.getNetworkType());
2922             }
2923             ApnSetting apn = apnContext.getApnSetting();
2924             mPhone.notifyDataConnectionFailed(apnContext.getApnType(),
2925                     apn != null ? apn.getApnName() : null, cause);
2926 
2927             // Compose broadcast intent send to the specific carrier signaling receivers
2928             Intent intent = new Intent(TelephonyManager
2929                     .ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED);
2930             intent.putExtra(TelephonyManager.EXTRA_ERROR_CODE, cause);
2931             intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, apnContext.getApnType());
2932             intent.putExtra(TelephonyManager.EXTRA_APN_TYPE_INT,
2933                     ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType()));
2934             mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
2935 
2936             if (DataFailCause.isRadioRestartFailure(mPhone.getContext(), cause, mPhone.getSubId())
2937                     || apnContext.restartOnError(cause)) {
2938                 if (DBG) log("Modem restarted.");
2939                 sendRestartRadio();
2940             }
2941 
2942             // If the data call failure cause is a permanent failure, we mark the APN as permanent
2943             // failed.
2944             if (isPermanentFailure(cause)) {
2945                 log("cause = " + cause + ", mark apn as permanent failed. apn = " + apn);
2946                 apnContext.markApnPermanentFailed(apn);
2947             }
2948             onDataSetupCompleteError(apnContext, requestType);
2949         }
2950     }
2951 
2952     /**
2953      * Error has occurred during the SETUP {aka bringUP} request and the DCT
2954      * should either try the next waiting APN or start over from the
2955      * beginning if the list is empty. Between each SETUP request there will
2956      * be a delay defined by {@link #getApnDelay()}.
2957      */
onDataSetupCompleteError(ApnContext apnContext, @RequestNetworkType int requestType)2958     protected void onDataSetupCompleteError(ApnContext apnContext,
2959                                           @RequestNetworkType int requestType) {
2960         long delay = apnContext.getDelayForNextApn(mFailFast);
2961 
2962         // Check if we need to retry or not.
2963         // TODO: We should support handover retry in the future.
2964         if (delay >= 0) {
2965             if (DBG) log("onDataSetupCompleteError: Try next APN. delay = " + delay);
2966             apnContext.setState(DctConstants.State.RETRYING);
2967             // Wait a bit before trying the next APN, so that
2968             // we're not tying up the RIL command channel
2969 
2970             startReconnect(delay, apnContext);
2971         } else {
2972             // If we are not going to retry any APN, set this APN context to failed state.
2973             // This would be the final state of a data connection.
2974             apnContext.setState(DctConstants.State.FAILED);
2975             mPhone.notifyDataConnection(apnContext.getApnType());
2976             apnContext.setDataConnection(null);
2977             log("onDataSetupCompleteError: Stop retrying APNs. delay=" + delay
2978                     + ", requestType=" + requestTypeToString(requestType));
2979         }
2980     }
2981 
2982     /**
2983      * Called when EVENT_NETWORK_STATUS_CHANGED is received.
2984      *
2985      * @param status One of {@code NetworkAgent.VALID_NETWORK} or
2986      * {@code NetworkAgent.INVALID_NETWORK}.
2987      * @param cid context id {@code cid}
2988      * @param redirectUrl If the Internet probe was redirected, this
2989      * is the destination it was redirected to, otherwise {@code null}
2990      */
onNetworkStatusChanged(int status, int cid, String redirectUrl)2991     private void onNetworkStatusChanged(int status, int cid, String redirectUrl) {
2992         if (!TextUtils.isEmpty(redirectUrl)) {
2993             Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_REDIRECTED);
2994             intent.putExtra(TelephonyManager.EXTRA_REDIRECTION_URL, redirectUrl);
2995             mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
2996             log("Notify carrier signal receivers with redirectUrl: " + redirectUrl);
2997         } else {
2998             final boolean isValid = status == NetworkAgent.VALIDATION_STATUS_VALID;
2999             final DataConnection dc = getDataConnectionByContextId(cid);
3000             if (!mDsRecoveryHandler.isRecoveryOnBadNetworkEnabled()) {
3001                 if (DBG) log("Skip data stall recovery on network status change with in threshold");
3002                 return;
3003             }
3004             if (mTransportType != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
3005                 if (DBG) log("Skip data stall recovery on non WWAN");
3006                 return;
3007             }
3008             if (dc != null && dc.isValidationRequired()) {
3009                 mDsRecoveryHandler.processNetworkStatusChanged(isValid);
3010             }
3011         }
3012     }
3013 
3014     /**
3015      * Called when EVENT_DISCONNECT_DONE is received.
3016      */
onDisconnectDone(ApnContext apnContext)3017     private void onDisconnectDone(ApnContext apnContext) {
3018         if(DBG) log("onDisconnectDone: EVENT_DISCONNECT_DONE apnContext=" + apnContext);
3019         apnContext.setState(DctConstants.State.IDLE);
3020         final DataConnection dc = apnContext.getDataConnection();
3021         // when data connection is gone and not for handover, notify all apn types which
3022         // this data connection can handle. Note, this might not work if one apn type served for
3023         // multiple data connection.
3024         if (dc != null && dc.isInactive() && !dc.hasBeenTransferred()) {
3025             String[] types = ApnSetting.getApnTypesStringFromBitmask(
3026                     apnContext.getApnSetting().getApnTypeBitmask()).split(",");
3027             for (String type : types) {
3028                 mPhone.notifyDataConnection(type);
3029             }
3030         }
3031         // if all data connection are gone, check whether Airplane mode request was
3032         // pending.
3033         if (areAllDataDisconnected()) {
3034             if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
3035                 if (DBG) log("onDisconnectDone: radio will be turned off, no retries");
3036                 // Radio will be turned off. No need to retry data setup
3037                 apnContext.setApnSetting(null);
3038                 apnContext.setDataConnection(null);
3039 
3040                 // Need to notify disconnect as well, in the case of switching Airplane mode.
3041                 // Otherwise, it would cause 30s delayed to turn on Airplane mode.
3042                 if (mDisconnectPendingCount > 0) {
3043                     mDisconnectPendingCount--;
3044                 }
3045 
3046                 if (mDisconnectPendingCount == 0) {
3047                     notifyAllDataDisconnected();
3048                 }
3049                 return;
3050             }
3051         }
3052         // If APN is still enabled, try to bring it back up automatically
3053         if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) {
3054             // Wait a bit before trying the next APN, so that
3055             // we're not tying up the RIL command channel.
3056             // This also helps in any external dependency to turn off the context.
3057             if (DBG) log("onDisconnectDone: attached, ready and retry after disconnect");
3058             long delay = apnContext.getRetryAfterDisconnectDelay();
3059             if (delay > 0) {
3060                 // Data connection is in IDLE state, so when we reconnect later, we'll rebuild
3061                 // the waiting APN list, which will also reset/reconfigure the retry manager.
3062                 startReconnect(delay, apnContext);
3063             }
3064         } else {
3065             boolean restartRadioAfterProvisioning = mPhone.getContext().getResources().getBoolean(
3066                     com.android.internal.R.bool.config_restartRadioAfterProvisioning);
3067 
3068             if (apnContext.isProvisioningApn() && restartRadioAfterProvisioning) {
3069                 log("onDisconnectDone: restartRadio after provisioning");
3070                 restartRadio();
3071             }
3072             apnContext.setApnSetting(null);
3073             apnContext.setDataConnection(null);
3074             if (isOnlySingleDcAllowed(getDataRat())) {
3075                 if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn");
3076                 setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION,
3077                         RetryFailures.ALWAYS);
3078             } else {
3079                 if(DBG) log("onDisconnectDone: not retrying");
3080             }
3081         }
3082 
3083         if (mDisconnectPendingCount > 0)
3084             mDisconnectPendingCount--;
3085 
3086         if (mDisconnectPendingCount == 0) {
3087             apnContext.setConcurrentVoiceAndDataAllowed(
3088                     mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed());
3089             notifyAllDataDisconnected();
3090         }
3091 
3092     }
3093 
onVoiceCallStarted()3094     private void onVoiceCallStarted() {
3095         if (DBG) log("onVoiceCallStarted");
3096         mInVoiceCall = true;
3097         if (isAnyDataConnected()
3098                 && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
3099             if (DBG) log("onVoiceCallStarted stop polling");
3100             stopNetStatPoll();
3101             stopDataStallAlarm();
3102             mPhone.notifyAllActiveDataConnections();
3103         }
3104     }
3105 
onVoiceCallEnded()3106     protected void onVoiceCallEnded() {
3107         if (DBG) log("onVoiceCallEnded");
3108         mInVoiceCall = false;
3109         if (isAnyDataConnected()) {
3110             if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
3111                 startNetStatPoll();
3112                 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
3113                 mPhone.notifyAllActiveDataConnections();
3114             } else {
3115                 // clean slate after call end.
3116                 resetPollStats();
3117             }
3118         }
3119         // reset reconnect timer
3120         setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS);
3121     }
3122     /**
3123      * @return {@code true} if there is any data in connected state.
3124      */
3125     @VisibleForTesting
isAnyDataConnected()3126     public boolean isAnyDataConnected() {
3127         for (DataConnection dc : mDataConnections.values()) {
3128             if (dc.isActive()) {
3129                 return true;
3130             }
3131         }
3132         return false;
3133     }
3134 
3135     /**
3136      * @return {@code true} if all data connections are in disconnected state.
3137      */
areAllDataDisconnected()3138     public boolean areAllDataDisconnected() {
3139         for (DataConnection dc : mDataConnections.values()) {
3140             if (!dc.isInactive()) {
3141                 return false;
3142             }
3143         }
3144         return true;
3145     }
3146 
setDataProfilesAsNeeded()3147     protected void setDataProfilesAsNeeded() {
3148         if (DBG) log("setDataProfilesAsNeeded");
3149 
3150         ArrayList<DataProfile> dataProfileList = new ArrayList<>();
3151 
3152         for (ApnSetting apn : mAllApnSettings) {
3153             DataProfile dp = createDataProfile(apn, apn.equals(getPreferredApn()));
3154             if (!dataProfileList.contains(dp)) {
3155                 dataProfileList.add(dp);
3156             }
3157         }
3158 
3159         // Check if the data profiles we are sending are same as we did last time. We don't want to
3160         // send the redundant profiles to the modem. Also if there the list is empty, we don't
3161         // send it to the modem.
3162         if (!dataProfileList.isEmpty()
3163                 && (dataProfileList.size() != mLastDataProfileList.size()
3164                 || !mLastDataProfileList.containsAll(dataProfileList))) {
3165             mDataServiceManager.setDataProfile(dataProfileList,
3166                     mPhone.getServiceState().getDataRoamingFromRegistration(), null);
3167         }
3168     }
3169 
3170     /**
3171      * Based on the sim operator numeric, create a list for all possible
3172      * Data Connections and setup the preferredApn.
3173      */
createAllApnList()3174     protected void createAllApnList() {
3175         mAllApnSettings.clear();
3176         String operator = mPhone.getOperatorNumeric();
3177 
3178         // ORDER BY Telephony.Carriers._ID ("_id")
3179         Cursor cursor = mPhone.getContext().getContentResolver().query(
3180                 Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, "filtered/subId/"
3181                         + mPhone.getSubId()), null, null, null, Telephony.Carriers._ID);
3182 
3183         if (cursor != null) {
3184             while (cursor.moveToNext()) {
3185                 ApnSetting apn = ApnSetting.makeApnSetting(cursor);
3186                 if (apn == null) {
3187                     continue;
3188                 }
3189                 mAllApnSettings.add(apn);
3190             }
3191             cursor.close();
3192         } else {
3193             if (DBG) log("createAllApnList: cursor is null");
3194             mApnSettingsInitializationLog.log("cursor is null for carrier, operator: "
3195                     + operator);
3196         }
3197 
3198         addEmergencyApnSetting();
3199 
3200         dedupeApnSettings();
3201 
3202         if (mAllApnSettings.isEmpty()) {
3203             log("createAllApnList: No APN found for carrier, operator: " + operator);
3204             mApnSettingsInitializationLog.log("no APN found for carrier, operator: "
3205                     + operator);
3206             mPreferredApn = null;
3207             // Notify that there are no APN Settings,
3208             mPhone.notifyDataConnectionFailed(null, null, DataFailCause.MISSING_UNKNOWN_APN);
3209         } else {
3210             mPreferredApn = getPreferredApn();
3211             if (mPreferredApn != null && !mPreferredApn.getOperatorNumeric().equals(operator)) {
3212                 mPreferredApn = null;
3213                 setPreferredApn(-1);
3214             }
3215             if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
3216         }
3217         if (DBG) log("createAllApnList: X mAllApnSettings=" + mAllApnSettings);
3218     }
3219 
dedupeApnSettings()3220     private void dedupeApnSettings() {
3221         ArrayList<ApnSetting> resultApns = new ArrayList<ApnSetting>();
3222 
3223         // coalesce APNs if they are similar enough to prevent
3224         // us from bringing up two data calls with the same interface
3225         int i = 0;
3226         while (i < mAllApnSettings.size() - 1) {
3227             ApnSetting first = mAllApnSettings.get(i);
3228             ApnSetting second = null;
3229             int j = i + 1;
3230             while (j < mAllApnSettings.size()) {
3231                 second = mAllApnSettings.get(j);
3232                 if (first.similar(second)) {
3233                     ApnSetting newApn = mergeApns(first, second);
3234                     mAllApnSettings.set(i, newApn);
3235                     first = newApn;
3236                     mAllApnSettings.remove(j);
3237                 } else {
3238                     j++;
3239                 }
3240             }
3241             i++;
3242         }
3243     }
3244 
mergeApns(ApnSetting dest, ApnSetting src)3245     private ApnSetting mergeApns(ApnSetting dest, ApnSetting src) {
3246         int id = dest.getId();
3247         if ((src.getApnTypeBitmask() & ApnSetting.TYPE_DEFAULT) == ApnSetting.TYPE_DEFAULT) {
3248             id = src.getId();
3249         }
3250         final int resultApnType = src.getApnTypeBitmask() | dest.getApnTypeBitmask();
3251         Uri mmsc = (dest.getMmsc() == null ? src.getMmsc() : dest.getMmsc());
3252         String mmsProxy = TextUtils.isEmpty(dest.getMmsProxyAddressAsString())
3253                 ? src.getMmsProxyAddressAsString() : dest.getMmsProxyAddressAsString();
3254         int mmsPort = dest.getMmsProxyPort() == -1 ? src.getMmsProxyPort() : dest.getMmsProxyPort();
3255         String proxy = TextUtils.isEmpty(dest.getProxyAddressAsString())
3256                 ? src.getProxyAddressAsString() : dest.getProxyAddressAsString();
3257         int port = dest.getProxyPort() == -1 ? src.getProxyPort() : dest.getProxyPort();
3258         int protocol = src.getProtocol() == ApnSetting.PROTOCOL_IPV4V6 ? src.getProtocol()
3259                 : dest.getProtocol();
3260         int roamingProtocol = src.getRoamingProtocol() == ApnSetting.PROTOCOL_IPV4V6
3261                 ? src.getRoamingProtocol() : dest.getRoamingProtocol();
3262         int networkTypeBitmask = (dest.getNetworkTypeBitmask() == 0
3263                 || src.getNetworkTypeBitmask() == 0)
3264                 ? 0 : (dest.getNetworkTypeBitmask() | src.getNetworkTypeBitmask());
3265 
3266         return ApnSetting.makeApnSetting(id, dest.getOperatorNumeric(), dest.getEntryName(),
3267             dest.getApnName(), proxy, port, mmsc, mmsProxy, mmsPort, dest.getUser(),
3268             dest.getPassword(), dest.getAuthType(), resultApnType, protocol, roamingProtocol,
3269             dest.isEnabled(), networkTypeBitmask, dest.getProfileId(),
3270             (dest.isPersistent() || src.isPersistent()), dest.getMaxConns(),
3271             dest.getWaitTime(), dest.getMaxConnsTime(), dest.getMtu(), dest.getMvnoType(),
3272             dest.getMvnoMatchData(), dest.getApnSetId(), dest.getCarrierId(),
3273             dest.getSkip464Xlat());
3274     }
3275 
createDataConnection()3276     private DataConnection createDataConnection() {
3277         if (DBG) log("createDataConnection E");
3278 
3279         int id = mUniqueIdGenerator.getAndIncrement();
3280         DataConnection dataConnection = DataConnection.makeDataConnection(mPhone, id, this,
3281                 mDataServiceManager, mDcTesterFailBringUpAll, mDcc);
3282         mDataConnections.put(id, dataConnection);
3283         if (DBG) log("createDataConnection() X id=" + id + " dc=" + dataConnection);
3284         return dataConnection;
3285     }
3286 
destroyDataConnections()3287     private void destroyDataConnections() {
3288         if(mDataConnections != null) {
3289             if (DBG) log("destroyDataConnections: clear mDataConnectionList");
3290             mDataConnections.clear();
3291         } else {
3292             if (DBG) log("destroyDataConnections: mDataConnecitonList is empty, ignore");
3293         }
3294     }
3295 
3296     /**
3297      * Build a list of APNs to be used to create PDP's.
3298      *
3299      * @param requestedApnType
3300      * @return waitingApns list to be used to create PDP
3301      *          error when waitingApns.isEmpty()
3302      */
buildWaitingApns(String requestedApnType, int radioTech)3303     private ArrayList<ApnSetting> buildWaitingApns(String requestedApnType, int radioTech) {
3304         if (DBG) log("buildWaitingApns: E requestedApnType=" + requestedApnType);
3305         ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();
3306 
3307         int requestedApnTypeBitmask = ApnSetting.getApnTypesBitmaskFromString(requestedApnType);
3308         if (requestedApnTypeBitmask == ApnSetting.TYPE_DUN) {
3309             ArrayList<ApnSetting> dunApns = fetchDunApns();
3310             if (dunApns.size() > 0) {
3311                 for (ApnSetting dun : dunApns) {
3312                     apnList.add(dun);
3313                     if (DBG) log("buildWaitingApns: X added APN_TYPE_DUN apnList=" + apnList);
3314                 }
3315                 return sortApnListByPreferred(apnList);
3316             }
3317         }
3318 
3319         String operator = mPhone.getOperatorNumeric();
3320 
3321         // This is a workaround for a bug (7305641) where we don't failover to other
3322         // suitable APNs if our preferred APN fails.  On prepaid ATT sims we need to
3323         // failover to a provisioning APN, but once we've used their default data
3324         // connection we are locked to it for life.  This change allows ATT devices
3325         // to say they don't want to use preferred at all.
3326         boolean usePreferred = true;
3327         try {
3328             usePreferred = ! mPhone.getContext().getResources().getBoolean(com.android.
3329                     internal.R.bool.config_dontPreferApn);
3330         } catch (Resources.NotFoundException e) {
3331             if (DBG) log("buildWaitingApns: usePreferred NotFoundException set to true");
3332             usePreferred = true;
3333         }
3334         if (usePreferred) {
3335             mPreferredApn = getPreferredApn();
3336         }
3337         if (DBG) {
3338             log("buildWaitingApns: usePreferred=" + usePreferred
3339                     + " canSetPreferApn=" + mCanSetPreferApn
3340                     + " mPreferredApn=" + mPreferredApn
3341                     + " operator=" + operator + " radioTech=" + radioTech);
3342         }
3343 
3344         if (usePreferred && mCanSetPreferApn && mPreferredApn != null &&
3345                 mPreferredApn.canHandleType(requestedApnTypeBitmask)) {
3346             if (DBG) {
3347                 log("buildWaitingApns: Preferred APN:" + operator + ":"
3348                         + mPreferredApn.getOperatorNumeric() + ":" + mPreferredApn);
3349             }
3350             if (mPreferredApn.getOperatorNumeric().equals(operator)) {
3351                 if (mPreferredApn.canSupportNetworkType(
3352                         ServiceState.rilRadioTechnologyToNetworkType(radioTech))) {
3353                     apnList.add(mPreferredApn);
3354                     apnList = sortApnListByPreferred(apnList);
3355                     if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
3356                     return apnList;
3357                 }
3358             }
3359             if (DBG) log("buildWaitingApns: no preferred APN");
3360             setPreferredApn(-1);
3361             mPreferredApn = null;
3362         }
3363 
3364         if (DBG) log("buildWaitingApns: mAllApnSettings=" + mAllApnSettings);
3365         for (ApnSetting apn : mAllApnSettings) {
3366             if (apn.canHandleType(requestedApnTypeBitmask)) {
3367                 if (apn.canSupportNetworkType(
3368                         ServiceState.rilRadioTechnologyToNetworkType(radioTech))) {
3369                     if (VDBG) log("buildWaitingApns: adding apn=" + apn);
3370                     apnList.add(apn);
3371                 } else {
3372                     if (DBG) {
3373                         log("buildWaitingApns: networkTypeBitmask:"
3374                                 + apn.getNetworkTypeBitmask()
3375                                 + " does not include radioTech:"
3376                                 + ServiceState.rilRadioTechnologyToString(radioTech));
3377                     }
3378                 }
3379             } else if (VDBG) {
3380                 log("buildWaitingApns: couldn't handle requested ApnType="
3381                         + requestedApnType);
3382             }
3383         }
3384 
3385         apnList = sortApnListByPreferred(apnList);
3386         if (DBG) log("buildWaitingApns: " + apnList.size() + " APNs in the list: " + apnList);
3387         return apnList;
3388     }
3389 
3390     /**
3391      * Sort a list of ApnSetting objects, with the preferred APNs at the front of the list
3392      *
3393      * e.g. if the preferred APN set = 2 and we have
3394      *   1. APN with apn_set_id = 0 = Carriers.NO_SET_SET (no set is set)
3395      *   2. APN with apn_set_id = 1 (not preferred set)
3396      *   3. APN with apn_set_id = 2 (preferred set)
3397      * Then the return order should be (3, 1, 2) or (3, 2, 1)
3398      *
3399      * e.g. if the preferred APN set = Carriers.NO_SET_SET (no preferred set) then the
3400      * return order can be anything
3401      */
3402     @VisibleForTesting
sortApnListByPreferred(ArrayList<ApnSetting> list)3403     public ArrayList<ApnSetting> sortApnListByPreferred(ArrayList<ApnSetting> list) {
3404         if (list == null || list.size() <= 1) return list;
3405         int preferredApnSetId = getPreferredApnSetId();
3406         if (preferredApnSetId != Telephony.Carriers.NO_APN_SET_ID) {
3407             list.sort(new Comparator<ApnSetting>() {
3408                 @Override
3409                 public int compare(ApnSetting apn1, ApnSetting apn2) {
3410                     if (apn1.getApnSetId() == preferredApnSetId) {
3411                         return -1;
3412                     }
3413                     if (apn2.getApnSetId() == preferredApnSetId) {
3414                         return 1;
3415                     }
3416                     return 0;
3417                 }
3418             });
3419         }
3420         return list;
3421     }
3422 
apnListToString(ArrayList<ApnSetting> apns)3423     private String apnListToString (ArrayList<ApnSetting> apns) {
3424         StringBuilder result = new StringBuilder();
3425         for (int i = 0, size = apns.size(); i < size; i++) {
3426             result.append('[')
3427                   .append(apns.get(i).toString())
3428                   .append(']');
3429         }
3430         return result.toString();
3431     }
3432 
setPreferredApn(int pos)3433     private void setPreferredApn(int pos) {
3434         if (!mCanSetPreferApn) {
3435             log("setPreferredApn: X !canSEtPreferApn");
3436             return;
3437         }
3438 
3439         String subId = Long.toString(mPhone.getSubId());
3440         Uri uri = Uri.withAppendedPath(PREFERAPN_NO_UPDATE_URI_USING_SUBID, subId);
3441         log("setPreferredApn: delete");
3442         ContentResolver resolver = mPhone.getContext().getContentResolver();
3443         resolver.delete(uri, null, null);
3444 
3445         if (pos >= 0) {
3446             log("setPreferredApn: insert");
3447             ContentValues values = new ContentValues();
3448             values.put(APN_ID, pos);
3449             resolver.insert(uri, values);
3450         }
3451     }
3452 
3453     @Nullable
getPreferredApn()3454     ApnSetting getPreferredApn() {
3455         //Only call this method from main thread
3456         if (mAllApnSettings == null || mAllApnSettings.isEmpty()) {
3457             log("getPreferredApn: mAllApnSettings is empty");
3458             return null;
3459         }
3460 
3461         String subId = Long.toString(mPhone.getSubId());
3462         Uri uri = Uri.withAppendedPath(PREFERAPN_NO_UPDATE_URI_USING_SUBID, subId);
3463         Cursor cursor = mPhone.getContext().getContentResolver().query(
3464                 uri, new String[] { "_id", "name", "apn" },
3465                 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
3466 
3467         if (cursor != null) {
3468             mCanSetPreferApn = true;
3469         } else {
3470             mCanSetPreferApn = false;
3471         }
3472 
3473         if (VDBG) {
3474             log("getPreferredApn: mRequestedApnType=" + mRequestedApnType + " cursor=" + cursor
3475                     + " cursor.count=" + ((cursor != null) ? cursor.getCount() : 0));
3476         }
3477 
3478         if (mCanSetPreferApn && cursor.getCount() > 0) {
3479             int pos;
3480             cursor.moveToFirst();
3481             pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID));
3482             for(ApnSetting p : mAllApnSettings) {
3483                 if (p.getId() == pos && p.canHandleType(mRequestedApnType)) {
3484                     log("getPreferredApn: For APN type "
3485                             + ApnSetting.getApnTypeString(mRequestedApnType) + " found apnSetting "
3486                             + p);
3487                     cursor.close();
3488                     return p;
3489                 }
3490             }
3491         }
3492 
3493         if (cursor != null) {
3494             cursor.close();
3495         }
3496 
3497         log("getPreferredApn: X not found");
3498         return null;
3499     }
3500 
3501     @Override
handleMessage(Message msg)3502     public void handleMessage (Message msg) {
3503         if (VDBG) log("handleMessage msg=" + msg);
3504 
3505         AsyncResult ar;
3506         Pair<ApnContext, Integer> pair;
3507         ApnContext apnContext;
3508         int generation;
3509         int requestType;
3510         switch (msg.what) {
3511             case DctConstants.EVENT_DATA_CONNECTION_DETACHED:
3512                 onDataConnectionDetached();
3513                 break;
3514 
3515             case DctConstants.EVENT_DATA_CONNECTION_ATTACHED:
3516                 onDataConnectionAttached();
3517                 break;
3518 
3519             case DctConstants.EVENT_DO_RECOVERY:
3520                 mDsRecoveryHandler.doRecovery();
3521                 break;
3522 
3523             case DctConstants.EVENT_APN_CHANGED:
3524                 onApnChanged();
3525                 break;
3526 
3527             case DctConstants.EVENT_PS_RESTRICT_ENABLED:
3528                 /**
3529                  * We don't need to explicitly to tear down the PDP context
3530                  * when PS restricted is enabled. The base band will deactive
3531                  * PDP context and notify us with PDP_CONTEXT_CHANGED.
3532                  * But we should stop the network polling and prevent reset PDP.
3533                  */
3534                 if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
3535                 stopNetStatPoll();
3536                 stopDataStallAlarm();
3537                 mIsPsRestricted = true;
3538                 break;
3539 
3540             case DctConstants.EVENT_PS_RESTRICT_DISABLED:
3541                 /**
3542                  * When PS restrict is removed, we need setup PDP connection if
3543                  * PDP connection is down.
3544                  */
3545                 if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
3546                 mIsPsRestricted  = false;
3547                 if (isAnyDataConnected()) {
3548                     startNetStatPoll();
3549                     startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
3550                 } else {
3551                     // TODO: Should all PDN states be checked to fail?
3552                     if (mState == DctConstants.State.FAILED) {
3553                         cleanUpAllConnectionsInternal(false, Phone.REASON_PS_RESTRICT_ENABLED);
3554                         mReregisterOnReconnectFailure = false;
3555                     }
3556                     apnContext = mApnContextsByType.get(ApnSetting.TYPE_DEFAULT);
3557                     if (apnContext != null) {
3558                         apnContext.setReason(Phone.REASON_PS_RESTRICT_ENABLED);
3559                         trySetupData(apnContext, REQUEST_TYPE_NORMAL);
3560                     } else {
3561                         loge("**** Default ApnContext not found ****");
3562                         if (TelephonyUtils.IS_DEBUGGABLE) {
3563                             throw new RuntimeException("Default ApnContext not found");
3564                         }
3565                     }
3566                 }
3567                 break;
3568 
3569             case DctConstants.EVENT_TRY_SETUP_DATA:
3570                 trySetupData((ApnContext) msg.obj, REQUEST_TYPE_NORMAL);
3571                 break;
3572 
3573             case DctConstants.EVENT_CLEAN_UP_CONNECTION:
3574                 if (DBG) log("EVENT_CLEAN_UP_CONNECTION");
3575                 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, (ApnContext) msg.obj);
3576                 break;
3577             case DctConstants.EVENT_CLEAN_UP_ALL_CONNECTIONS:
3578                 if ((msg.obj != null) && (msg.obj instanceof String == false)) {
3579                     msg.obj = null;
3580                 }
3581                 cleanUpAllConnectionsInternal(true, (String) msg.obj);
3582                 break;
3583 
3584             case DctConstants.EVENT_DATA_RAT_CHANGED:
3585                 if (getDataRat() == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
3586                     // unknown rat is an exception for data rat change. It's only received when out
3587                     // of service and is not applicable for apn bearer bitmask. We should bypass the
3588                     // check of waiting apn list and keep the data connection on, and no need to
3589                     // setup a new one.
3590                     break;
3591                 }
3592                 cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED);
3593                 //May new Network allow setupData, so try it here
3594                 setupDataOnAllConnectableApns(Phone.REASON_NW_TYPE_CHANGED,
3595                         RetryFailures.ONLY_ON_CHANGE);
3596                 break;
3597 
3598             case DctConstants.CMD_CLEAR_PROVISIONING_SPINNER:
3599                 // Check message sender intended to clear the current spinner.
3600                 if (mProvisioningSpinner == msg.obj) {
3601                     mProvisioningSpinner.dismiss();
3602                     mProvisioningSpinner = null;
3603                 }
3604                 break;
3605 
3606             case DctConstants.EVENT_ENABLE_APN:
3607                 onEnableApn(msg.arg1, msg.arg2, (Message) msg.obj);
3608                 break;
3609 
3610             case DctConstants.EVENT_DISABLE_APN:
3611                 onDisableApn(msg.arg1, msg.arg2);
3612                 break;
3613 
3614             case DctConstants.EVENT_DATA_STALL_ALARM:
3615                 onDataStallAlarm(msg.arg1);
3616                 break;
3617 
3618             case DctConstants.EVENT_ROAMING_OFF:
3619                 onDataRoamingOff();
3620                 break;
3621 
3622             case DctConstants.EVENT_ROAMING_ON:
3623             case DctConstants.EVENT_ROAMING_SETTING_CHANGE:
3624                 onDataRoamingOnOrSettingsChanged(msg.what);
3625                 break;
3626 
3627             case DctConstants.EVENT_DEVICE_PROVISIONED_CHANGE:
3628                 // Update sharedPreference to false when exits new device provisioning, indicating
3629                 // no users modifications on the settings for new devices. Thus carrier specific
3630                 // default roaming settings can be applied for new devices till user modification.
3631                 final SharedPreferences sp = PreferenceManager
3632                         .getDefaultSharedPreferences(mPhone.getContext());
3633                 if (!sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) {
3634                     sp.edit().putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, false).commit();
3635                 }
3636                 break;
3637 
3638             case DctConstants.EVENT_NETWORK_STATUS_CHANGED:
3639                 int status = msg.arg1;
3640                 int cid = msg.arg2;
3641                 String url = (String) msg.obj;
3642                 onNetworkStatusChanged(status, cid, url);
3643                 break;
3644 
3645             case DctConstants.EVENT_RADIO_AVAILABLE:
3646                 onRadioAvailable();
3647                 break;
3648 
3649             case DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
3650                 onRadioOffOrNotAvailable();
3651                 break;
3652 
3653             case DctConstants.EVENT_DATA_SETUP_COMPLETE:
3654                 ar = (AsyncResult) msg.obj;
3655                 pair = (Pair<ApnContext, Integer>) ar.userObj;
3656                 apnContext = pair.first;
3657                 generation = pair.second;
3658                 requestType = msg.arg2;
3659                 if (apnContext.getConnectionGeneration() == generation) {
3660                     boolean success = true;
3661                     int cause = DataFailCause.UNKNOWN;
3662                     if (ar.exception != null) {
3663                         success = false;
3664                         cause = (int) ar.result;
3665                     }
3666                     onDataSetupComplete(apnContext, success, cause, requestType);
3667                 } else {
3668                     loge("EVENT_DATA_SETUP_COMPLETE: Dropped the event because generation "
3669                             + "did not match.");
3670                 }
3671                 break;
3672 
3673             case DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR:
3674                 ar = (AsyncResult) msg.obj;
3675                 pair = (Pair<ApnContext, Integer>) ar.userObj;
3676                 apnContext = pair.first;
3677                 generation = pair.second;
3678                 requestType = msg.arg2;
3679                 if (apnContext.getConnectionGeneration() == generation) {
3680                     onDataSetupCompleteError(apnContext, requestType);
3681                 } else {
3682                     loge("EVENT_DATA_SETUP_COMPLETE_ERROR: Dropped the event because generation "
3683                             + "did not match.");
3684                 }
3685                 break;
3686 
3687             case DctConstants.EVENT_DISCONNECT_DONE:
3688                 log("EVENT_DISCONNECT_DONE msg=" + msg);
3689                 ar = (AsyncResult) msg.obj;
3690                 pair = (Pair<ApnContext, Integer>) ar.userObj;
3691                 apnContext = pair.first;
3692                 generation = pair.second;
3693                 if (apnContext.getConnectionGeneration() == generation) {
3694                     onDisconnectDone(apnContext);
3695                 } else {
3696                     loge("EVENT_DISCONNECT_DONE: Dropped the event because generation "
3697                             + "did not match.");
3698                 }
3699                 break;
3700 
3701             case DctConstants.EVENT_VOICE_CALL_STARTED:
3702                 onVoiceCallStarted();
3703                 break;
3704 
3705             case DctConstants.EVENT_VOICE_CALL_ENDED:
3706                 onVoiceCallEnded();
3707                 break;
3708             case DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: {
3709                 sEnableFailFastRefCounter += (msg.arg1 == DctConstants.ENABLED) ? 1 : -1;
3710                 if (DBG) {
3711                     log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: "
3712                             + " sEnableFailFastRefCounter=" + sEnableFailFastRefCounter);
3713                 }
3714                 if (sEnableFailFastRefCounter < 0) {
3715                     final String s = "CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: "
3716                             + "sEnableFailFastRefCounter:" + sEnableFailFastRefCounter + " < 0";
3717                     loge(s);
3718                     sEnableFailFastRefCounter = 0;
3719                 }
3720                 final boolean enabled = sEnableFailFastRefCounter > 0;
3721                 if (DBG) {
3722                     log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: enabled=" + enabled
3723                             + " sEnableFailFastRefCounter=" + sEnableFailFastRefCounter);
3724                 }
3725                 if (mFailFast != enabled) {
3726                     mFailFast = enabled;
3727 
3728                     mDataStallNoRxEnabled = !enabled;
3729                     if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled()
3730                             && isAnyDataConnected()
3731                             && (!mInVoiceCall ||
3732                                     mPhone.getServiceStateTracker()
3733                                         .isConcurrentVoiceAndDataAllowed())) {
3734                         if (DBG) log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: start data stall");
3735                         stopDataStallAlarm();
3736                         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
3737                     } else {
3738                         if (DBG) log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: stop data stall");
3739                         stopDataStallAlarm();
3740                     }
3741                 }
3742 
3743                 break;
3744             }
3745             case DctConstants.CMD_ENABLE_MOBILE_PROVISIONING: {
3746                 Bundle bundle = msg.getData();
3747                 if (bundle != null) {
3748                     try {
3749                         mProvisioningUrl = (String)bundle.get(DctConstants.PROVISIONING_URL_KEY);
3750                     } catch(ClassCastException e) {
3751                         loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioning url not a string" + e);
3752                         mProvisioningUrl = null;
3753                     }
3754                 }
3755                 if (TextUtils.isEmpty(mProvisioningUrl)) {
3756                     loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioning url is empty, ignoring");
3757                     mIsProvisioning = false;
3758                     mProvisioningUrl = null;
3759                 } else {
3760                     loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioningUrl=" + mProvisioningUrl);
3761                     mIsProvisioning = true;
3762                     startProvisioningApnAlarm();
3763                 }
3764                 break;
3765             }
3766             case DctConstants.EVENT_PROVISIONING_APN_ALARM: {
3767                 if (DBG) log("EVENT_PROVISIONING_APN_ALARM");
3768                 ApnContext apnCtx = mApnContextsByType.get(ApnSetting.TYPE_DEFAULT);
3769                 if (apnCtx.isProvisioningApn() && apnCtx.isConnectedOrConnecting()) {
3770                     if (mProvisioningApnAlarmTag == msg.arg1) {
3771                         if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Disconnecting");
3772                         mIsProvisioning = false;
3773                         mProvisioningUrl = null;
3774                         stopProvisioningApnAlarm();
3775                         cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnCtx);
3776                     } else {
3777                         if (DBG) {
3778                             log("EVENT_PROVISIONING_APN_ALARM: ignore stale tag,"
3779                                     + " mProvisioningApnAlarmTag:" + mProvisioningApnAlarmTag
3780                                     + " != arg1:" + msg.arg1);
3781                         }
3782                     }
3783                 } else {
3784                     if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Not connected ignore");
3785                 }
3786                 break;
3787             }
3788             case DctConstants.CMD_IS_PROVISIONING_APN: {
3789                 if (DBG) log("CMD_IS_PROVISIONING_APN");
3790                 boolean isProvApn;
3791                 try {
3792                     String apnType = null;
3793                     Bundle bundle = msg.getData();
3794                     if (bundle != null) {
3795                         apnType = (String)bundle.get(DctConstants.APN_TYPE_KEY);
3796                     }
3797                     if (TextUtils.isEmpty(apnType)) {
3798                         loge("CMD_IS_PROVISIONING_APN: apnType is empty");
3799                         isProvApn = false;
3800                     } else {
3801                         isProvApn = isProvisioningApn(apnType);
3802                     }
3803                 } catch (ClassCastException e) {
3804                     loge("CMD_IS_PROVISIONING_APN: NO provisioning url ignoring");
3805                     isProvApn = false;
3806                 }
3807                 if (DBG) log("CMD_IS_PROVISIONING_APN: ret=" + isProvApn);
3808                 mReplyAc.replyToMessage(msg, DctConstants.CMD_IS_PROVISIONING_APN,
3809                         isProvApn ? DctConstants.ENABLED : DctConstants.DISABLED);
3810                 break;
3811             }
3812             case DctConstants.EVENT_RESTART_RADIO: {
3813                 restartRadio();
3814                 break;
3815             }
3816             case DctConstants.CMD_NET_STAT_POLL: {
3817                 if (msg.arg1 == DctConstants.ENABLED) {
3818                     handleStartNetStatPoll((DctConstants.Activity)msg.obj);
3819                 } else if (msg.arg1 == DctConstants.DISABLED) {
3820                     handleStopNetStatPoll((DctConstants.Activity)msg.obj);
3821                 }
3822                 break;
3823             }
3824             case DctConstants.EVENT_PCO_DATA_RECEIVED: {
3825                 handlePcoData((AsyncResult)msg.obj);
3826                 break;
3827             }
3828             case DctConstants.EVENT_DATA_RECONNECT:
3829                 if (DBG) log("EVENT_DATA_RECONNECT: subId=" + msg.arg1);
3830                 onDataReconnect((ApnContext) msg.obj, msg.arg1);
3831                 break;
3832             case DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED:
3833                 onDataServiceBindingChanged((Boolean) ((AsyncResult) msg.obj).result);
3834                 break;
3835             case DctConstants.EVENT_DATA_ENABLED_CHANGED:
3836                 ar = (AsyncResult) msg.obj;
3837                 if (ar.result instanceof Pair) {
3838                     Pair<Boolean, Integer> p = (Pair<Boolean, Integer>) ar.result;
3839                     boolean enabled = p.first;
3840                     int reason = p.second;
3841                     onDataEnabledChanged(enabled, reason);
3842                 }
3843                 break;
3844             case DctConstants.EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED:
3845                 onDataEnabledOverrideRulesChanged();
3846                 break;
3847             case DctConstants.EVENT_NR_TIMER_WATCHDOG:
3848                 mWatchdog = false;
3849                 reevaluateUnmeteredConnections();
3850                 break;
3851             case DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED:
3852                 reevaluateUnmeteredConnections();
3853                 break;
3854             case DctConstants.EVENT_CARRIER_CONFIG_CHANGED:
3855                 onCarrierConfigChanged();
3856                 break;
3857             case DctConstants.EVENT_SIM_STATE_UPDATED:
3858                 int simState = msg.arg1;
3859                 onSimStateUpdated(simState);
3860                 break;
3861             default:
3862                 Rlog.e("DcTracker", "Unhandled event=" + msg);
3863                 break;
3864 
3865         }
3866     }
3867 
getApnProfileID(String apnType)3868     private int getApnProfileID(String apnType) {
3869         if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_IMS)) {
3870             return RILConstants.DATA_PROFILE_IMS;
3871         } else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_FOTA)) {
3872             return RILConstants.DATA_PROFILE_FOTA;
3873         } else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_CBS)) {
3874             return RILConstants.DATA_PROFILE_CBS;
3875         } else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_IA)) {
3876             return RILConstants.DATA_PROFILE_DEFAULT; // DEFAULT for now
3877         } else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_DUN)) {
3878             return RILConstants.DATA_PROFILE_TETHERED;
3879         } else {
3880             return RILConstants.DATA_PROFILE_DEFAULT;
3881         }
3882     }
3883 
getCellLocationId()3884     private int getCellLocationId() {
3885         int cid = -1;
3886         CellLocation loc = mPhone.getCellIdentity().asCellLocation();
3887 
3888         if (loc != null) {
3889             if (loc instanceof GsmCellLocation) {
3890                 cid = ((GsmCellLocation)loc).getCid();
3891             } else if (loc instanceof CdmaCellLocation) {
3892                 cid = ((CdmaCellLocation)loc).getBaseStationId();
3893             }
3894         }
3895         return cid;
3896     }
3897 
3898     /**
3899      * Update link bandwidth estimate default values from carrier config.
3900      * @param bandwidths String array of "RAT:upstream,downstream" for each RAT
3901      * @param useLte For NR NSA, whether to use LTE value for upstream or not
3902      */
updateLinkBandwidths(String[] bandwidths, boolean useLte)3903     private void updateLinkBandwidths(String[] bandwidths, boolean useLte) {
3904         ConcurrentHashMap<String, Pair<Integer, Integer>> temp = new ConcurrentHashMap<>();
3905         for (String config : bandwidths) {
3906             int downstream = 14;
3907             int upstream = 14;
3908             String[] kv = config.split(":");
3909             if (kv.length == 2) {
3910                 String[] split = kv[1].split(",");
3911                 if (split.length == 2) {
3912                     try {
3913                         downstream = Integer.parseInt(split[0]);
3914                         upstream = Integer.parseInt(split[1]);
3915                     } catch (NumberFormatException ignored) {
3916                     }
3917                 }
3918                 temp.put(kv[0], new Pair<>(downstream, upstream));
3919             }
3920         }
3921         if (useLte) {
3922             Pair<Integer, Integer> ltePair = temp.get(DctConstants.RAT_NAME_LTE);
3923             if (ltePair != null) {
3924                 if (temp.containsKey(DctConstants.RAT_NAME_NR_NSA)) {
3925                     temp.put(DctConstants.RAT_NAME_NR_NSA, new Pair<>(
3926                             temp.get(DctConstants.RAT_NAME_NR_NSA).first, ltePair.second));
3927                 }
3928                 if (temp.containsKey(DctConstants.RAT_NAME_NR_NSA_MMWAVE)) {
3929                     temp.put(DctConstants.RAT_NAME_NR_NSA_MMWAVE, new Pair<>(
3930                             temp.get(DctConstants.RAT_NAME_NR_NSA_MMWAVE).first, ltePair.second));
3931                 }
3932             }
3933         }
3934         mBandwidths = temp;
3935         for (DataConnection dc : mDataConnections.values()) {
3936             dc.sendMessage(DataConnection.EVENT_CARRIER_CONFIG_LINK_BANDWIDTHS_CHANGED);
3937         }
3938     }
3939 
3940     /**
3941      * Return the link upstream/downstream values from CarrierConfig for the given RAT name.
3942      * @param ratName RAT name from ServiceState#rilRadioTechnologyToString.
3943      * @return pair of downstream/upstream values (kbps), or null if the config is not defined.
3944      */
getLinkBandwidthsFromCarrierConfig(String ratName)3945     public Pair<Integer, Integer> getLinkBandwidthsFromCarrierConfig(String ratName) {
3946         return mBandwidths.get(ratName);
3947     }
3948 
3949     @VisibleForTesting
shouldAutoAttach()3950     public boolean shouldAutoAttach() {
3951         if (mAutoAttachEnabled.get()) return true;
3952 
3953         PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance();
3954         ServiceState serviceState = mPhone.getServiceState();
3955 
3956         if (phoneSwitcher == null || serviceState == null) return false;
3957 
3958         // If voice is also not in service, don't auto attach.
3959         if (serviceState.getState() != ServiceState.STATE_IN_SERVICE) return false;
3960 
3961         // If voice is on LTE or NR, don't auto attach as for LTE / NR data would be attached.
3962         if (serviceState.getVoiceNetworkType() == NETWORK_TYPE_LTE
3963                 || serviceState.getVoiceNetworkType() == NETWORK_TYPE_NR) return false;
3964 
3965         // If phone is non default phone, modem may have detached from data for optimization.
3966         // If phone is in voice call, for DSDS case DDS switch may be limited so we do try our
3967         // best to setup data connection and allow auto-attach.
3968         return (mPhone.getPhoneId() != phoneSwitcher.getPreferredDataPhoneId()
3969                 || mPhone.getState() != PhoneConstants.State.IDLE);
3970     }
3971 
notifyAllDataDisconnected()3972     private void notifyAllDataDisconnected() {
3973         sEnableFailFastRefCounter = 0;
3974         mFailFast = false;
3975         mAllDataDisconnectedRegistrants.notifyRegistrants();
3976     }
3977 
registerForAllDataDisconnected(Handler h, int what)3978     public void registerForAllDataDisconnected(Handler h, int what) {
3979         mAllDataDisconnectedRegistrants.addUnique(h, what, null);
3980 
3981         if (areAllDataDisconnected()) {
3982             log("notify All Data Disconnected");
3983             notifyAllDataDisconnected();
3984         }
3985     }
3986 
unregisterForAllDataDisconnected(Handler h)3987     public void unregisterForAllDataDisconnected(Handler h) {
3988         mAllDataDisconnectedRegistrants.remove(h);
3989     }
3990 
onDataEnabledChanged(boolean enable, @DataEnabledChangedReason int enabledChangedReason)3991     private void onDataEnabledChanged(boolean enable,
3992                                       @DataEnabledChangedReason int enabledChangedReason) {
3993         if (DBG) {
3994             log("onDataEnabledChanged: enable=" + enable + ", enabledChangedReason="
3995                     + enabledChangedReason);
3996         }
3997 
3998         if (enable) {
3999             reevaluateDataConnections();
4000             setupDataOnAllConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS);
4001         } else {
4002             String cleanupReason;
4003             switch (enabledChangedReason) {
4004                 case DataEnabledSettings.REASON_INTERNAL_DATA_ENABLED:
4005                     cleanupReason = Phone.REASON_DATA_DISABLED_INTERNAL;
4006                     break;
4007                 case DataEnabledSettings.REASON_DATA_ENABLED_BY_CARRIER:
4008                     cleanupReason = Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN;
4009                     break;
4010                 case DataEnabledSettings.REASON_USER_DATA_ENABLED:
4011                 case DataEnabledSettings.REASON_POLICY_DATA_ENABLED:
4012                 case DataEnabledSettings.REASON_PROVISIONED_CHANGED:
4013                 case DataEnabledSettings.REASON_PROVISIONING_DATA_ENABLED_CHANGED:
4014                 default:
4015                     cleanupReason = Phone.REASON_DATA_SPECIFIC_DISABLED;
4016                     break;
4017 
4018             }
4019             cleanUpAllConnectionsInternal(true, cleanupReason);
4020         }
4021     }
4022 
reevaluateUnmeteredConnections()4023     private void reevaluateUnmeteredConnections() {
4024         log("reevaluateUnmeteredConnections");
4025         int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType();
4026         int override = mPhone.getDisplayInfoController().getTelephonyDisplayInfo()
4027                 .getOverrideNetworkType();
4028         boolean nrPlanUnmetered = isNetworkTypeUnmetered(NETWORK_TYPE_NR) && (rat == NETWORK_TYPE_NR
4029                 || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA
4030                 || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE);
4031         if ((nrPlanUnmetered || isNrNsaFrequencyRangeUnmetered() || isNrSaFrequencyRangeUnmetered())
4032                 && !mPhone.getServiceState().getRoaming() || mRoamingUnmetered) {
4033             if (DBG) log("NR is unmetered");
4034             setDataConnectionUnmetered(true);
4035             if (!mWatchdog) {
4036                 startWatchdogAlarm();
4037             }
4038         } else {
4039             stopWatchdogAlarm();
4040             setDataConnectionUnmetered(isNetworkTypeUnmetered(rat));
4041         }
4042     }
4043 
setDataConnectionUnmetered(boolean isUnmetered)4044     private void setDataConnectionUnmetered(boolean isUnmetered) {
4045         for (DataConnection dataConnection : mDataConnections.values()) {
4046             dataConnection.onMeterednessChanged(isUnmetered);
4047         }
4048     }
4049 
isNetworkTypeUnmetered(@etworkType int networkType)4050     private boolean isNetworkTypeUnmetered(@NetworkType int networkType) {
4051         if (mSubscriptionPlans == null || mSubscriptionPlans.size() == 0) {
4052             // safe return false if unable to get subscription plans or plans don't exist
4053             return false;
4054         }
4055 
4056         boolean isGeneralUnmetered = true;
4057         Set<Integer> allNetworkTypes = Arrays.stream(TelephonyManager.getAllNetworkTypes())
4058                 .boxed().collect(Collectors.toSet());
4059         for (SubscriptionPlan plan : mSubscriptionPlans) {
4060             // check plan is general (applies to all network types) or specific
4061             if (Arrays.stream(plan.getNetworkTypes()).boxed().collect(Collectors.toSet())
4062                     .containsAll(allNetworkTypes)) {
4063                 if (!isPlanUnmetered(plan)) {
4064                     // metered takes precedence over unmetered for safety
4065                     isGeneralUnmetered = false;
4066                 }
4067             } else {
4068                 // check plan applies to given network type
4069                 if (networkType != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
4070                     for (int planNetworkType : plan.getNetworkTypes()) {
4071                         if (planNetworkType == networkType) {
4072                             return isPlanUnmetered(plan);
4073                         }
4074                     }
4075                 }
4076             }
4077         }
4078         return isGeneralUnmetered;
4079     }
4080 
isPlanUnmetered(SubscriptionPlan plan)4081     private boolean isPlanUnmetered(SubscriptionPlan plan) {
4082         return plan.getDataLimitBytes() == SubscriptionPlan.BYTES_UNLIMITED
4083                 && (plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN
4084                 || plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED);
4085     }
4086 
isNrNsaFrequencyRangeUnmetered()4087     private boolean isNrNsaFrequencyRangeUnmetered() {
4088         int override = mPhone.getDisplayInfoController().getTelephonyDisplayInfo()
4089                 .getOverrideNetworkType();
4090         if (mNrNsaMmwaveUnmetered || mNrNsaSub6Unmetered) {
4091             return (mNrNsaMmwaveUnmetered
4092                     && override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE)
4093                     || (mNrNsaSub6Unmetered
4094                     && override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA);
4095         } else {
4096             return mNrNsaAllUnmetered
4097                     && (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE
4098                     || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA);
4099         }
4100     }
4101 
isNrSaFrequencyRangeUnmetered()4102     private boolean isNrSaFrequencyRangeUnmetered() {
4103         if (ServiceState.rilRadioTechnologyToNetworkType(getDataRat()) != NETWORK_TYPE_NR) {
4104             return false;
4105         }
4106         if (mNrSaMmwaveUnmetered || mNrSaSub6Unmetered) {
4107             int frequencyRange = mPhone.getServiceState().getNrFrequencyRange();
4108             boolean mmwave = frequencyRange == ServiceState.FREQUENCY_RANGE_MMWAVE;
4109             // frequency range LOW, MID, or HIGH
4110             boolean sub6 = frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN && !mmwave;
4111             return mNrSaMmwaveUnmetered && mmwave || mNrSaSub6Unmetered && sub6;
4112         } else {
4113             return mNrSaAllUnmetered;
4114         }
4115     }
4116 
log(String s)4117     protected void log(String s) {
4118         Rlog.d(mLogTag, s);
4119     }
4120 
loge(String s)4121     private void loge(String s) {
4122         Rlog.e(mLogTag, s);
4123     }
4124 
logSortedApnContexts()4125     private void logSortedApnContexts() {
4126         if (VDBG) {
4127             log("initApnContexts: X mApnContexts=" + mApnContexts);
4128 
4129             StringBuilder sb = new StringBuilder();
4130             sb.append("sorted apncontexts -> [");
4131             for (ApnContext apnContext : mPrioritySortedApnContexts) {
4132                 sb.append(apnContext);
4133                 sb.append(", ");
4134 
4135                 log("sorted list");
4136             }
4137             sb.append("]");
4138             log(sb.toString());
4139         }
4140     }
4141 
dump(FileDescriptor fd, PrintWriter pw, String[] args)4142     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4143         pw.println("DcTracker:");
4144         pw.println(" RADIO_TESTS=" + RADIO_TESTS);
4145         pw.println(" mDataEnabledSettings=" + mDataEnabledSettings);
4146         pw.println(" isDataAllowed=" + isDataAllowed(null));
4147         pw.flush();
4148         pw.println(" mRequestedApnType=" + mRequestedApnType);
4149         pw.println(" mPhone=" + mPhone.getPhoneName());
4150         pw.println(" mConfigReady=" + mConfigReady);
4151         pw.println(" mSimState=" + SubscriptionInfoUpdater.simStateString(mSimState));
4152         pw.println(" mActivity=" + mActivity);
4153         pw.println(" mState=" + mState);
4154         pw.println(" mTxPkts=" + mTxPkts);
4155         pw.println(" mRxPkts=" + mRxPkts);
4156         pw.println(" mNetStatPollPeriod=" + mNetStatPollPeriod);
4157         pw.println(" mNetStatPollEnabled=" + mNetStatPollEnabled);
4158         pw.println(" mDataStallTxRxSum=" + mDataStallTxRxSum);
4159         pw.println(" mDataStallAlarmTag=" + mDataStallAlarmTag);
4160         pw.println(" mDataStallNoRxEnabled=" + mDataStallNoRxEnabled);
4161         pw.println(" mEmergencyApn=" + mEmergencyApn);
4162         pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv);
4163         pw.println(" mNoRecvPollCount=" + mNoRecvPollCount);
4164         pw.println(" mResolver=" + mResolver);
4165         pw.println(" mReconnectIntent=" + mReconnectIntent);
4166         pw.println(" mAutoAttachEnabled=" + mAutoAttachEnabled.get());
4167         pw.println(" mIsScreenOn=" + mIsScreenOn);
4168         pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator);
4169         pw.println(" mDataServiceBound=" + mDataServiceBound);
4170         pw.println(" mDataRoamingLeakageLog= ");
4171         mDataRoamingLeakageLog.dump(fd, pw, args);
4172         pw.println(" mApnSettingsInitializationLog= ");
4173         mApnSettingsInitializationLog.dump(fd, pw, args);
4174         pw.flush();
4175         pw.println(" ***************************************");
4176         DcController dcc = mDcc;
4177         if (dcc != null) {
4178             if (mDataServiceBound) {
4179                 dcc.dump(fd, pw, args);
4180             } else {
4181                 pw.println(" Can't dump mDcc because data service is not bound.");
4182             }
4183         } else {
4184             pw.println(" mDcc=null");
4185         }
4186         pw.println(" ***************************************");
4187         HashMap<Integer, DataConnection> dcs = mDataConnections;
4188         if (dcs != null) {
4189             Set<Entry<Integer, DataConnection> > mDcSet = mDataConnections.entrySet();
4190             pw.println(" mDataConnections: count=" + mDcSet.size());
4191             for (Entry<Integer, DataConnection> entry : mDcSet) {
4192                 pw.printf(" *** mDataConnection[%d] \n", entry.getKey());
4193                 entry.getValue().dump(fd, pw, args);
4194             }
4195         } else {
4196             pw.println("mDataConnections=null");
4197         }
4198         pw.println(" ***************************************");
4199         pw.flush();
4200         HashMap<String, Integer> apnToDcId = mApnToDataConnectionId;
4201         if (apnToDcId != null) {
4202             Set<Entry<String, Integer>> apnToDcIdSet = apnToDcId.entrySet();
4203             pw.println(" mApnToDataConnectonId size=" + apnToDcIdSet.size());
4204             for (Entry<String, Integer> entry : apnToDcIdSet) {
4205                 pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue());
4206             }
4207         } else {
4208             pw.println("mApnToDataConnectionId=null");
4209         }
4210         pw.println(" ***************************************");
4211         pw.flush();
4212         ConcurrentHashMap<String, ApnContext> apnCtxs = mApnContexts;
4213         if (apnCtxs != null) {
4214             Set<Entry<String, ApnContext>> apnCtxsSet = apnCtxs.entrySet();
4215             pw.println(" mApnContexts size=" + apnCtxsSet.size());
4216             for (Entry<String, ApnContext> entry : apnCtxsSet) {
4217                 entry.getValue().dump(fd, pw, args);
4218             }
4219             pw.println(" ***************************************");
4220         } else {
4221             pw.println(" mApnContexts=null");
4222         }
4223         pw.flush();
4224 
4225         pw.println(" mAllApnSettings size=" + mAllApnSettings.size());
4226         for (int i = 0; i < mAllApnSettings.size(); i++) {
4227             pw.printf(" mAllApnSettings[%d]: %s\n", i, mAllApnSettings.get(i));
4228         }
4229         pw.flush();
4230 
4231         pw.println(" mPreferredApn=" + mPreferredApn);
4232         pw.println(" mIsPsRestricted=" + mIsPsRestricted);
4233         pw.println(" mIsDisposed=" + mIsDisposed);
4234         pw.println(" mIntentReceiver=" + mIntentReceiver);
4235         pw.println(" mReregisterOnReconnectFailure=" + mReregisterOnReconnectFailure);
4236         pw.println(" canSetPreferApn=" + mCanSetPreferApn);
4237         pw.println(" mApnObserver=" + mApnObserver);
4238         pw.println(" isAnyDataConnected=" + isAnyDataConnected());
4239         pw.println(" mAttached=" + mAttached.get());
4240         mDataEnabledSettings.dump(fd, pw, args);
4241         pw.flush();
4242     }
4243 
getPcscfAddress(String apnType)4244     public String[] getPcscfAddress(String apnType) {
4245         log("getPcscfAddress()");
4246         ApnContext apnContext = null;
4247 
4248         if(apnType == null){
4249             log("apnType is null, return null");
4250             return null;
4251         }
4252 
4253         if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_EMERGENCY)) {
4254             apnContext = mApnContextsByType.get(ApnSetting.TYPE_EMERGENCY);
4255         } else if (TextUtils.equals(apnType, PhoneConstants.APN_TYPE_IMS)) {
4256             apnContext = mApnContextsByType.get(ApnSetting.TYPE_IMS);
4257         } else {
4258             log("apnType is invalid, return null");
4259             return null;
4260         }
4261 
4262         if (apnContext == null) {
4263             log("apnContext is null, return null");
4264             return null;
4265         }
4266 
4267         DataConnection dataConnection = apnContext.getDataConnection();
4268         String[] result = null;
4269 
4270         if (dataConnection != null) {
4271             result = dataConnection.getPcscfAddresses();
4272 
4273             if (result != null) {
4274                 for (int i = 0; i < result.length; i++) {
4275                     log("Pcscf[" + i + "]: " + result[i]);
4276                 }
4277             }
4278             return result;
4279         }
4280         return null;
4281     }
4282 
4283     /**
4284      * Read APN configuration from Telephony.db for Emergency APN
4285      * All operators recognize the connection request for EPDN based on APN type
4286      * PLMN name,APN name are not mandatory parameters
4287      */
initEmergencyApnSetting()4288     private void initEmergencyApnSetting() {
4289         // Operator Numeric is not available when SIM is not ready.
4290         // Query Telephony.db with APN type as EPDN request does not
4291         // require APN name, plmn and all operators support same APN config.
4292         // DB will contain only one entry for Emergency APN
4293         String selection = "type=\"emergency\"";
4294         Cursor cursor = mPhone.getContext().getContentResolver().query(
4295                 Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "filtered"),
4296                 null, selection, null, null);
4297 
4298         if (cursor != null) {
4299             if (cursor.getCount() > 0) {
4300                 if (cursor.moveToFirst()) {
4301                     mEmergencyApn = ApnSetting.makeApnSetting(cursor);
4302                 }
4303             }
4304             cursor.close();
4305         }
4306         if (mEmergencyApn != null) return;
4307 
4308         // If no emergency APN setting has been found, make one using reasonable defaults
4309         mEmergencyApn = new ApnSetting.Builder()
4310                 .setEntryName("Emergency")
4311                 .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
4312                 .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
4313                 .setNetworkTypeBitmask((int)(TelephonyManager.NETWORK_TYPE_BITMASK_LTE
4314                 | TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN))
4315                 .setApnName("sos")
4316                 .setApnTypeBitmask(ApnSetting.TYPE_EMERGENCY)
4317                 .setCarrierEnabled(true)
4318                 .build();
4319     }
4320 
4321     /**
4322      * Add the Emergency APN settings to APN settings list
4323      */
addEmergencyApnSetting()4324     private void addEmergencyApnSetting() {
4325         if(mEmergencyApn != null) {
4326             for (ApnSetting apn : mAllApnSettings) {
4327                 if (apn.canHandleType(ApnSetting.TYPE_EMERGENCY)) {
4328                     log("addEmergencyApnSetting - E-APN setting is already present");
4329                     return;
4330                 }
4331             }
4332 
4333             // If all of the APN settings cannot handle emergency, we add the emergency APN to the
4334             // list explicitly.
4335             if (!mAllApnSettings.contains(mEmergencyApn)) {
4336                 mAllApnSettings.add(mEmergencyApn);
4337                 log("Adding emergency APN : " + mEmergencyApn);
4338                 return;
4339             }
4340         }
4341     }
4342 
containsAllApns(List<ApnSetting> oldApnList, List<ApnSetting> newApnList)4343     private boolean containsAllApns(List<ApnSetting> oldApnList, List<ApnSetting> newApnList) {
4344         for (ApnSetting newApnSetting : newApnList) {
4345             boolean canHandle = false;
4346             for (ApnSetting oldApnSetting : oldApnList) {
4347                 // Make sure at least one of the APN from old list can cover the new APN
4348                 if (oldApnSetting.equals(newApnSetting,
4349                         mPhone.getServiceState().getDataRoamingFromRegistration())) {
4350                     canHandle = true;
4351                     break;
4352                 }
4353             }
4354             if (!canHandle) return false;
4355         }
4356         return true;
4357     }
4358 
cleanUpConnectionsOnUpdatedApns(boolean detach, String reason)4359     private void cleanUpConnectionsOnUpdatedApns(boolean detach, String reason) {
4360         if (DBG) log("cleanUpConnectionsOnUpdatedApns: detach=" + detach);
4361         if (mAllApnSettings.isEmpty()) {
4362             cleanUpAllConnectionsInternal(detach, Phone.REASON_APN_CHANGED);
4363         } else {
4364             if (getDataRat() == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
4365                 // unknown rat is an exception for data rat change. Its only received when out of
4366                 // service and is not applicable for apn bearer bitmask. We should bypass the check
4367                 // of waiting apn list and keep the data connection on.
4368                 return;
4369             }
4370             for (ApnContext apnContext : mApnContexts.values()) {
4371                 boolean cleanupRequired = true;
4372                 if (!apnContext.isDisconnected()) {
4373                     ArrayList<ApnSetting> waitingApns = buildWaitingApns(
4374                             apnContext.getApnType(), getDataRat());
4375                     apnContext.setWaitingApns(waitingApns);
4376                     for (ApnSetting apnSetting : waitingApns) {
4377                         if (apnSetting.equals(apnContext.getApnSetting(),
4378                                 mPhone.getServiceState().getDataRoamingFromRegistration())) {
4379                             cleanupRequired = false;
4380                             break;
4381                         }
4382                     }
4383 
4384                     if (cleanupRequired) {
4385                         if (DBG) {
4386                             log("cleanUpConnectionsOnUpdatedApns: APN type "
4387                                     + apnContext.getApnType() + " clean up is required. The new "
4388                                     + "waiting APN list " + waitingApns + " does not cover "
4389                                     + apnContext.getApnSetting());
4390                         }
4391                         apnContext.setReason(reason);
4392                         cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext);
4393                     }
4394                 }
4395             }
4396         }
4397 
4398         if (!isAnyDataConnected()) {
4399             stopNetStatPoll();
4400             stopDataStallAlarm();
4401         }
4402 
4403         mRequestedApnType = ApnSetting.TYPE_DEFAULT;
4404 
4405         if (DBG) log("mDisconnectPendingCount = " + mDisconnectPendingCount);
4406         if (detach && mDisconnectPendingCount == 0) {
4407             notifyAllDataDisconnected();
4408         }
4409     }
4410 
4411     /**
4412      * Polling stuff
4413      */
resetPollStats()4414     protected void resetPollStats() {
4415         mTxPkts = -1;
4416         mRxPkts = -1;
4417         mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
4418     }
4419 
startNetStatPoll()4420     protected void startNetStatPoll() {
4421         if (isAnyDataConnected() && !mNetStatPollEnabled) {
4422             if (DBG) {
4423                 log("startNetStatPoll");
4424             }
4425             resetPollStats();
4426             mNetStatPollEnabled = true;
4427             mPollNetStat.run();
4428         }
4429         if (mPhone != null) {
4430             mPhone.notifyDataActivity();
4431         }
4432     }
4433 
stopNetStatPoll()4434     private void stopNetStatPoll() {
4435         mNetStatPollEnabled = false;
4436         removeCallbacks(mPollNetStat);
4437         if (DBG) {
4438             log("stopNetStatPoll");
4439         }
4440 
4441         // To sync data activity icon in the case of switching data connection to send MMS.
4442         if (mPhone != null) {
4443             mPhone.notifyDataActivity();
4444         }
4445     }
4446 
sendStartNetStatPoll(DctConstants.Activity activity)4447     public void sendStartNetStatPoll(DctConstants.Activity activity) {
4448         Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL);
4449         msg.arg1 = DctConstants.ENABLED;
4450         msg.obj = activity;
4451         sendMessage(msg);
4452     }
4453 
handleStartNetStatPoll(DctConstants.Activity activity)4454     private void handleStartNetStatPoll(DctConstants.Activity activity) {
4455         startNetStatPoll();
4456         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
4457         setActivity(activity);
4458     }
4459 
sendStopNetStatPoll(DctConstants.Activity activity)4460     public void sendStopNetStatPoll(DctConstants.Activity activity) {
4461         Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL);
4462         msg.arg1 = DctConstants.DISABLED;
4463         msg.obj = activity;
4464         sendMessage(msg);
4465     }
4466 
handleStopNetStatPoll(DctConstants.Activity activity)4467     private void handleStopNetStatPoll(DctConstants.Activity activity) {
4468         stopNetStatPoll();
4469         stopDataStallAlarm();
4470         setActivity(activity);
4471     }
4472 
onDataEnabledOverrideRulesChanged()4473     private void onDataEnabledOverrideRulesChanged() {
4474         if (DBG) {
4475             log("onDataEnabledOverrideRulesChanged");
4476         }
4477 
4478         for (ApnContext apnContext : mPrioritySortedApnContexts) {
4479             if (isDataAllowed(apnContext, REQUEST_TYPE_NORMAL, null)) {
4480                 if (apnContext.getDataConnection() != null) {
4481                     apnContext.getDataConnection().reevaluateRestrictedState();
4482                 }
4483                 setupDataOnConnectableApn(apnContext, Phone.REASON_DATA_ENABLED_OVERRIDE,
4484                         RetryFailures.ALWAYS);
4485             } else if (shouldCleanUpConnection(apnContext, true, false)) {
4486                 apnContext.setReason(Phone.REASON_DATA_ENABLED_OVERRIDE);
4487                 cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext);
4488             }
4489         }
4490     }
4491 
updateDataActivity()4492     private void updateDataActivity() {
4493         long sent, received;
4494 
4495         DctConstants.Activity newActivity;
4496 
4497         TxRxSum preTxRxSum = new TxRxSum(mTxPkts, mRxPkts);
4498         TxRxSum curTxRxSum = new TxRxSum();
4499         curTxRxSum.updateTotalTxRxSum();
4500         mTxPkts = curTxRxSum.txPkts;
4501         mRxPkts = curTxRxSum.rxPkts;
4502 
4503         if (VDBG) {
4504             log("updateDataActivity: curTxRxSum=" + curTxRxSum + " preTxRxSum=" + preTxRxSum);
4505         }
4506 
4507         if (mNetStatPollEnabled && (preTxRxSum.txPkts > 0 || preTxRxSum.rxPkts > 0)) {
4508             sent = mTxPkts - preTxRxSum.txPkts;
4509             received = mRxPkts - preTxRxSum.rxPkts;
4510 
4511             if (VDBG)
4512                 log("updateDataActivity: sent=" + sent + " received=" + received);
4513             if (sent > 0 && received > 0) {
4514                 newActivity = DctConstants.Activity.DATAINANDOUT;
4515             } else if (sent > 0 && received == 0) {
4516                 newActivity = DctConstants.Activity.DATAOUT;
4517             } else if (sent == 0 && received > 0) {
4518                 newActivity = DctConstants.Activity.DATAIN;
4519             } else {
4520                 newActivity = (mActivity == DctConstants.Activity.DORMANT) ?
4521                         mActivity : DctConstants.Activity.NONE;
4522             }
4523 
4524             if (mActivity != newActivity && mIsScreenOn) {
4525                 if (VDBG)
4526                     log("updateDataActivity: newActivity=" + newActivity);
4527                 mActivity = newActivity;
4528                 mPhone.notifyDataActivity();
4529             }
4530         }
4531     }
4532 
handlePcoData(AsyncResult ar)4533     private void handlePcoData(AsyncResult ar) {
4534         if (ar.exception != null) {
4535             loge("PCO_DATA exception: " + ar.exception);
4536             return;
4537         }
4538         PcoData pcoData = (PcoData)(ar.result);
4539         ArrayList<DataConnection> dcList = new ArrayList<>();
4540         DataConnection temp = mDcc.getActiveDcByCid(pcoData.cid);
4541         if (temp != null) {
4542             dcList.add(temp);
4543         }
4544         if (dcList.size() == 0) {
4545             loge("PCO_DATA for unknown cid: " + pcoData.cid + ", inferring");
4546             for (DataConnection dc : mDataConnections.values()) {
4547                 final int cid = dc.getCid();
4548                 if (cid == pcoData.cid) {
4549                     if (VDBG) log("  found " + dc);
4550                     dcList.clear();
4551                     dcList.add(dc);
4552                     break;
4553                 }
4554                 // check if this dc is still connecting
4555                 if (cid == -1) {
4556                     for (ApnContext apnContext : dc.getApnContexts()) {
4557                         if (apnContext.getState() == DctConstants.State.CONNECTING) {
4558                             if (VDBG) log("  found potential " + dc);
4559                             dcList.add(dc);
4560                             break;
4561                         }
4562                     }
4563                 }
4564             }
4565         }
4566         if (dcList.size() == 0) {
4567             loge("PCO_DATA - couldn't infer cid");
4568             return;
4569         }
4570         for (DataConnection dc : dcList) {
4571             List<ApnContext> apnContextList = dc.getApnContexts();
4572             if (apnContextList.size() == 0) {
4573                 break;
4574             }
4575             // send one out for each apn type in play
4576             for (ApnContext apnContext : apnContextList) {
4577                 String apnType = apnContext.getApnType();
4578 
4579                 final Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE);
4580                 intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, apnType);
4581                 intent.putExtra(TelephonyManager.EXTRA_APN_TYPE_INT,
4582                         ApnSetting.getApnTypesBitmaskFromString(apnType));
4583                 intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, pcoData.bearerProto);
4584                 intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL_INT,
4585                         ApnSetting.getProtocolIntFromString(pcoData.bearerProto));
4586                 intent.putExtra(TelephonyManager.EXTRA_PCO_ID, pcoData.pcoId);
4587                 intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, pcoData.contents);
4588                 mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
4589             }
4590         }
4591     }
4592 
4593     /**
4594      * Data-Stall
4595      */
4596 
4597     // Recovery action taken in case of data stall
4598     @IntDef(
4599         value = {
4600             RECOVERY_ACTION_GET_DATA_CALL_LIST,
4601             RECOVERY_ACTION_CLEANUP,
4602             RECOVERY_ACTION_REREGISTER,
4603             RECOVERY_ACTION_RADIO_RESTART
4604         })
4605     @Retention(RetentionPolicy.SOURCE)
4606     private @interface RecoveryAction {};
4607     private static final int RECOVERY_ACTION_GET_DATA_CALL_LIST      = 0;
4608     private static final int RECOVERY_ACTION_CLEANUP                 = 1;
4609     private static final int RECOVERY_ACTION_REREGISTER              = 2;
4610     private static final int RECOVERY_ACTION_RADIO_RESTART           = 3;
4611 
4612     // Recovery handler class for cellular data stall
4613     private class DataStallRecoveryHandler {
4614         // Default minimum duration between each recovery steps
4615         private static final int
4616                 DEFAULT_MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS = (3 * 60 * 1000); // 3 mins
4617 
4618         // The elapsed real time of last recovery attempted
4619         private long mTimeLastRecoveryStartMs;
4620         // Whether current network good or not
4621         private boolean mIsValidNetwork;
4622 
DataStallRecoveryHandler()4623         public DataStallRecoveryHandler() {
4624             reset();
4625         }
4626 
reset()4627         public void reset() {
4628             mTimeLastRecoveryStartMs = 0;
4629             putRecoveryAction(RECOVERY_ACTION_GET_DATA_CALL_LIST);
4630         }
4631 
isAggressiveRecovery()4632         public boolean isAggressiveRecovery() {
4633             @RecoveryAction int action = getRecoveryAction();
4634 
4635             return ((action == RECOVERY_ACTION_CLEANUP)
4636                     || (action == RECOVERY_ACTION_REREGISTER)
4637                     || (action == RECOVERY_ACTION_RADIO_RESTART));
4638         }
4639 
getMinDurationBetweenRecovery()4640         private long getMinDurationBetweenRecovery() {
4641             return Settings.Global.getLong(mResolver,
4642                 Settings.Global.MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS,
4643                 DEFAULT_MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS);
4644         }
4645 
getElapsedTimeSinceRecoveryMs()4646         private long getElapsedTimeSinceRecoveryMs() {
4647             return (SystemClock.elapsedRealtime() - mTimeLastRecoveryStartMs);
4648         }
4649 
4650         @RecoveryAction
getRecoveryAction()4651         private int getRecoveryAction() {
4652             @RecoveryAction int action = Settings.System.getInt(mResolver,
4653                     "radio.data.stall.recovery.action", RECOVERY_ACTION_GET_DATA_CALL_LIST);
4654             if (VDBG_STALL) log("getRecoveryAction: " + action);
4655             return action;
4656         }
4657 
putRecoveryAction(@ecoveryAction int action)4658         private void putRecoveryAction(@RecoveryAction int action) {
4659             Settings.System.putInt(mResolver, "radio.data.stall.recovery.action", action);
4660             if (VDBG_STALL) log("putRecoveryAction: " + action);
4661         }
4662 
broadcastDataStallDetected(@ecoveryAction int recoveryAction)4663         private void broadcastDataStallDetected(@RecoveryAction int recoveryAction) {
4664             Intent intent = new Intent(TelephonyManager.ACTION_DATA_STALL_DETECTED);
4665             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
4666             intent.putExtra(TelephonyManager.EXTRA_RECOVERY_ACTION, recoveryAction);
4667             mPhone.getContext().sendBroadcast(intent, READ_PRIVILEGED_PHONE_STATE);
4668         }
4669 
isRecoveryAlreadyStarted()4670         private boolean isRecoveryAlreadyStarted() {
4671             return getRecoveryAction() != RECOVERY_ACTION_GET_DATA_CALL_LIST;
4672         }
4673 
checkRecovery()4674         private boolean checkRecovery() {
4675             // To avoid back to back recovery wait for a grace period
4676             if (getElapsedTimeSinceRecoveryMs() < getMinDurationBetweenRecovery()) {
4677                 if (VDBG_STALL) log("skip back to back data stall recovery");
4678                 return false;
4679             }
4680 
4681             // Skip recovery if it can cause a call to drop
4682             if (mInVoiceCall && getRecoveryAction() > RECOVERY_ACTION_CLEANUP) {
4683                 if (VDBG_STALL) log("skip data stall recovery as there is an active call");
4684                 return false;
4685             }
4686 
4687             // Allow recovery if data is expected to work
4688             return mAttached.get() && isDataAllowed(null);
4689         }
4690 
triggerRecovery()4691         private void triggerRecovery() {
4692             // Updating the recovery start time early to avoid race when
4693             // the message is being processed in the Queue
4694             mTimeLastRecoveryStartMs = SystemClock.elapsedRealtime();
4695             sendMessage(obtainMessage(DctConstants.EVENT_DO_RECOVERY));
4696         }
4697 
doRecovery()4698         public void doRecovery() {
4699             if (isAnyDataConnected()) {
4700                 // Go through a series of recovery steps, each action transitions to the next action
4701                 @RecoveryAction final int recoveryAction = getRecoveryAction();
4702                 final int signalStrength = mPhone.getSignalStrength().getLevel();
4703                 TelephonyMetrics.getInstance().writeSignalStrengthEvent(
4704                         mPhone.getPhoneId(), signalStrength);
4705                 TelephonyMetrics.getInstance().writeDataStallEvent(
4706                         mPhone.getPhoneId(), recoveryAction);
4707                 broadcastDataStallDetected(recoveryAction);
4708 
4709                 switch (recoveryAction) {
4710                     case RECOVERY_ACTION_GET_DATA_CALL_LIST:
4711                         EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_GET_DATA_CALL_LIST,
4712                             mSentSinceLastRecv);
4713                         if (DBG) log("doRecovery() get data call list");
4714                         mDataServiceManager.requestDataCallList(obtainMessage());
4715                         putRecoveryAction(RECOVERY_ACTION_CLEANUP);
4716                         break;
4717                     case RECOVERY_ACTION_CLEANUP:
4718                         EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_CLEANUP,
4719                             mSentSinceLastRecv);
4720                         if (DBG) log("doRecovery() cleanup all connections");
4721                         cleanUpConnection(mApnContexts.get(ApnSetting.getApnTypeString(
4722                                 ApnSetting.TYPE_DEFAULT)));
4723                         putRecoveryAction(RECOVERY_ACTION_REREGISTER);
4724                         break;
4725                     case RECOVERY_ACTION_REREGISTER:
4726                         EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_REREGISTER,
4727                             mSentSinceLastRecv);
4728                         if (DBG) log("doRecovery() re-register");
4729                         mPhone.getServiceStateTracker().reRegisterNetwork(null);
4730                         putRecoveryAction(RECOVERY_ACTION_RADIO_RESTART);
4731                         break;
4732                     case RECOVERY_ACTION_RADIO_RESTART:
4733                         EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_RADIO_RESTART,
4734                             mSentSinceLastRecv);
4735                         if (DBG) log("restarting radio");
4736                         restartRadio();
4737                         reset();
4738                         break;
4739                     default:
4740                         throw new RuntimeException("doRecovery: Invalid recoveryAction="
4741                             + recoveryAction);
4742                 }
4743                 mSentSinceLastRecv = 0;
4744             }
4745         }
4746 
processNetworkStatusChanged(boolean isValid)4747         public void processNetworkStatusChanged(boolean isValid) {
4748             if (isValid) {
4749                 mIsValidNetwork = true;
4750                 reset();
4751             } else {
4752                 if (mIsValidNetwork || isRecoveryAlreadyStarted()) {
4753                     mIsValidNetwork = false;
4754                     // Check and trigger a recovery if network switched from good
4755                     // to bad or recovery is already started before.
4756                     if (checkRecovery()) {
4757                         if (DBG) log("trigger data stall recovery");
4758                         triggerRecovery();
4759                     }
4760                 }
4761             }
4762         }
4763 
isRecoveryOnBadNetworkEnabled()4764         public boolean isRecoveryOnBadNetworkEnabled() {
4765             return Settings.Global.getInt(mResolver,
4766                     Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 1) == 1;
4767         }
4768 
isNoRxDataStallDetectionEnabled()4769         public boolean isNoRxDataStallDetectionEnabled() {
4770             return mDataStallNoRxEnabled && !isRecoveryOnBadNetworkEnabled();
4771         }
4772     }
4773 
updateDataStallInfo()4774     private void updateDataStallInfo() {
4775         long sent, received;
4776 
4777         TxRxSum preTxRxSum = new TxRxSum(mDataStallTxRxSum);
4778         mDataStallTxRxSum.updateTotalTxRxSum();
4779 
4780         if (VDBG_STALL) {
4781             log("updateDataStallInfo: mDataStallTxRxSum=" + mDataStallTxRxSum +
4782                     " preTxRxSum=" + preTxRxSum);
4783         }
4784 
4785         sent = mDataStallTxRxSum.txPkts - preTxRxSum.txPkts;
4786         received = mDataStallTxRxSum.rxPkts - preTxRxSum.rxPkts;
4787 
4788         if (RADIO_TESTS) {
4789             if (SystemProperties.getBoolean("radio.test.data.stall", false)) {
4790                 log("updateDataStallInfo: radio.test.data.stall true received = 0;");
4791                 received = 0;
4792             }
4793         }
4794         if ( sent > 0 && received > 0 ) {
4795             if (VDBG_STALL) log("updateDataStallInfo: IN/OUT");
4796             mSentSinceLastRecv = 0;
4797             mDsRecoveryHandler.reset();
4798         } else if (sent > 0 && received == 0) {
4799             if (isPhoneStateIdle()) {
4800                 mSentSinceLastRecv += sent;
4801             } else {
4802                 mSentSinceLastRecv = 0;
4803             }
4804             if (DBG) {
4805                 log("updateDataStallInfo: OUT sent=" + sent +
4806                         " mSentSinceLastRecv=" + mSentSinceLastRecv);
4807             }
4808         } else if (sent == 0 && received > 0) {
4809             if (VDBG_STALL) log("updateDataStallInfo: IN");
4810             mSentSinceLastRecv = 0;
4811             mDsRecoveryHandler.reset();
4812         } else {
4813             if (VDBG_STALL) log("updateDataStallInfo: NONE");
4814         }
4815     }
4816 
isPhoneStateIdle()4817     private boolean isPhoneStateIdle() {
4818         for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
4819             Phone phone = PhoneFactory.getPhone(i);
4820             if (phone != null && phone.getState() != PhoneConstants.State.IDLE) {
4821                 log("isPhoneStateIdle false: Voice call active on phone " + i);
4822                 return false;
4823             }
4824         }
4825         return true;
4826     }
4827 
onDataStallAlarm(int tag)4828     private void onDataStallAlarm(int tag) {
4829         if (mDataStallAlarmTag != tag) {
4830             if (DBG) {
4831                 log("onDataStallAlarm: ignore, tag=" + tag + " expecting " + mDataStallAlarmTag);
4832             }
4833             return;
4834         }
4835 
4836         if (DBG) log("Data stall alarm");
4837         updateDataStallInfo();
4838 
4839         int hangWatchdogTrigger = Settings.Global.getInt(mResolver,
4840                 Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
4841                 NUMBER_SENT_PACKETS_OF_HANG);
4842 
4843         boolean suspectedStall = DATA_STALL_NOT_SUSPECTED;
4844         if (mSentSinceLastRecv >= hangWatchdogTrigger) {
4845             if (DBG) {
4846                 log("onDataStallAlarm: tag=" + tag + " do recovery action="
4847                         + mDsRecoveryHandler.getRecoveryAction());
4848             }
4849             suspectedStall = DATA_STALL_SUSPECTED;
4850             sendMessage(obtainMessage(DctConstants.EVENT_DO_RECOVERY));
4851         } else {
4852             if (VDBG_STALL) {
4853                 log("onDataStallAlarm: tag=" + tag + " Sent " + String.valueOf(mSentSinceLastRecv) +
4854                     " pkts since last received, < watchdogTrigger=" + hangWatchdogTrigger);
4855             }
4856         }
4857         startDataStallAlarm(suspectedStall);
4858     }
4859 
startDataStallAlarm(boolean suspectedStall)4860     protected void startDataStallAlarm(boolean suspectedStall) {
4861         int delayInMs;
4862 
4863         if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled() && isAnyDataConnected()) {
4864             // If screen is on or data stall is currently suspected, set the alarm
4865             // with an aggressive timeout.
4866             if (mIsScreenOn || suspectedStall || mDsRecoveryHandler.isAggressiveRecovery()) {
4867                 delayInMs = Settings.Global.getInt(mResolver,
4868                         Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
4869                         DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT);
4870             } else {
4871                 delayInMs = Settings.Global.getInt(mResolver,
4872                         Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
4873                         DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT);
4874             }
4875 
4876             mDataStallAlarmTag += 1;
4877             if (VDBG_STALL) {
4878                 log("startDataStallAlarm: tag=" + mDataStallAlarmTag +
4879                         " delay=" + (delayInMs / 1000) + "s");
4880             }
4881             Intent intent = new Intent(INTENT_DATA_STALL_ALARM);
4882             intent.putExtra(INTENT_DATA_STALL_ALARM_EXTRA_TAG, mDataStallAlarmTag);
4883             intent.putExtra(INTENT_DATA_STALL_ALARM_EXTRA_TRANSPORT_TYPE, mTransportType);
4884             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
4885             mDataStallAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
4886                     PendingIntent.FLAG_UPDATE_CURRENT);
4887             mAlarmManager.set(AlarmManager.ELAPSED_REALTIME,
4888                     SystemClock.elapsedRealtime() + delayInMs, mDataStallAlarmIntent);
4889         } else {
4890             if (VDBG_STALL) {
4891                 log("startDataStallAlarm: NOT started, no connection tag=" + mDataStallAlarmTag);
4892             }
4893         }
4894     }
4895 
stopDataStallAlarm()4896     private void stopDataStallAlarm() {
4897         if (VDBG_STALL) {
4898             log("stopDataStallAlarm: current tag=" + mDataStallAlarmTag +
4899                     " mDataStallAlarmIntent=" + mDataStallAlarmIntent);
4900         }
4901         mDataStallAlarmTag += 1;
4902         if (mDataStallAlarmIntent != null) {
4903             mAlarmManager.cancel(mDataStallAlarmIntent);
4904             mDataStallAlarmIntent = null;
4905         }
4906     }
4907 
restartDataStallAlarm()4908     private void restartDataStallAlarm() {
4909         if (!isAnyDataConnected()) return;
4910         // To be called on screen status change.
4911         // Do not cancel the alarm if it is set with aggressive timeout.
4912         if (mDsRecoveryHandler.isAggressiveRecovery()) {
4913             if (DBG) log("restartDataStallAlarm: action is pending. not resetting the alarm.");
4914             return;
4915         }
4916         if (VDBG_STALL) log("restartDataStallAlarm: stop then start.");
4917         stopDataStallAlarm();
4918         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
4919     }
4920 
4921     /**
4922      * Provisioning APN
4923      */
onActionIntentProvisioningApnAlarm(Intent intent)4924     private void onActionIntentProvisioningApnAlarm(Intent intent) {
4925         if (DBG) log("onActionIntentProvisioningApnAlarm: action=" + intent.getAction());
4926         Message msg = obtainMessage(DctConstants.EVENT_PROVISIONING_APN_ALARM,
4927                 intent.getAction());
4928         msg.arg1 = intent.getIntExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, 0);
4929         sendMessage(msg);
4930     }
4931 
startProvisioningApnAlarm()4932     private void startProvisioningApnAlarm() {
4933         int delayInMs = Settings.Global.getInt(mResolver,
4934                                 Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS,
4935                                 PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT);
4936         if (TelephonyUtils.IS_DEBUGGABLE) {
4937             // Allow debug code to use a system property to provide another value
4938             String delayInMsStrg = Integer.toString(delayInMs);
4939             delayInMsStrg = System.getProperty(DEBUG_PROV_APN_ALARM, delayInMsStrg);
4940             try {
4941                 delayInMs = Integer.parseInt(delayInMsStrg);
4942             } catch (NumberFormatException e) {
4943                 loge("startProvisioningApnAlarm: e=" + e);
4944             }
4945         }
4946         mProvisioningApnAlarmTag += 1;
4947         if (DBG) {
4948             log("startProvisioningApnAlarm: tag=" + mProvisioningApnAlarmTag +
4949                     " delay=" + (delayInMs / 1000) + "s");
4950         }
4951         Intent intent = new Intent(INTENT_PROVISIONING_APN_ALARM);
4952         intent.putExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, mProvisioningApnAlarmTag);
4953         mProvisioningApnAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
4954                 PendingIntent.FLAG_UPDATE_CURRENT);
4955         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
4956                 SystemClock.elapsedRealtime() + delayInMs, mProvisioningApnAlarmIntent);
4957     }
4958 
stopProvisioningApnAlarm()4959     private void stopProvisioningApnAlarm() {
4960         if (DBG) {
4961             log("stopProvisioningApnAlarm: current tag=" + mProvisioningApnAlarmTag +
4962                     " mProvsioningApnAlarmIntent=" + mProvisioningApnAlarmIntent);
4963         }
4964         mProvisioningApnAlarmTag += 1;
4965         if (mProvisioningApnAlarmIntent != null) {
4966             mAlarmManager.cancel(mProvisioningApnAlarmIntent);
4967             mProvisioningApnAlarmIntent = null;
4968         }
4969     }
4970 
4971     /**
4972      * 5G connection reevaluation alarm
4973      */
startWatchdogAlarm()4974     private void startWatchdogAlarm() {
4975         sendMessageDelayed(obtainMessage(DctConstants.EVENT_NR_TIMER_WATCHDOG), mWatchdogTimeMs);
4976         mWatchdog = true;
4977     }
4978 
stopWatchdogAlarm()4979     private void stopWatchdogAlarm() {
4980         removeMessages(DctConstants.EVENT_NR_TIMER_WATCHDOG);
4981         mWatchdog = false;
4982     }
4983 
createDataProfile(ApnSetting apn, boolean isPreferred)4984     private static DataProfile createDataProfile(ApnSetting apn, boolean isPreferred) {
4985         return createDataProfile(apn, apn.getProfileId(), isPreferred);
4986     }
4987 
4988     @VisibleForTesting
createDataProfile(ApnSetting apn, int profileId, boolean isPreferred)4989     public static DataProfile createDataProfile(ApnSetting apn, int profileId,
4990                                                 boolean isPreferred) {
4991         int profileType;
4992 
4993         int networkTypeBitmask = apn.getNetworkTypeBitmask();
4994 
4995         if (networkTypeBitmask == 0) {
4996             profileType = DataProfile.TYPE_COMMON;
4997         } else if (ServiceState.bearerBitmapHasCdma(networkTypeBitmask)) {
4998             profileType = DataProfile.TYPE_3GPP2;
4999         } else {
5000             profileType = DataProfile.TYPE_3GPP;
5001         }
5002 
5003         return new DataProfile.Builder()
5004                 .setProfileId(profileId)
5005                 .setApn(apn.getApnName())
5006                 .setProtocolType(apn.getProtocol())
5007                 .setAuthType(apn.getAuthType())
5008                 .setUserName(apn.getUser() == null ? "" : apn.getUser())
5009                 .setPassword(apn.getPassword() == null ? "" : apn.getPassword())
5010                 .setType(profileType)
5011                 .setMaxConnectionsTime(apn.getMaxConnsTime())
5012                 .setMaxConnections(apn.getMaxConns())
5013                 .setWaitTime(apn.getWaitTime())
5014                 .enable(apn.isEnabled())
5015                 .setSupportedApnTypesBitmask(apn.getApnTypeBitmask())
5016                 .setRoamingProtocolType(apn.getRoamingProtocol())
5017                 .setBearerBitmask(networkTypeBitmask)
5018                 .setMtu(apn.getMtu())
5019                 .setPersistent(apn.isPersistent())
5020                 .setPreferred(isPreferred)
5021                 .build();
5022     }
5023 
onDataServiceBindingChanged(boolean bound)5024     private void onDataServiceBindingChanged(boolean bound) {
5025         if (bound) {
5026             if (mDcc == null) {
5027                 mDcc = DcController.makeDcc(mPhone, this, mDataServiceManager,
5028                         new Handler(mHandlerThread.getLooper()), mLogTagSuffix);
5029             }
5030             mDcc.start();
5031         } else {
5032             if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
5033                 boolean connPersistenceOnRestart = mPhone.getContext().getResources()
5034                    .getBoolean(com.android
5035                        .internal.R.bool.config_wlan_data_service_conn_persistence_on_restart);
5036                 if (!connPersistenceOnRestart) {
5037                     cleanUpAllConnectionsInternal(false, Phone.REASON_IWLAN_DATA_SERVICE_DIED);
5038                 }
5039             }
5040             mDcc.dispose();
5041             // dispose sets the associated Handler object (StateMachine#mSmHandler) to null, so mDcc
5042             // needs to be created again (simply calling start() on it after dispose will not work)
5043             mDcc = null;
5044         }
5045         mDataServiceBound = bound;
5046     }
5047 
requestTypeToString(@equestNetworkType int type)5048     public static String requestTypeToString(@RequestNetworkType int type) {
5049         switch (type) {
5050             case REQUEST_TYPE_NORMAL: return "NORMAL";
5051             case REQUEST_TYPE_HANDOVER: return "HANDOVER";
5052         }
5053         return "UNKNOWN";
5054     }
5055 
releaseTypeToString(@eleaseNetworkType int type)5056     public static String releaseTypeToString(@ReleaseNetworkType int type) {
5057         switch (type) {
5058             case RELEASE_TYPE_NORMAL: return "NORMAL";
5059             case RELEASE_TYPE_DETACH: return "DETACH";
5060             case RELEASE_TYPE_HANDOVER: return "HANDOVER";
5061         }
5062         return "UNKNOWN";
5063     }
5064 
5065     @RilRadioTechnology
getDataRat()5066     protected int getDataRat() {
5067         ServiceState ss = mPhone.getServiceState();
5068         NetworkRegistrationInfo nrs = ss.getNetworkRegistrationInfo(
5069                 NetworkRegistrationInfo.DOMAIN_PS, mTransportType);
5070         if (nrs != null) {
5071             return ServiceState.networkTypeToRilRadioTechnology(nrs.getAccessNetworkTechnology());
5072         }
5073         return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
5074     }
5075 
5076     @RilRadioTechnology
getVoiceRat()5077     private int getVoiceRat() {
5078         ServiceState ss = mPhone.getServiceState();
5079         NetworkRegistrationInfo nrs = ss.getNetworkRegistrationInfo(
5080                 NetworkRegistrationInfo.DOMAIN_CS, mTransportType);
5081         if (nrs != null) {
5082             return ServiceState.networkTypeToRilRadioTechnology(nrs.getAccessNetworkTechnology());
5083         }
5084         return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
5085     }
5086 
read5GConfiguration()5087     private void read5GConfiguration() {
5088         if (DBG) log("read5GConfiguration");
5089         String[] bandwidths = CarrierConfigManager.getDefaultConfig().getStringArray(
5090                 CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY);
5091         boolean useLte = false;
5092         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
5093                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
5094         if (configManager != null) {
5095             PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
5096             if (b != null) {
5097                 if (b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY) != null) {
5098                     bandwidths = b.getStringArray(CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY);
5099                 }
5100                 useLte = b.getBoolean(CarrierConfigManager
5101                         .KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL);
5102                 mWatchdogTimeMs = b.getLong(CarrierConfigManager.KEY_5G_WATCHDOG_TIME_MS_LONG);
5103                 mNrNsaAllUnmetered = b.getBoolean(CarrierConfigManager.KEY_UNMETERED_NR_NSA_BOOL);
5104                 mNrNsaMmwaveUnmetered = b.getBoolean(
5105                         CarrierConfigManager.KEY_UNMETERED_NR_NSA_MMWAVE_BOOL);
5106                 mNrNsaSub6Unmetered = b.getBoolean(
5107                         CarrierConfigManager.KEY_UNMETERED_NR_NSA_SUB6_BOOL);
5108                 mNrSaAllUnmetered = b.getBoolean(CarrierConfigManager.KEY_UNMETERED_NR_SA_BOOL);
5109                 mNrSaMmwaveUnmetered = b.getBoolean(
5110                         CarrierConfigManager.KEY_UNMETERED_NR_SA_MMWAVE_BOOL);
5111                 mNrSaSub6Unmetered = b.getBoolean(
5112                         CarrierConfigManager.KEY_UNMETERED_NR_SA_SUB6_BOOL);
5113                 mRoamingUnmetered = b.getBoolean(
5114                         CarrierConfigManager.KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL);
5115             }
5116         }
5117         updateLinkBandwidths(bandwidths, useLte);
5118     }
5119 
5120     /**
5121      * Register for physical link state (i.e. RRC state) changed event.
5122      *
5123      * @param h The handler
5124      * @param what The event
5125      */
registerForPhysicalLinkStateChanged(Handler h, int what)5126     public void registerForPhysicalLinkStateChanged(Handler h, int what) {
5127         mDcc.registerForPhysicalLinkStateChanged(h, what);
5128     }
5129 
5130     /**
5131      * Unregister from physical link state (i.e. RRC state) changed event.
5132      *
5133      * @param h The previously registered handler
5134      */
unregisterForPhysicalLinkStateChanged(Handler h)5135     public void unregisterForPhysicalLinkStateChanged(Handler h) {
5136         mDcc.unregisterForPhysicalLinkStateChanged(h);
5137     }
5138 }
5139