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