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