• Android U 匹配不到APN,无法发起数据建立的问题分析


    问题

    打开数据开关后,没有data PDN请求发起,因此无法上网。

    根据日志确定是没有找到合适的data profile,原因一般有:

    1、APN 没有配置

    2、APN 类型/网络能力不满足——APN type或bearer

    3、APN 配置了但被disable了——APN proofile的carrierEnable值

    日志分析

    fail log:

    APN 被disable了,所以无法匹配。

    //preferred=true说明当前选中的是此条APN

    11-20 15:01:51.409140  2316  3480 D DPM-0   : getApnSettingForNetworkRequest: networkType=13 isMtkImsDataSupport=true hasEimsCapability=false mPreferredDataProfile=[DataProfile=[ApnSetting]....] dataProfilesCount=0 dataProfiles=[] mAllDataProfiles=[[DataProfile=[ApnSetting] INTERNET, 3080, xxxxxx, internet, , null, , null, null, 0, supl | hipri | default, IPV4V6, IP, false, 0, true, 0, 0, 0, 0, 0, gid, xxxxx000000000000, false, UNKNOWN, UNKNOWN, 0, -1, -1, false, 961, TrafficDescriptor={mDnn=internet, null}, preferred=true]...]
    11-20 15:01:51.410224  2316  3480 D DPM-0   : Can't find any data profile that can satisfy [NetworkRequest [ NONE id=0, [ Capabilities: DUN&TRUSTED&NOT_VPN&NOT_VCN_MANAGED Uid: 1001 UnderlyingNetworks: Null] ], mPriority=30, state=UNSATISFIED, mAttachedDataNetwork=null, isMetered=true, created time=15:01:51.407, evaluation result=null]
    11-20 15:01:51.411224  1366  1366 D ImsManager: [1] Registration callback removed.
    11-20 15:01:51.413463  2316  3480 D DPM-0   : Unable to find a data profile for [NetworkRequest [ NONE id=0, [ Capabilities: DUN&TRUSTED&NOT_VPN&NOT_VCN_MANAGED Uid: 1001 UnderlyingNetworks: Null] ], mPriority=30, state=UNSATISFIED, mAttachedDataNetwork=null, isMetered=true, created time=15:01:51.408, evaluation result=null]

    正常日志:

    dataProfilesCount 指明网络能力匹配的APN数

    11-20 15:19:20.723854  2316  2316 D DPM-0   : getApnSettingForNetworkRequest: networkType=13 isMtkImsDataSupport=true hasEimsCapability=false mPreferredDataProfile=[DataProfile=[ApnSetting] ....] dataProfilesCount=1 dataProfiles=[[DataProfile=[ApnSetting] 

    11-20 15:19:20.725075  2316  2316 V DPM-0   : Satisfied profile: [DataProfile=[ApnSetting]

    11-20 15:19:20.725871  2316  2316 D DPM-0   : The final available profile: [DataProfile=[ApnSetting] 

    11-20 15:19:20.729504  2316  2316 D DNC-0   : Data evaluation: evaluation reason:NEW_REQUEST, Data allowed reason: NORMAL, candidate profile=[DataProfile=[ApnSetting] 

    11-20 15:19:20.730116  2316  2316 D DNC-0   : onSetupDataNetwork: dataProfile=[DataProfile=[ApnSetting] 

    11-20 15:19:20.731688  2316  2316 D DNC-0   : Creating data network on WWAN with [DataProfile=[ApnSetting] 

    11-20 15:19:20.768286  2316  2316 D DSM-C-0 : setupDataCall

    11-20 15:19:20.769505  2316  2316 D DN-114-C: ConnectingState: setupData: accessNetwork=EUTRAN, [DataProfile=[ApnSetting] ...], isModemRoaming=false, allowRoaming=true, PDU session id=0, matchAllRuleAllowed=true
    11-20 15:19:20.776007  2316  2682 D RILJ    :

     [0868]> SETUP_DATA_CALL,reason=NORMAL,accessNetworkType=EUTRAN,dataProfile=[DataProfile=[ApnSetting] ..],isRoaming=false,allowRoaming=true,linkProperties=null,pduSessionId=0,sliceInfo=null,trafficDescriptor=TrafficDescriptor={mDnn=VZWADMIN, null},matchAllRuleAllowed=true [PHONE0]

    11-20 15:19:21.063568  2316  2674 D RILJ    : [0868]< SETUP_DATA_CALL DataCallResponse: { cause=NONE(0x0) retry=-1 cid=1803 linkStatus=2 protocolType=2 ifname=ccmni3 addresses=[10.128.159.113/32, 2600:100f:f00c:330f:0:56:6fe2:e801/64] dnses=[/2001:4888:53:ff00:524:d::, /2001:4888:52:ff00:528:d::, /198.224.166.135, /198.224.167.135] gateways=[/10.128.159.113, /::] pcscf=[] mtu=1428 mtuV4=1428 mtuV6=1428 handoverFailureMode=unknown pduSessionId=0 defaultQos=EpsQos { qosClassId=8 downlink=Bandwidth { maxBitrateKbps=0 guaranteedBitrateKbps=0} uplink=Bandwidth { maxBitrateKbps=0 guaranteedBitrateKbps=0}} qosBearerSessions=[] sliceInfo=null trafficDescriptors=[]} [PHONE0]

     代码分析

    DataProfileManager.java - 【frameworks/opt/telephony】

    1. /**
    2. * Get the APN setting for the network request.
    3. *
    4. * @param networkRequest The network request.
    5. * @param networkType The current data network type.
    6. * @param ignorePermanentFailure {@code true} to ignore {@link ApnSetting#getPermanentFailed()}.
    7. * This should be set to true for condition-based retry/setup.
    8. * @return The APN setting. {@code null} if can't find any satisfiable data profile.
    9. */
    10. private @Nullable ApnSetting getApnSettingForNetworkRequest(
    11. @NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType,
    12. boolean ignorePermanentFailure) {
    13. if (!networkRequest.hasAttribute(
    14. TelephonyNetworkRequest.CAPABILITY_ATTRIBUTE_APN_SETTING)) {
    15. loge("Network request does not have APN setting attribute.");
    16. return null;
    17. }
    18. //1、优先选择preferred APN,如果满足并且不处于PermanentFailure状态则直接请求
    19. // If the preferred data profile can be used, always use it if it can satisfy the network
    20. // request with current network type (even though it's been marked as permanent failed.)
    21. if (mPreferredDataProfile != null
    22. && networkRequest.canBeSatisfiedBy(mPreferredDataProfile)
    23. && mPreferredDataProfile.getApnSetting() != null
    24. && mPreferredDataProfile.getApnSetting().canSupportNetworkType(networkType)) {
    25. if (ignorePermanentFailure || !mPreferredDataProfile.getApnSetting()
    26. .getPermanentFailed()) {
    27. return mPreferredDataProfile.getApnSetting();
    28. }
    29. log("The preferred data profile is permanently failed. Only condition based retry "
    30. + "can happen.");
    31. return null;
    32. }
    33. //2、如果没有首选数据配置文件,则过滤掉不能满足网络请求的数据配置文件
    34. //Note:找不到profile 一般就是这里匹配不到了
    35. // Filter out the data profile that can't satisfy the request.
    36. // Preferred data profile should be returned in the top of the list.
    37. List dataProfiles = mAllDataProfiles.stream()
    38. .filter(networkRequest::canBeSatisfiedBy)
    39. // The longest time hasn't used data profile will be in the front so all the data
    40. // profiles can be tried.
    41. .sorted(Comparator.comparing(DataProfile::getLastSetupTimestamp)) //并按照它们的最后设置时间进行排序,将最长时间未使用的数据配置文件放在列表的前面
    42. .collect(Collectors.toList());
    43. for (DataProfile dataProfile : dataProfiles) { //然后尝试筛选并使用它们来满足网络请求。
    44. logv("Satisfied profile: " + dataProfile + ", last setup="
    45. + DataUtils.elapsedTimeToString(dataProfile.getLastSetupTimestamp()));
    46. }
    47. if (dataProfiles.size() == 0) {
    48. log("Can't find any data profile that can satisfy " + networkRequest);
    49. return null;
    50. }
    51. // Check if the remaining data profiles can used in current data network type.
    52. dataProfiles = dataProfiles.stream()
    53. .filter(dp -> dp.getApnSetting() != null
    54. && dp.getApnSetting().canSupportNetworkType(networkType))
    55. .collect(Collectors.toList());
    56. if (dataProfiles.size() == 0) {
    57. log("Can't find any data profile for network type "
    58. + TelephonyManager.getNetworkTypeName(networkType));
    59. return null;
    60. }
    61. // Check if preferred data profile set id matches.
    62. dataProfiles = dataProfiles.stream()
    63. .filter(dp -> dp.getApnSetting() != null
    64. && (dp.getApnSetting().getApnSetId()
    65. == Telephony.Carriers.MATCH_ALL_APN_SET_ID
    66. || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId))
    67. .collect(Collectors.toList());
    68. if (dataProfiles.size() == 0) {
    69. log("Can't find any data profile has APN set id matched. mPreferredDataProfileSetId="
    70. + mPreferredDataProfileSetId);
    71. return null;
    72. }
    73. // Check if data profiles are permanently failed.
    74. dataProfiles = dataProfiles.stream()
    75. .filter(dp -> ignorePermanentFailure || !dp.getApnSetting().getPermanentFailed())
    76. .collect(Collectors.toList());
    77. if (dataProfiles.size() == 0) {
    78. log("The suitable data profiles are all in permanent failed state.");
    79. return null;
    80. }
    81. return dataProfiles.get(0).getApnSetting();
    82. }
    排查接口

    canBeSatisfiedBy in TelephonyNetworkRequest.java -【frameworks/opt/telephony】

    canHandleType in ApnSetting.java【frameworks/base/telephony】


    匹配不到关键就是在网络能力评估的过程,canBeSatisfiedBy会根据APN类型筛选能力匹配的项,在canHandleType检查完APN可用性之后,返回enable且符合网络的APN。

    1. /**
    2. * Check if this network request can be satisfied by a data profile.
    3. *
    4. * @param dataProfile The data profile to check.
    5. * @return {@code true} if this network request can be satisfied by the data profile.
    6. */
    7. public boolean canBeSatisfiedBy(@NonNull DataProfile dataProfile) {
    8. // If the network request can be translated to OS/App id, then check if the data profile's
    9. // OS/App id can satisfy it.
    10. if (hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)
    11. && getOsAppId() != null) {
    12. // The network request has traffic descriptor type capabilities. Match the traffic
    13. // descriptor.
    14. if (dataProfile.getTrafficDescriptor() != null && Arrays.equals(getOsAppId().getBytes(),
    15. dataProfile.getTrafficDescriptor().getOsAppId())) {
    16. return true;
    17. }
    18. }
    19. // If the network request can be translated to APN setting or DNN in traffic descriptor,
    20. // then check if the data profile's APN setting can satisfy it.
    21. if ((hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)
    22. || hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN))
    23. && dataProfile.getApnSetting() != null) {
    24. // Fallback to the legacy APN type matching.
    25. List apnTypes = Arrays.stream(getCapabilities()).boxed()
    26. .map(DataUtils::networkCapabilityToApnType)
    27. .filter(apnType -> apnType != ApnSetting.TYPE_NONE)
    28. .collect(Collectors.toList());
    29. // In case of enterprise network request, the network request will have internet,
    30. // but APN type will not have default type as the enterprise apn should not be used
    31. // as default network. Ignore default type of the network request if it
    32. // has enterprise type as well. This will make sure the network request with
    33. // internet and enterprise will be satisfied with data profile with enterprise at the
    34. // same time default network request will not get satisfied with enterprise data
    35. // profile.
    36. // TODO b/232264746
    37. if (apnTypes.contains(ApnSetting.TYPE_ENTERPRISE)) {
    38. apnTypes.remove((Integer) ApnSetting.TYPE_DEFAULT);
    39. }
    40. return apnTypes.stream().allMatch(dataProfile.getApnSetting()::canHandleType);
    41. }
    42. return false;
    43. }
    44. /** @hide */
    45. public boolean canHandleType(@ApnType int type) {
    46. if (!mCarrierEnabled) {
    47. return false;
    48. }
    49. // DEFAULT can handle HIPRI.
    50. return hasApnType(type);
    51. }

    定位原因的方法

    查看APNSettings配置是否正确,以上问题就是APN配置了但被disable了。

    [DataProfile=[ApnSetting] INTERNET, 3080, xxxxxx, internet, , null, , null, null, 0, supl | hipri | default, IPV4V6, IP, false, 0, true, 0, 0, 0, 0, 0, gid, xxxxx000000000000, false, UNKNOWN, UNKNOWN, 0, -1, -1, false, 961, TrafficDescriptor={mDnn=internet, null}, preferred=true]

    根据ApnSettings实体节后打印信息,mCarrierEnabled就是上述日志false的位置。

    1. /**
    2. * Returns the string representation of ApnSetting.
    3. *
    4. * This method prints null for unset elements. The output doesn't contain password or user.
    5. * @hide
    6. */
    7. public String toString() {
    8. StringBuilder sb = new StringBuilder();
    9. sb.append("[ApnSetting] ")
    10. .append(mEntryName)
    11. .append(", ").append(mId)
    12. .append(", ").append(mOperatorNumeric)
    13. .append(", ").append(mApnName)
    14. .append(", ").append(mProxyAddress)
    15. .append(", ").append(UriToString(mMmsc))
    16. .append(", ").append(mMmsProxyAddress)
    17. .append(", ").append(portToString(mMmsProxyPort))
    18. .append(", ").append(portToString(mProxyPort))
    19. .append(", ").append(mAuthType).append(", ");
    20. final String[] types = getApnTypesStringFromBitmask(mApnTypeBitmask).split(",");
    21. sb.append(TextUtils.join(" | ", types));
    22. sb.append(", ").append(PROTOCOL_INT_MAP.get(mProtocol));
    23. sb.append(", ").append(PROTOCOL_INT_MAP.get(mRoamingProtocol));
    24. sb.append(", ").append(mCarrierEnabled); //APN启用情况
    25. sb.append(", ").append(mProfileId);
    26. sb.append(", ").append(mPersistent);
    27. sb.append(", ").append(mMaxConns);
    28. sb.append(", ").append(mWaitTime);
    29. sb.append(", ").append(mMaxConnsTime);
    30. sb.append(", ").append(mMtuV4);
    31. sb.append(", ").append(mMtuV6);
    32. sb.append(", ").append(MVNO_TYPE_INT_MAP.get(mMvnoType));
    33. sb.append(", ").append(mMvnoMatchData);
    34. sb.append(", ").append(mPermanentFailed);
    35. sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString(
    36. mNetworkTypeBitmask));
    37. sb.append(", ").append(TelephonyManager.convertNetworkTypeBitmaskToString(
    38. mLingeringNetworkTypeBitmask));
    39. sb.append(", ").append(mApnSetId);
    40. sb.append(", ").append(mCarrierId);
    41. sb.append(", ").append(mSkip464Xlat);
    42. sb.append(", ").append(mAlwaysOn);
    43. sb.append(", ").append(Objects.hash(mUser, mPassword));
    44. return sb.toString();
    45. }

  • 相关阅读:
    请问各位关于virtual.lab的问题
    bit byte 和各进制关系(位、字节、字符、进制)、常见编码格式
    年如何在不丢失数据的情况下解锁锁定的 Android 手机?
    文件操作(详解!)
    web概述09
    Python基础分享之缩进和选择
    18_ue4进阶末日生存游戏开发[创建运行时UI]
    2022年高教社杯全国大学生数学建模竞赛-【赛题解析篇】D题:气象报文信息卫星通信传输
    现货黄金滑点多少是正常的?
    【C++项目】高并发内存池第七讲性能分析
  • 原文地址:https://blog.csdn.net/qq_38666896/article/details/134557586