• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.data;
18 
19 import android.annotation.CallbackExecutor;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.ContentResolver;
23 import android.content.ContentValues;
24 import android.database.ContentObserver;
25 import android.database.Cursor;
26 import android.net.NetworkCapabilities;
27 import android.net.NetworkRequest;
28 import android.net.Uri;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.Message;
32 import android.provider.Telephony;
33 import android.telephony.Annotation;
34 import android.telephony.Annotation.NetworkType;
35 import android.telephony.AnomalyReporter;
36 import android.telephony.CarrierConfigManager;
37 import android.telephony.SubscriptionManager;
38 import android.telephony.TelephonyManager;
39 import android.telephony.data.ApnSetting;
40 import android.telephony.data.DataProfile;
41 import android.telephony.data.TrafficDescriptor;
42 import android.text.TextUtils;
43 import android.util.ArraySet;
44 import android.util.IndentingPrintWriter;
45 import android.util.LocalLog;
46 
47 import com.android.internal.telephony.Phone;
48 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
49 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
50 import com.android.telephony.Rlog;
51 
52 import java.io.FileDescriptor;
53 import java.io.PrintWriter;
54 import java.util.ArrayList;
55 import java.util.Comparator;
56 import java.util.List;
57 import java.util.Objects;
58 import java.util.Set;
59 import java.util.UUID;
60 import java.util.concurrent.Executor;
61 import java.util.stream.Collectors;
62 
63 /**
64  * DataProfileManager manages the all {@link DataProfile}s for the current
65  * subscription.
66  */
67 public class DataProfileManager extends Handler {
68     private static final boolean VDBG = true;
69 
70     /** Event for APN database changed. */
71     private static final int EVENT_APN_DATABASE_CHANGED = 2;
72 
73     /** Event for SIM refresh. */
74     private static final int EVENT_SIM_REFRESH = 3;
75 
76     private final Phone mPhone;
77     private final String mLogTag;
78     private final LocalLog mLocalLog = new LocalLog(128);
79 
80     /** Data network controller. */
81     private final @NonNull DataNetworkController mDataNetworkController;
82 
83     /** Data config manager. */
84     private final @NonNull DataConfigManager mDataConfigManager;
85 
86     /** Cellular data service. */
87     private final @NonNull DataServiceManager mWwanDataServiceManager;
88 
89     /**
90      * All data profiles for the current carrier. Note only data profiles loaded from the APN
91      * database will be stored here. The on-demand data profiles (generated dynamically, for
92      * example, enterprise data profiles with differentiator) are not stored here.
93      */
94     private final @NonNull List<DataProfile> mAllDataProfiles = new ArrayList<>();
95 
96     /** The data profile used for initial attach. */
97     private @Nullable DataProfile mInitialAttachDataProfile = null;
98 
99     /** The preferred data profile used for internet. */
100     private @Nullable DataProfile mPreferredDataProfile = null;
101 
102     /** The last data profile that's successful for internet connection. */
103     private @Nullable DataProfile mLastInternetDataProfile = null;
104 
105     /** Preferred data profile set id. */
106     private int mPreferredDataProfileSetId = Telephony.Carriers.NO_APN_SET_ID;
107 
108     /** Data profile manager callbacks. */
109     private final @NonNull Set<DataProfileManagerCallback> mDataProfileManagerCallbacks =
110             new ArraySet<>();
111 
112     /**
113      * Data profile manager callback. This should be only used by {@link DataNetworkController}.
114      */
115     public abstract static class DataProfileManagerCallback extends DataCallback {
116         /**
117          * Constructor
118          *
119          * @param executor The executor of the callback.
120          */
DataProfileManagerCallback(@onNull @allbackExecutor Executor executor)121         public DataProfileManagerCallback(@NonNull @CallbackExecutor Executor executor) {
122             super(executor);
123         }
124 
125         /**
126          * Called when data profiles changed.
127          */
onDataProfilesChanged()128         public abstract void onDataProfilesChanged();
129     }
130 
131     /**
132      * Constructor
133      *
134      * @param phone The phone instance.
135      * @param dataNetworkController Data network controller.
136      * @param dataServiceManager WWAN data service manager.
137      * @param looper The looper to be used by the handler. Currently the handler thread is the
138      * phone process's main thread.
139      * @param callback Data profile manager callback.
140      */
DataProfileManager(@onNull Phone phone, @NonNull DataNetworkController dataNetworkController, @NonNull DataServiceManager dataServiceManager, @NonNull Looper looper, @NonNull DataProfileManagerCallback callback)141     public DataProfileManager(@NonNull Phone phone,
142             @NonNull DataNetworkController dataNetworkController,
143             @NonNull DataServiceManager dataServiceManager, @NonNull Looper looper,
144             @NonNull DataProfileManagerCallback callback) {
145         super(looper);
146         mPhone = phone;
147         mLogTag = "DPM-" + mPhone.getPhoneId();
148         mDataNetworkController = dataNetworkController;
149         mWwanDataServiceManager = dataServiceManager;
150         mDataConfigManager = dataNetworkController.getDataConfigManager();
151         mDataProfileManagerCallbacks.add(callback);
152         registerAllEvents();
153     }
154 
155     /**
156      * Register for all events that data network controller is interested.
157      */
registerAllEvents()158     private void registerAllEvents() {
159         mDataNetworkController.registerDataNetworkControllerCallback(
160                 new DataNetworkControllerCallback(this::post) {
161                     @Override
162                     public void onInternetDataNetworkConnected(
163                             @NonNull List<DataNetwork> internetNetworks) {
164                         DataProfileManager.this.onInternetDataNetworkConnected(internetNetworks);
165                     }
166                 });
167         mDataConfigManager.registerCallback(new DataConfigManagerCallback(this::post) {
168             @Override
169             public void onCarrierConfigChanged() {
170                 DataProfileManager.this.onCarrierConfigUpdated();
171             }
172         });
173         mPhone.getContext().getContentResolver().registerContentObserver(
174                 Telephony.Carriers.CONTENT_URI, true, new ContentObserver(this) {
175                     @Override
176                     public void onChange(boolean selfChange) {
177                         super.onChange(selfChange);
178                         sendEmptyMessage(EVENT_APN_DATABASE_CHANGED);
179                     }
180                 });
181         mPhone.mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);
182     }
183 
184     @Override
handleMessage(Message msg)185     public void handleMessage(Message msg) {
186         switch (msg.what) {
187             case EVENT_SIM_REFRESH:
188                 log("Update data profiles due to SIM refresh.");
189                 updateDataProfiles(!mDataConfigManager.allowClearInitialAttachDataProfile()
190                         /*force update IA*/);
191                 break;
192             case EVENT_APN_DATABASE_CHANGED:
193                 log("Update data profiles due to APN db updated.");
194                 updateDataProfiles(false/*force update IA*/);
195                 break;
196             default:
197                 loge("Unexpected event " + msg);
198                 break;
199         }
200     }
201 
202     /**
203      * Called when carrier config was updated.
204      */
onCarrierConfigUpdated()205     private void onCarrierConfigUpdated() {
206         log("Update data profiles due to carrier config updated.");
207         updateDataProfiles(!mDataConfigManager.allowClearInitialAttachDataProfile()
208                 /*force update IA*/);
209     }
210 
211     /**
212      * Check if there are any Enterprise APN configured by DPC and return a data profile
213      * with the same.
214      * @return data profile with enterprise ApnSetting if available, else null
215      */
getEnterpriseDataProfile()216     @Nullable private DataProfile getEnterpriseDataProfile() {
217         Cursor cursor = mPhone.getContext().getContentResolver().query(
218                 Telephony.Carriers.DPC_URI, null, null, null, null);
219         if (cursor == null) {
220             loge("Cannot access APN database through telephony provider.");
221             return null;
222         }
223 
224         DataProfile dataProfile = null;
225         while (cursor.moveToNext()) {
226             ApnSetting apn = ApnSetting.makeApnSetting(cursor);
227             if (apn != null) {
228                 dataProfile = new DataProfile.Builder()
229                         .setApnSetting(apn)
230                         .setTrafficDescriptor(new TrafficDescriptor(apn.getApnName(), null))
231                         .setPreferred(false)
232                         .build();
233                 if (dataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)) {
234                     break;
235                 }
236             }
237         }
238         cursor.close();
239         return dataProfile;
240     }
241     /**
242      * Update all data profiles, including preferred data profile, and initial attach data profile.
243      * Also send those profiles down to the modem if needed.
244      *
245      * @param forceUpdateIa If {@code true}, we should always send initial attach data profile again
246      *                     to modem.
247      */
updateDataProfiles(boolean forceUpdateIa)248     private void updateDataProfiles(boolean forceUpdateIa) {
249         List<DataProfile> profiles = new ArrayList<>();
250         if (mDataConfigManager.isConfigCarrierSpecific()) {
251             Cursor cursor = mPhone.getContext().getContentResolver().query(
252                     Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, "filtered/subId/"
253                             + mPhone.getSubId()), null, null, null, Telephony.Carriers._ID);
254             if (cursor == null) {
255                 loge("Cannot access APN database through telephony provider.");
256                 return;
257             }
258             boolean isInternetSupported = false;
259             while (cursor.moveToNext()) {
260                 ApnSetting apn = ApnSetting.makeApnSetting(cursor);
261                 if (apn != null) {
262                     DataProfile dataProfile = new DataProfile.Builder()
263                             .setApnSetting(apn)
264                             .setTrafficDescriptor(new TrafficDescriptor(apn.getApnName(), null))
265                             .setPreferred(false)
266                             .build();
267                     profiles.add(dataProfile);
268                     log("Added " + dataProfile);
269 
270                     isInternetSupported |= apn.canHandleType(ApnSetting.TYPE_DEFAULT);
271                     if (mDataConfigManager.isApnConfigAnomalyReportEnabled()) {
272                         checkApnSetting(apn);
273                     }
274                 }
275             }
276             cursor.close();
277 
278             if (!isInternetSupported
279                     && !profiles.isEmpty() // APN database has been read successfully
280                     && mDataConfigManager.isApnConfigAnomalyReportEnabled()) {
281                 reportAnomaly("Carrier doesn't support internet.",
282                         "9af73e18-b523-4dc5-adab-363eb6613305");
283             }
284         }
285 
286         DataProfile dataProfile;
287 
288         if (!profiles.isEmpty()) { // APN database has been read successfully after SIM loaded
289             // Check if any of the profile already supports IMS, if not, add the default one.
290             dataProfile = profiles.stream()
291                     .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS))
292                     .findFirst()
293                     .orElse(null);
294             if (dataProfile == null) {
295                 profiles.add(new DataProfile.Builder()
296                         .setApnSetting(buildDefaultApnSetting("DEFAULT IMS", "ims",
297                                 ApnSetting.TYPE_IMS))
298                         .setTrafficDescriptor(new TrafficDescriptor("ims", null))
299                         .build());
300                 log("Added default IMS data profile.");
301             }
302         }
303 
304         // Check if any of the profile already supports ENTERPRISE, if not, check if DPC has
305         // configured one and retrieve the same.
306         dataProfile = profiles.stream()
307                 .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE))
308                 .findFirst()
309                 .orElse(null);
310         if (dataProfile == null) {
311             dataProfile = getEnterpriseDataProfile();
312             if (dataProfile != null) {
313                 profiles.add(dataProfile);
314                 log("Added enterprise profile " + dataProfile);
315             }
316         }
317 
318         // Check if any of the profile already supports EIMS, if not, add the default one.
319         dataProfile = profiles.stream()
320                 .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_EIMS))
321                 .findFirst()
322                 .orElse(null);
323         if (dataProfile == null) {
324             profiles.add(new DataProfile.Builder()
325                     .setApnSetting(buildDefaultApnSetting("DEFAULT EIMS", "sos",
326                             ApnSetting.TYPE_EMERGENCY))
327                     .setTrafficDescriptor(new TrafficDescriptor("sos", null))
328                     .build());
329             log("Added default EIMS data profile.");
330         }
331 
332         dedupeDataProfiles(profiles);
333 
334         if (mDataConfigManager.isApnConfigAnomalyReportEnabled()) {
335             checkDataProfiles(profiles);
336         }
337 
338         log("Found " + profiles.size() + " data profiles. profiles = " + profiles);
339 
340         boolean profilesChanged = false;
341         if (mAllDataProfiles.size() != profiles.size() || !mAllDataProfiles.containsAll(profiles)) {
342             log("Data profiles changed.");
343             mAllDataProfiles.clear();
344             mAllDataProfiles.addAll(profiles);
345             profilesChanged = true;
346         }
347 
348         // Reload the latest preferred data profile from either database or config.
349         profilesChanged |= updatePreferredDataProfile();
350 
351         int setId = getPreferredDataProfileSetId();
352         if (setId != mPreferredDataProfileSetId) {
353             logl("Changed preferred data profile set id to " + setId);
354             mPreferredDataProfileSetId = setId;
355             profilesChanged = true;
356         }
357 
358         updateDataProfilesAtModem();
359         updateInitialAttachDataProfileAtModem(forceUpdateIa);
360 
361         if (profilesChanged) {
362             mDataProfileManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
363                     callback::onDataProfilesChanged));
364         }
365     }
366 
367     /**
368      * @return The preferred data profile set id.
369      */
getPreferredDataProfileSetId()370     private int getPreferredDataProfileSetId() {
371         // Query the preferred APN set id. The set id is automatically set when we set by
372         // TelephonyProvider when setting preferred APN in setPreferredDataProfile().
373         Cursor cursor = mPhone.getContext().getContentResolver()
374                 .query(Uri.withAppendedPath(Telephony.Carriers.PREFERRED_APN_SET_URI,
375                         String.valueOf(mPhone.getSubId())),
376                         new String[] {Telephony.Carriers.APN_SET_ID}, null, null, null);
377         // Returns all APNs for the current carrier which have an apn_set_id
378         // equal to the preferred APN (if no preferred APN, or if the preferred APN has no set id,
379         // the query will return null)
380         if (cursor == null) {
381             log("getPreferredDataProfileSetId: cursor is null");
382             return Telephony.Carriers.NO_APN_SET_ID;
383         }
384 
385         int setId;
386         if (cursor.getCount() < 1) {
387             loge("getPreferredDataProfileSetId: no APNs found");
388             setId = Telephony.Carriers.NO_APN_SET_ID;
389         } else {
390             cursor.moveToFirst();
391             setId = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID));
392         }
393 
394         cursor.close();
395         return setId;
396     }
397 
398     /**
399      * Called when internet data is connected.
400      *
401      * @param internetNetworks The connected internet data networks.
402      */
onInternetDataNetworkConnected(@onNull List<DataNetwork> internetNetworks)403     private void onInternetDataNetworkConnected(@NonNull List<DataNetwork> internetNetworks) {
404         DataProfile defaultProfile = null;
405         if (internetNetworks.size() == 1) {
406             // Most of the cases there should be only one.
407             defaultProfile = internetNetworks.get(0).getDataProfile();
408         } else if (internetNetworks.size() > 1) {
409             // but in case there are multiple, find the default internet network, and choose the
410             // one which has longest life cycle.
411             logv("onInternetDataNetworkConnected: mPreferredDataProfile=" + mPreferredDataProfile
412                     + " internetNetworks=" + internetNetworks);
413             defaultProfile = internetNetworks.stream()
414                     .filter(network -> mPreferredDataProfile == null
415                             || canPreferredDataProfileSatisfy(
416                             network.getAttachedNetworkRequestList()))
417                     .map(DataNetwork::getDataProfile)
418                     .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
419                     .orElse(null);
420         }
421 
422         // Update a working internet data profile as a future candidate for preferred data profile
423         // after APNs are reset to default
424         mLastInternetDataProfile = defaultProfile;
425 
426         // If the live default internet network is not using the preferred data profile, since
427         // brought up a network means it passed sophisticated checks, update the preferred data
428         // profile so that this network won't be torn down in future network evaluations.
429         if (defaultProfile == null || defaultProfile.equals(mPreferredDataProfile)) return;
430         // Save the preferred data profile into database.
431         setPreferredDataProfile(defaultProfile);
432         updateDataProfiles(false/*force update IA*/);
433     }
434 
435     /**
436      * Get the preferred data profile for internet data.
437      *
438      * @return The preferred data profile.
439      */
getPreferredDataProfileFromDb()440     private @Nullable DataProfile getPreferredDataProfileFromDb() {
441         Cursor cursor = mPhone.getContext().getContentResolver().query(
442                 Uri.withAppendedPath(Telephony.Carriers.PREFERRED_APN_URI,
443                         String.valueOf(mPhone.getSubId())), null, null, null,
444                 Telephony.Carriers.DEFAULT_SORT_ORDER);
445         DataProfile dataProfile = null;
446         if (cursor != null) {
447             if (cursor.getCount() > 0) {
448                 cursor.moveToFirst();
449                 int apnId = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID));
450                 dataProfile = mAllDataProfiles.stream()
451                         .filter(dp -> dp.getApnSetting() != null
452                                 && dp.getApnSetting().getId() == apnId)
453                         .findFirst()
454                         .orElse(null);
455             }
456             cursor.close();
457         }
458         log("getPreferredDataProfileFromDb: " + dataProfile);
459         return dataProfile;
460     }
461 
462     /**
463      * @return The preferred data profile from carrier config.
464      */
getPreferredDataProfileFromConfig()465     private @Nullable DataProfile getPreferredDataProfileFromConfig() {
466         // Check if there is configured default preferred data profile.
467         String defaultPreferredApn = mDataConfigManager.getDefaultPreferredApn();
468         if (!TextUtils.isEmpty(defaultPreferredApn)) {
469             return mAllDataProfiles.stream()
470                     .filter(dp -> dp.getApnSetting() != null && defaultPreferredApn.equals(
471                                     dp.getApnSetting().getApnName()))
472                     .findFirst()
473                     .orElse(null);
474         }
475         return null;
476     }
477 
478     /**
479      * Save the preferred data profile into the database.
480      *
481      * @param dataProfile The preferred data profile used for internet data. {@code null} to clear
482      * the preferred data profile from database.
483      */
setPreferredDataProfile(@ullable DataProfile dataProfile)484     private void setPreferredDataProfile(@Nullable DataProfile dataProfile) {
485         logl("setPreferredDataProfile: " + dataProfile);
486 
487         String subId = Long.toString(mPhone.getSubId());
488         Uri uri = Uri.withAppendedPath(Telephony.Carriers.PREFERRED_APN_URI, subId);
489         ContentResolver resolver = mPhone.getContext().getContentResolver();
490         resolver.delete(uri, null, null);
491 
492         if (dataProfile != null && dataProfile.getApnSetting() != null) {
493             ContentValues values = new ContentValues();
494             // Fill only the id here. TelephonyProvider will pull the rest of key fields and write
495             // into the database.
496             values.put(Telephony.Carriers.APN_ID, dataProfile.getApnSetting().getId());
497             resolver.insert(uri, values);
498         }
499     }
500 
501     /**
502      * Reload the latest preferred data profile from either database or the config. This is to
503      * make sure the cached {@link #mPreferredDataProfile} is in-sync.
504      *
505      * @return {@code true} if preferred data profile changed.
506      */
updatePreferredDataProfile()507     private boolean updatePreferredDataProfile() {
508         DataProfile preferredDataProfile;
509         if (SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())) {
510             preferredDataProfile = getPreferredDataProfileFromDb();
511             if (preferredDataProfile == null) {
512                 preferredDataProfile = getPreferredDataProfileFromConfig();
513                 if (preferredDataProfile != null) {
514                     // Save the carrier specified preferred data profile into database
515                     setPreferredDataProfile(preferredDataProfile);
516                 } else {
517                     preferredDataProfile = mAllDataProfiles.stream()
518                             .filter(dp -> areDataProfilesSharingApn(dp, mLastInternetDataProfile))
519                             .findFirst()
520                             .orElse(null);
521                     if (preferredDataProfile != null) {
522                         log("updatePreferredDataProfile: preferredDB is empty and no carrier "
523                                 + "default configured, setting preferred to be prev internet DP.");
524                         setPreferredDataProfile(preferredDataProfile);
525                     }
526                 }
527             }
528         } else {
529             preferredDataProfile = null;
530         }
531 
532         for (DataProfile dataProfile : mAllDataProfiles) {
533             dataProfile.setPreferred(dataProfile.equals(preferredDataProfile));
534         }
535 
536         if (!Objects.equals(mPreferredDataProfile, preferredDataProfile)) {
537             mPreferredDataProfile = preferredDataProfile;
538 
539             logl("Changed preferred data profile to " + mPreferredDataProfile);
540             return true;
541         }
542         return false;
543     }
544 
545     /**
546      * Update the data profile used for initial attach.
547      *
548      * Note that starting from Android 13 only APNs that supports "IA" type will be used for
549      * initial attach. Please update APN configuration file if needed.
550      *
551      * Some carriers might explicitly require that using "user-added" APN for initial
552      * attach. In this case, exception can be configured through
553      * {@link CarrierConfigManager#KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY}.
554      *
555      * @param forceUpdateIa If {@code true}, we should always send initial attach data profile again
556      *                     to modem.
557      */
updateInitialAttachDataProfileAtModem(boolean forceUpdateIa)558     private void updateInitialAttachDataProfileAtModem(boolean forceUpdateIa) {
559         DataProfile initialAttachDataProfile = null;
560 
561         // Sort the data profiles so the preferred data profile is at the beginning.
562         List<DataProfile> allDataProfiles = mAllDataProfiles.stream()
563                 .sorted(Comparator.comparing((DataProfile dp) -> !dp.equals(mPreferredDataProfile)))
564                 .collect(Collectors.toList());
565         // Search in the order. "IA" type should be the first from getAllowedInitialAttachApnTypes.
566         for (int apnType : mDataConfigManager.getAllowedInitialAttachApnTypes()) {
567             initialAttachDataProfile = allDataProfiles.stream()
568                     .filter(dp -> dp.canSatisfy(DataUtils.apnTypeToNetworkCapability(apnType)))
569                     .findFirst()
570                     .orElse(null);
571             if (initialAttachDataProfile != null) break;
572         }
573 
574         if (forceUpdateIa || !Objects.equals(mInitialAttachDataProfile, initialAttachDataProfile)) {
575             mInitialAttachDataProfile = initialAttachDataProfile;
576             logl("Initial attach data profile updated as " + mInitialAttachDataProfile
577                     + " or forceUpdateIa= " + forceUpdateIa);
578             if (mInitialAttachDataProfile != null || mDataConfigManager
579                     .allowClearInitialAttachDataProfile()) {
580                 mWwanDataServiceManager.setInitialAttachApn(mInitialAttachDataProfile,
581                         mPhone.getServiceState().getDataRoamingFromRegistration(), null);
582             }
583         }
584     }
585 
586     /**
587      * Update the data profiles at modem.
588      */
updateDataProfilesAtModem()589     private void updateDataProfilesAtModem() {
590         log("updateDataProfilesAtModem: set " + mAllDataProfiles.size() + " data profiles.");
591         mWwanDataServiceManager.setDataProfile(mAllDataProfiles,
592                 mPhone.getServiceState().getDataRoamingFromRegistration(), null);
593     }
594 
595     /**
596      * Create default apn settings for the apn type like emergency, and ims
597      *
598      * @param entry Entry name
599      * @param apn APN name
600      * @param apnTypeBitmask APN type
601      * @return The APN setting
602      */
buildDefaultApnSetting(@onNull String entry, @NonNull String apn, @Annotation.ApnType int apnTypeBitmask)603     private @NonNull ApnSetting buildDefaultApnSetting(@NonNull String entry,
604             @NonNull String apn, @Annotation.ApnType int apnTypeBitmask) {
605         return new ApnSetting.Builder()
606                 .setEntryName(entry)
607                 .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
608                 .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
609                 .setApnName(apn)
610                 .setApnTypeBitmask(apnTypeBitmask)
611                 .setCarrierEnabled(true)
612                 .setApnSetId(Telephony.Carriers.MATCH_ALL_APN_SET_ID)
613                 .build();
614     }
615 
616     /**
617      * Get the data profile that can satisfy the network request.
618      *
619      * @param networkRequest The network request.
620      * @param networkType The current data network type.
621      * @param ignorePermanentFailure {@code true} to ignore {@link ApnSetting#getPermanentFailed()}.
622      * This should be set to true for condition-based retry/setup.
623      * @return The data profile. {@code null} if can't find any satisfiable data profile.
624      */
getDataProfileForNetworkRequest( @onNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType, boolean ignorePermanentFailure)625     public @Nullable DataProfile getDataProfileForNetworkRequest(
626             @NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType,
627             boolean ignorePermanentFailure) {
628         ApnSetting apnSetting = null;
629         if (networkRequest.hasAttribute(TelephonyNetworkRequest
630                 .CAPABILITY_ATTRIBUTE_APN_SETTING)) {
631             apnSetting = getApnSettingForNetworkRequest(networkRequest, networkType,
632                     ignorePermanentFailure);
633         }
634 
635         TrafficDescriptor.Builder trafficDescriptorBuilder = new TrafficDescriptor.Builder();
636         if (networkRequest.hasAttribute(TelephonyNetworkRequest
637                 .CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN)) {
638             if (apnSetting != null) {
639                 trafficDescriptorBuilder.setDataNetworkName(apnSetting.getApnName());
640             }
641         }
642 
643         if (networkRequest.hasAttribute(
644                 TelephonyNetworkRequest.CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)) {
645             TrafficDescriptor.OsAppId osAppId = networkRequest.getOsAppId();
646             if (osAppId != null) {
647                 trafficDescriptorBuilder.setOsAppId(osAppId.getBytes());
648             }
649         }
650 
651         TrafficDescriptor trafficDescriptor;
652         try {
653             trafficDescriptor = trafficDescriptorBuilder.build();
654         } catch (IllegalArgumentException e) {
655             // We reach here when both ApnSetting and trafficDescriptor are null.
656             log("Unable to find a data profile for " + networkRequest);
657             return null;
658         }
659 
660         // Instead of building the data profile from APN setting and traffic descriptor on-the-fly,
661         // find the existing one from mAllDataProfiles so the last-setup timestamp can be retained.
662         // Only create a new one when it can't be found.
663         for (DataProfile dataProfile : mAllDataProfiles) {
664             if (Objects.equals(apnSetting, dataProfile.getApnSetting())
665                     && trafficDescriptor.equals(dataProfile.getTrafficDescriptor())) {
666                 return dataProfile;
667             }
668         }
669 
670         // When reaching here, it means that we have a valid non-null traffic descriptor, but
671         // could not find it in mAllDataProfiles. This could happen on the traffic descriptor
672         // capable capabilities like ENTERPRISE.
673         DataProfile.Builder profileBuilder = new DataProfile.Builder();
674         if (apnSetting != null) {
675             profileBuilder.setApnSetting(apnSetting);
676         }
677 
678         // trafficDescriptor is always non-null when we reach here.
679         profileBuilder.setTrafficDescriptor(trafficDescriptor);
680 
681         DataProfile dataProfile = profileBuilder.build();
682         log("Created data profile " + dataProfile + " for " + networkRequest);
683         return dataProfile;
684     }
685 
686     /**
687      * Get the APN setting for the network request.
688      *
689      * @param networkRequest The network request.
690      * @param networkType The current data network type.
691      * @param ignorePermanentFailure {@code true} to ignore {@link ApnSetting#getPermanentFailed()}.
692      * This should be set to true for condition-based retry/setup.
693      * @return The APN setting. {@code null} if can't find any satisfiable data profile.
694      */
getApnSettingForNetworkRequest( @onNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType, boolean ignorePermanentFailure)695     private @Nullable ApnSetting getApnSettingForNetworkRequest(
696             @NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType,
697             boolean ignorePermanentFailure) {
698         if (!networkRequest.hasAttribute(
699                 TelephonyNetworkRequest.CAPABILITY_ATTRIBUTE_APN_SETTING)) {
700             loge("Network request does not have APN setting attribute.");
701             return null;
702         }
703 
704         // If the preferred data profile can be used, always use it if it can satisfy the network
705         // request with current network type (even though it's been marked as permanent failed.)
706         if (mPreferredDataProfile != null
707                 && networkRequest.canBeSatisfiedBy(mPreferredDataProfile)
708                 && mPreferredDataProfile.getApnSetting() != null
709                 && mPreferredDataProfile.getApnSetting().canSupportNetworkType(networkType)) {
710             if (ignorePermanentFailure || !mPreferredDataProfile.getApnSetting()
711                     .getPermanentFailed()) {
712                 return mPreferredDataProfile.getApnSetting();
713             }
714             log("The preferred data profile is permanently failed. Only condition based retry "
715                     + "can happen.");
716             return null;
717         }
718 
719         // Filter out the data profile that can't satisfy the request.
720         // Preferred data profile should be returned in the top of the list.
721         List<DataProfile> dataProfiles = mAllDataProfiles.stream()
722                 .filter(networkRequest::canBeSatisfiedBy)
723                 // The longest time hasn't used data profile will be in the front so all the data
724                 // profiles can be tried.
725                 .sorted(Comparator.comparing(DataProfile::getLastSetupTimestamp))
726                 .collect(Collectors.toList());
727         for (DataProfile dataProfile : dataProfiles) {
728             logv("Satisfied profile: " + dataProfile + ", last setup="
729                     + DataUtils.elapsedTimeToString(dataProfile.getLastSetupTimestamp()));
730         }
731         if (dataProfiles.size() == 0) {
732             log("Can't find any data profile that can satisfy " + networkRequest);
733             return null;
734         }
735 
736         // Check if the remaining data profiles can used in current data network type.
737         dataProfiles = dataProfiles.stream()
738                 .filter(dp -> dp.getApnSetting() != null
739                         && dp.getApnSetting().canSupportNetworkType(networkType))
740                 .collect(Collectors.toList());
741         if (dataProfiles.size() == 0) {
742             log("Can't find any data profile for network type "
743                     + TelephonyManager.getNetworkTypeName(networkType));
744             return null;
745         }
746 
747         // Check if preferred data profile set id matches.
748         dataProfiles = dataProfiles.stream()
749                 .filter(dp -> dp.getApnSetting() != null
750                         && (dp.getApnSetting().getApnSetId()
751                         == Telephony.Carriers.MATCH_ALL_APN_SET_ID
752                         || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId))
753                 .collect(Collectors.toList());
754         if (dataProfiles.size() == 0) {
755             log("Can't find any data profile has APN set id matched. mPreferredDataProfileSetId="
756                     + mPreferredDataProfileSetId);
757             return null;
758         }
759 
760         // Check if data profiles are permanently failed.
761         dataProfiles = dataProfiles.stream()
762                 .filter(dp -> ignorePermanentFailure || !dp.getApnSetting().getPermanentFailed())
763                 .collect(Collectors.toList());
764         if (dataProfiles.size() == 0) {
765             log("The suitable data profiles are all in permanent failed state.");
766             return null;
767         }
768 
769         return dataProfiles.get(0).getApnSetting();
770     }
771 
772     /**
773      * Check if the data profile is essentially the preferred data profile. The non-essential
774      * elements include e.g.APN Id.
775      *
776      * @param dataProfile The data profile to check.
777      * @return {@code true} if the data profile is essentially the preferred data profile.
778      */
isDataProfilePreferred(@onNull DataProfile dataProfile)779     public boolean isDataProfilePreferred(@NonNull DataProfile dataProfile) {
780         return areDataProfilesSharingApn(dataProfile, mPreferredDataProfile);
781     }
782 
783     /**
784      * @param networkRequests The required network requests
785      * @return {@code true} if we currently have a preferred data profile that's capable of
786      * satisfying the required network requests; {@code false} if we have no preferred, or the
787      * preferred cannot satisfy the required requests.
788      */
canPreferredDataProfileSatisfy( @onNull DataNetworkController.NetworkRequestList networkRequests)789     public boolean canPreferredDataProfileSatisfy(
790             @NonNull DataNetworkController.NetworkRequestList networkRequests) {
791         return mPreferredDataProfile != null && networkRequests.stream()
792                 .allMatch(request -> request.canBeSatisfiedBy(mPreferredDataProfile));
793     }
794 
795     /**
796      * Check if there is tethering data profile for certain network type.
797      *
798      * @param networkType The network type
799      * @return {@code true} if tethering data profile is found. {@code false} if no specific profile
800      * should used for tethering. In this case, tethering service will use internet network for
801      * tethering.
802      */
isTetheringDataProfileExisting(@etworkType int networkType)803     public boolean isTetheringDataProfileExisting(@NetworkType int networkType) {
804         if (mDataConfigManager.isTetheringProfileDisabledForRoaming()
805                 && mPhone.getServiceState().getDataRoaming()) {
806             // Use internet network for tethering.
807             return false;
808         }
809         TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
810                 new NetworkRequest.Builder()
811                         .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
812                         .build(), mPhone);
813         return getDataProfileForNetworkRequest(networkRequest, networkType, true) != null;
814     }
815 
816     /**
817      * Dedupe the similar data profiles.
818      */
dedupeDataProfiles(@onNull List<DataProfile> dataProfiles)819     private void dedupeDataProfiles(@NonNull List<DataProfile> dataProfiles) {
820         int i = 0;
821         while (i < dataProfiles.size() - 1) {
822             DataProfile first = dataProfiles.get(i);
823             int j = i + 1;
824             while (j < dataProfiles.size()) {
825                 DataProfile second = dataProfiles.get(j);
826                 DataProfile merged = mergeDataProfiles(first, second);
827                 if (merged != null) {
828                     log("Created a merged profile " + merged + " from " + first + " and "
829                             + second);
830                     loge("Merging data profiles will not be supported anymore. Please "
831                             + "directly configure the merged profile " + merged + " in the APN "
832                             + "config.");
833                     dataProfiles.set(i, merged);
834                     dataProfiles.remove(j);
835                 } else {
836                     j++;
837                 }
838             }
839             i++;
840         }
841     }
842 
843     /**
844      * Trigger anomaly report if APN Setting contains invalid info.
845      *
846      * @param setting The Apn setting to be checked.
847      */
checkApnSetting(@onNull ApnSetting setting)848     private void checkApnSetting(@NonNull ApnSetting setting) {
849         if (setting.canHandleType(ApnSetting.TYPE_MMS)) {
850             if (setting.getMmsc() == null) {
851                 reportAnomaly("MMS is supported but no MMSC configured " + setting,
852                         "9af73e18-b523-4dc5-adab-19d86c6a3685");
853             } else if (!setting.getMmsc().toString().matches("^https?:\\/\\/.+")) {
854                 reportAnomaly("Apn config mmsc should start with http but is "
855                                 + setting.getMmsc(),
856                         "9af73e18-b523-4dc5-adab-ec754d959d4d");
857             }
858             if (!TextUtils.isEmpty(setting.getMmsProxyAddressAsString())
859                     && setting.getMmsProxyAddressAsString().matches("^https?:\\/\\/.+")) {
860                 reportAnomaly("Apn config mmsc_proxy should NOT start with http but is "
861                                 + setting.getMmsc(), "9af73e18-b523-4dc5-adab-ec754d959d4d");
862             }
863         }
864     }
865 
866     /**
867      * Trigger anomaly report if any two Apn Settings share the same APN name while having
868      * overlapped network types.
869      *
870      * @param profiles The list of data profiles to be checked.
871      */
checkDataProfiles(List<DataProfile> profiles)872     private void checkDataProfiles(List<DataProfile> profiles) {
873         for (int i = 0; i < profiles.size(); i++) {
874             ApnSetting a = profiles.get(i).getApnSetting();
875             if (a == null) continue;
876             if (// Lingering network is not the default and doesn't cover all the regular networks
877                     (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN
878                     != a.getLingeringNetworkTypeBitmask()
879                             && (a.getNetworkTypeBitmask() | a.getLingeringNetworkTypeBitmask())
880                     != a.getLingeringNetworkTypeBitmask()) {
881                 reportAnomaly("Apn[" + a.getApnName() + "] network "
882                                 + TelephonyManager.convertNetworkTypeBitmaskToString(
883                                         a.getNetworkTypeBitmask()) + " should be a subset of "
884                                 + "the lingering network "
885                                 + TelephonyManager.convertNetworkTypeBitmaskToString(
886                                 a.getLingeringNetworkTypeBitmask()),
887                         "9af73e18-b523-4dc5-adab-4bb24355d838");
888             }
889             for (int j = i + 1; j < profiles.size(); j++) {
890                 ApnSetting b = profiles.get(j).getApnSetting();
891                 if (b == null) continue;
892                 String apnNameA = a.getApnName();
893                 String apnNameB = b.getApnName();
894                 if (TextUtils.equals(apnNameA, apnNameB)
895                         // TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN means all network types
896                         && (a.getNetworkTypeBitmask()
897                         == (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN
898                         || b.getNetworkTypeBitmask()
899                         == (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN
900                         || (a.getNetworkTypeBitmask() & b.getNetworkTypeBitmask()) != 0)) {
901                     reportAnomaly("Found overlapped network type under the APN name "
902                                     + a.getApnName(),
903                             "9af73e18-b523-4dc5-adab-4bb24555d839");
904                 }
905             }
906         }
907     }
908 
909     /**
910      * Merge two data profiles if possible.
911      *
912      * @param dp1 Data profile 1 to be merged.
913      * @param dp2 Data profile 2 to be merged.
914      *
915      * @return The merged data profile. {@code null} if merging is not possible.
916      */
mergeDataProfiles( @onNull DataProfile dp1, @NonNull DataProfile dp2)917     private static @Nullable DataProfile mergeDataProfiles(
918             @NonNull DataProfile dp1, @NonNull DataProfile dp2) {
919         Objects.requireNonNull(dp1);
920         Objects.requireNonNull(dp2);
921 
922         // We don't merge data profiles that have different traffic descriptor.
923         if (!Objects.equals(dp1.getTrafficDescriptor(), dp2.getTrafficDescriptor())) return null;
924 
925         // If one of the APN setting is null, we don't merge.
926         if (dp1.getApnSetting() == null || dp2.getApnSetting() == null) return null;
927 
928         // If two APN settings are not similar, we don't merge.
929         if (!dp1.getApnSetting().similar(dp2.getApnSetting())) return null;
930 
931         // Start to merge APN setting 1 and 2.
932         ApnSetting apn1 = dp1.getApnSetting();
933         ApnSetting apn2 = dp2.getApnSetting();
934         ApnSetting.Builder apnBuilder = new ApnSetting.Builder();
935 
936         // Special handling id and entry name. We want to keep the default APN as it could be the
937         // preferred APN.
938         apnBuilder.setId(apn1.getId());
939         apnBuilder.setEntryName(apn1.getEntryName());
940         if (apn2.canHandleType(ApnSetting.TYPE_DEFAULT)
941                 && !apn1.canHandleType(ApnSetting.TYPE_DEFAULT)) {
942             apnBuilder.setId(apn2.getId());
943             apnBuilder.setEntryName(apn2.getEntryName());
944         }
945 
946         // Merge the following fields from apn1 and apn2.
947         apnBuilder.setProxyAddress(TextUtils.isEmpty(apn2.getProxyAddressAsString())
948                 ? apn1.getProxyAddressAsString() : apn2.getProxyAddressAsString());
949         apnBuilder.setProxyPort(apn2.getProxyPort() == -1
950                 ? apn1.getProxyPort() : apn2.getProxyPort());
951         apnBuilder.setMmsc(apn2.getMmsc() == null ? apn1.getMmsc() : apn2.getMmsc());
952         apnBuilder.setMmsProxyAddress(TextUtils.isEmpty(apn2.getMmsProxyAddressAsString())
953                 ? apn1.getMmsProxyAddressAsString() : apn2.getMmsProxyAddressAsString());
954         apnBuilder.setMmsProxyPort(apn2.getMmsProxyPort() == -1
955                 ? apn1.getMmsProxyPort() : apn2.getMmsProxyPort());
956         apnBuilder.setUser(TextUtils.isEmpty(apn2.getUser()) ? apn1.getUser() : apn2.getUser());
957         apnBuilder.setPassword(TextUtils.isEmpty(apn2.getPassword())
958                 ? apn1.getPassword() : apn2.getPassword());
959         apnBuilder.setAuthType(apn2.getAuthType() == -1
960                 ? apn1.getAuthType() : apn2.getAuthType());
961         apnBuilder.setApnTypeBitmask(apn1.getApnTypeBitmask() | apn2.getApnTypeBitmask());
962         apnBuilder.setMtuV4(apn2.getMtuV4() <= ApnSetting.UNSET_MTU
963                 ? apn1.getMtuV4() : apn2.getMtuV4());
964         apnBuilder.setMtuV6(apn2.getMtuV6() <= ApnSetting.UNSET_MTU
965                 ? apn1.getMtuV6() : apn2.getMtuV6());
966         // legacy properties that don't matter
967         apnBuilder.setMvnoType(apn1.getMvnoType());
968         apnBuilder.setMvnoMatchData(apn1.getMvnoMatchData());
969 
970         // The following fields in apn1 and apn2 should be the same, otherwise ApnSetting.similar()
971         // should fail earlier.
972         apnBuilder.setApnName(apn1.getApnName());
973         apnBuilder.setProtocol(apn1.getProtocol());
974         apnBuilder.setRoamingProtocol(apn1.getRoamingProtocol());
975         apnBuilder.setCarrierEnabled(apn1.isEnabled());
976         apnBuilder.setNetworkTypeBitmask(apn1.getNetworkTypeBitmask());
977         apnBuilder.setLingeringNetworkTypeBitmask(apn1.getLingeringNetworkTypeBitmask());
978         apnBuilder.setProfileId(apn1.getProfileId());
979         apnBuilder.setPersistent(apn1.isPersistent());
980         apnBuilder.setMaxConns(apn1.getMaxConns());
981         apnBuilder.setWaitTime(apn1.getWaitTime());
982         apnBuilder.setMaxConnsTime(apn1.getMaxConnsTime());
983         apnBuilder.setApnSetId(apn1.getApnSetId());
984         apnBuilder.setCarrierId(apn1.getCarrierId());
985         apnBuilder.setSkip464Xlat(apn1.getSkip464Xlat());
986         apnBuilder.setAlwaysOn(apn1.isAlwaysOn());
987 
988         return new DataProfile.Builder()
989                 .setApnSetting(apnBuilder.build())
990                 .setTrafficDescriptor(dp1.getTrafficDescriptor())
991                 .build();
992     }
993 
994     /**
995      * Check if the provided data profile is still compatible with the current environment. Note
996      * this method ignores APN id check and traffic descriptor check. A data profile with traffic
997      * descriptor only can always be used in any condition.
998      *
999      * @param dataProfile The data profile to check.
1000      * @return {@code true} if the provided data profile can be still used in current environment.
1001      */
isDataProfileCompatible(@onNull DataProfile dataProfile)1002     public boolean isDataProfileCompatible(@NonNull DataProfile dataProfile) {
1003         if (dataProfile == null) {
1004             return false;
1005         }
1006 
1007         if (dataProfile.getApnSetting() == null && dataProfile.getTrafficDescriptor() != null) {
1008             // A traffic descriptor only data profile can be always used. Traffic descriptors are
1009             // always generated on the fly instead loaded from the database.
1010             return true;
1011         }
1012 
1013         // Check the APN from the profile is compatible and matches preferred data profile set id.
1014         return mAllDataProfiles.stream()
1015                 .filter(dp -> dp.getApnSetting() != null
1016                         && (dp.getApnSetting().getApnSetId()
1017                         == Telephony.Carriers.MATCH_ALL_APN_SET_ID
1018                         || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId))
1019                 .anyMatch(dp -> areDataProfilesSharingApn(dataProfile, dp));
1020     }
1021 
1022     /**
1023      * @return {@code true} if both data profiles' APN setting are non-null and essentially the same
1024      * (non-essential elements include e.g.APN Id).
1025      */
areDataProfilesSharingApn(@ullable DataProfile a, @Nullable DataProfile b)1026     public boolean areDataProfilesSharingApn(@Nullable DataProfile a, @Nullable DataProfile b) {
1027         return a != null
1028                 && b != null
1029                 && a.getApnSetting() != null
1030                 && a.getApnSetting().equals(b.getApnSetting(),
1031                 mPhone.getServiceState().getDataRoamingFromRegistration());
1032     }
1033 
1034     /**
1035      * Register the callback for receiving information from {@link DataProfileManager}.
1036      *
1037      * @param callback The callback.
1038      */
registerCallback(@onNull DataProfileManagerCallback callback)1039     public void registerCallback(@NonNull DataProfileManagerCallback callback) {
1040         mDataProfileManagerCallbacks.add(callback);
1041     }
1042 
1043     /**
1044      * Unregister the previously registered {@link DataProfileManagerCallback}.
1045      *
1046      * @param callback The callback to unregister.
1047      */
unregisterCallback(@onNull DataProfileManagerCallback callback)1048     public void unregisterCallback(@NonNull DataProfileManagerCallback callback) {
1049         mDataProfileManagerCallbacks.remove(callback);
1050     }
1051 
1052     /**
1053      * Trigger the anomaly report with the specified UUID.
1054      *
1055      * @param anomalyMsg Description of the event
1056      * @param uuid UUID associated with that event
1057      */
reportAnomaly(@onNull String anomalyMsg, @NonNull String uuid)1058     private void reportAnomaly(@NonNull String anomalyMsg, @NonNull String uuid) {
1059         logl(anomalyMsg);
1060         AnomalyReporter.reportAnomaly(UUID.fromString(uuid), anomalyMsg, mPhone.getCarrierId());
1061     }
1062 
1063     /**
1064      * Log debug messages.
1065      * @param s debug messages
1066      */
log(@onNull String s)1067     private void log(@NonNull String s) {
1068         Rlog.d(mLogTag, s);
1069     }
1070 
1071     /**
1072      * Log error messages.
1073      * @param s error messages
1074      */
loge(@onNull String s)1075     private void loge(@NonNull String s) {
1076         Rlog.e(mLogTag, s);
1077     }
1078 
1079     /**
1080      * Log verbose messages.
1081      * @param s debug messages.
1082      */
logv(@onNull String s)1083     private void logv(@NonNull String s) {
1084         if (VDBG) Rlog.v(mLogTag, s);
1085     }
1086 
1087     /**
1088      * Log debug messages and also log into the local log.
1089      * @param s debug messages
1090      */
logl(@onNull String s)1091     private void logl(@NonNull String s) {
1092         log(s);
1093         mLocalLog.log(s);
1094     }
1095 
1096     /**
1097      * Dump the state of DataProfileManager
1098      *
1099      * @param fd File descriptor
1100      * @param printWriter Print writer
1101      * @param args Arguments
1102      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1103     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
1104         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
1105         pw.println(DataProfileManager.class.getSimpleName() + "-" + mPhone.getPhoneId() + ":");
1106         pw.increaseIndent();
1107 
1108         pw.println("Data profiles for the current carrier:");
1109         pw.increaseIndent();
1110         for (DataProfile dp : mAllDataProfiles) {
1111             pw.print(dp);
1112             pw.println(", last setup time: " + DataUtils.elapsedTimeToString(
1113                     dp.getLastSetupTimestamp()));
1114         }
1115         pw.decreaseIndent();
1116 
1117         pw.println("Preferred data profile=" + mPreferredDataProfile);
1118         pw.println("Preferred data profile from db=" + getPreferredDataProfileFromDb());
1119         pw.println("Preferred data profile from config=" + getPreferredDataProfileFromConfig());
1120         pw.println("Preferred data profile set id=" + mPreferredDataProfileSetId);
1121         pw.println("Last internet data profile=" + mLastInternetDataProfile);
1122         pw.println("Initial attach data profile=" + mInitialAttachDataProfile);
1123         pw.println("isTetheringDataProfileExisting=" + isTetheringDataProfileExisting(
1124                 TelephonyManager.NETWORK_TYPE_LTE));
1125         pw.println("Permanent failed profiles=");
1126         pw.increaseIndent();
1127         mAllDataProfiles.stream()
1128                 .filter(dp -> dp.getApnSetting() != null && dp.getApnSetting().getPermanentFailed())
1129                 .forEach(pw::println);
1130         pw.decreaseIndent();
1131 
1132         pw.println("Local logs:");
1133         pw.increaseIndent();
1134         mLocalLog.dump(fd, pw, args);
1135         pw.decreaseIndent();
1136         pw.decreaseIndent();
1137     }
1138 }
1139