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