Android- IP LOST_PROVISIONING 的机制

本文详细介绍了Android系统中处理IP配置丢失(LOST_PROVISIONING)的机制与流程,包括IpReachabilityMonitor如何监测并通知系统,以及系统如何响应这些事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当log中出现以下信息的时候,说明周围的AP设备出现了一个问题。

(standard input):1269530:12-20 06:53:39.325   578   622 D WifiStateMachine: FAILURE: LOST_PROVISIONING, NeighborEvent{elapsedMs=61927860, 10.10.100.11, [(null)], RTM_NEWNEIGH, NUD_FAILED}


下面是对这个机制的说明:


本文主要基于Android 7.0 介绍IP LOST_PROVISIONING 的情况的处理逻辑;

通过Android-IpReachabilityMonitor文章可知对于处于IpWatchlist中neighbor网络,Android 会定期持续地去Probe相应的neighbor状态,如果得不到任何响应response, 则可能将该neighbor的状态置为NUD_FAILED,进一步发出neighbor 配置丢失的消息LOST_PROVISIONING。


IpReachabilityMonitor


1、声明一个IpReachabilityMonitor  Callback接口:

public interface Callback {

// This callback function must execute as quickly as possible as it is

// run on the same thread that listens to kernel neighbor updates.

// TODO: refactor to something like notifyProvisioningLost(String msg).

public void notifyLost(InetAddress ip, String logMsg);

}

2、IpReachabilityMonitor  Callback接口调用

//在IpReachabilityMonitor构造函数中初始化

public IpReachabilityMonitor(Context context, String ifName, Callback callback,

AvoidBadWifiTracker tracker) throws IllegalArgumentException {

....

mCallback = callback;

....

}

//在IpReachiabilityMonitor的handleNeighborLost中,当neighbor的配置为LOST_PROVISIONING时调用回调函数

private void handleNeighborLost(String msg) {

......

        if (delta == ProvisioningChange.LOST_PROVISIONING) {

              if (mCallback != null) {

          // TODO: remove |ip| when the callback signature no longer has an InetAddress argument.

                       mCallback.notifyLost(ip, logMsg);

             }

         }

......

}

3、IpReachabilityMonitor  Callback接口的实现

IpReachabilityMonitor类的Callback Interface的实现是在IpManager类中。

在IpManager的RunningState状态的enter函数中,在启动Ipv6 和 Ipv4后,就会创建一个IpReachabilityMonitor的实例(在IpReachabilityMonitor的构造函数中就会启懂NetlinkSocketObserver子线程,用于接收Kernel 消息并解析,详见Android-IpReachabilityMonitor文章),同时对IpReachabilityMonitor的Callback进行赋值。

class RunningState extends State {

@Override

public void enter() {

.......

         //启动IPv6

         if (mConfiguration.mEnableIPv6) {

                startIPv6();

         }

         //启动IPv4

         if (mConfiguration.mEnableIPv4) {

               if (!startIPv4()) {

                      transitionTo(mStoppingState);

                      return;

               }

          }

          //使能IpReachabilityMonitor机制功能

          if (mConfiguration.mUsingIpReachabilityMonitor) {

                try {

                       mIpReachabilityMonitor = new IpReachabilityMonitor(

                       mContext,mInterfaceName,

                       new IpReachabilityMonitor.Callback() {

                               @Override

                               public void notifyLost(InetAddress ip, String logMsg) {

                                       //回调IpManager类中mCallback对象

                                         mCallback.onReachabilityLost(logMsg);

                               }

                         },

                         mAvoidBadWifiTracker);

                   } catch (IllegalArgumentException e) {

                         Log.e(mTag, "star IRM fail: " + e);

                         transitionTo(mStoppingState);

                  }

          }

}

上面的分析可知IpReachabilityMonitor  Callback接口的notifyLost(InetAddress ip, String logMsg) 调用IpManager Callback类的onReachabilityLost(logMsg)

下面分析IpManager Callback类。


IpManager


1、IpManager Callback类的声明和初始化

public IpManager(Context context, String ifName, Callback callback,

INetworkManagementService nwService) throws IllegalArgumentException {

.....

mCallback = callback;

....

}

/** Callbacks for handling IpManager events.*/

public static class Callback {

       ......

        // Called when the internal IpReachabilityMonitor (if enabled) hasdetected the loss of a critical number of required neighbors.

     //当内部IpReachabilityMonitor(如果使能了)已经检测到需要的邻居neighbor网络达到一个临界数量丢失时,就会调用。

        public void onReachabilityLost(String logMsg) {}

      ......

}

2、IpManager 子类Callback类的实现(主要针对onReachabilityLost 函数)

IpManager 子类Callback类的实现是在WifiStateMachine中实现的。

class IpManagerCallback extends IpManager.Callback { .......

@Override

public void onReachabilityLost(String logMsg) {

sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);

}

.......

}

上面的分析的LOST_PROVISIONING 处理逻辑如下:

IpReachabilityMonitor: LOST_PROVISIONING  -> mCallback.notifyLost(ip, logMsg);

IpManager: mCallback.onReachabilityLost(String logMsg)

WifiStateMachine: sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);


WifiStateMachine


此处主要关注WifiStateMachine中对CMD_IP_REACHABILITY_LOST命令的处理。

1、状态机对CMD_IP_REACHABILITY_LOST命令的处理

该消息的处理仅在WifiStateMachine的状态机中,有两个状态会处理DefaultState和L2ConnectedState。

在DefaultState中,接收到CMD_IP_REACHABILITY_LOST命令直接丢弃不处理:

class DefaultState extends State {

@Override

public boolean processMessage(Message message) {

....

         case CMD_IP_REACHABILITY_LOST:

              messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;

              break;

....

}

在L2ConnectedState状态中,接收到CMD_IP_REACHABILITY_LOST命令处理:

class L2ConnectedState extends State {

.....

     @Override

    public boolean processMessage(Message message) {

    switch (message.what) {

     ......

          case CMD_IP_REACHABILITY_LOST:

                 ///M: ALPS02475594 Ignore ip reachability lost for improving performance

                //由于一些特殊使用场景,比如使用Wi-Fi Display时为了提高Wi-Fi Tput ,可能需要临时暂停Wi-Fi 一段时间的Scan和重连动作。此时就会忽视ignore CMD_IP_REACHABILITY_LOST命令,不做任何处理。

                 if (isTemporarilyDontReconnectWifi()) {

                  //如果临时暂定Wi-Fi的扫描和重连功能,直接丢弃CMD_IP_REACHABILITY_LOST命令不做任何处理

                      log("isTemporarilyDontReconnectWifi is true, " +"ignore CMD_IP_REACHABILITY_LOST");

                } else if (enableIpReachabilityMonitor()) {

                   //如果已经使能了IpReachabilityMonitor机制功能,系统默认使能

                   if (!enableIpReachabilityMonitorEnhancement() ||   mIsListeningIpReachabilityLost

                      || ((mIpManager != null) && (mIpManager.getLostCount() >= 3)))  {

                       //这里满足三个条件任何一个就执行下面的操作

                          handleIpReachabilityLost();

                          transitionTo(mDisconnectingState);

                     } else {

                       ///如下这段MTK添加的patch, 由于在上一个if条件中已经有了mIsListeningIpReachabilityLost为true的情况,所以此段代码永远不会执行,为无效代码。

                                 ///M: ALPS02550356 Avoid frequently disconnect caused by ip                                    //   reachability lost @{

                          Log.d(TAG, "mIsListeningIpReachabilityLost: "+ mIsListeningIpReachabilityLost);

                                  if (mIsListeningIpReachabilityLost) {

                                              handleIpReachabilityLost();

                                              transitionTo(mDisconnectingState);

                                  } else {

                                      Log.d(TAG, "Ignore CMD_IP_REACHABILITY_LOST");

                                 }

                       }

              } else {

                  //如果没有使能 IpReachabilityMonitor机制功能,直接丢弃CMD_IP_REACHABILITY_LOST命令不做任何处理

                    Log.d(TAG, "Ignore CMD_IP_REACHABILITY_LOST " +"due to enableIpReachabilityMonitor is off");

             }

           break;

.....

}

从上面的代码可以看出,WifiStateMachine 中的消息CMD_IP_REACHABILITY_LOST在使能IpReachabilityMonitor的情况下,只要满足三个条件中一个,就执行handleIpReachabilityLost(),并且状态机由L2ConnectedState进入DisconnectingState.

这三个条件分别解释如下:

!enableIpReachabilityMonitorEnhancement()  //这个由系统属性persist.wifi.IRM.enhancement和com.mediatek.internal.R.bool.config_enable_ip_reachability_monitor_enhancement 两个值控制,其实这个条件就是MTK自己基于Google Android原生添加的,该条件为True的意思是系统属性和MTK的配置变量均置为了False了。

mIsListeningIpReachabilityLost  //这个也是MTK自己基于Google Android 原生添加的,跟上面的一样。为True的意思是已经启动开始监听IpReachabilityLost的功能。

((mIpManager != null) &&(mIpManager.getLostCount() >= 3)) //这个也是基于Android 原生自己新增的控制条件,主要用于控制出现3次IP LOST_PROVISIONING(CMD_IP_REACHABILITY_LOST)时,才执行handleIpReachabilityLost(); 主要是为了避免由于芯片级不稳定,驱动频繁发出IP LOST_PROVISIONING, 从而带来上层频繁断线,用户体验很差。当然这个仅算是一个避归方案。真正的问题出现在芯片驱动上。

2、handleIpReachabilityLost()操作

// TODO: De-duplicated this and handleIpConfigurationLost().

private void handleIpReachabilityLost() {

            //清空当前网络的mIpAddress

             mWifiInfo.setInetAddress(null);

            //将WifiInfo中mMeteredHint置为false。该变量表示相应的网络的上游连接被计量了(该网络需要按流量收费的意思),对于大数据传输很敏感。

             mWifiInfo.setMeteredHint(false);

             //发送一个广播出去,应用层获取广播后,友善提示用户当前网络已经断开

              sendBroadcastForErrorNetwork();

            // Disconnect via supplicant, and let autojoin retry connecting to the network.

            //将Supplicant连接也断开,即完全断开网络,让其执行重连动作。

            mWifiNative.disconnect();

}


总结

至此,Android 中由于IpReachabilityMonitor 监视到Kernel上报当前网络配置丢失(LOST_PROVISIONING)的处理完整流程介绍完毕,总结如下:

IpReachabilityMonitor:LOST_PROVISIONING  -> mCallback.notifyLost(ip, logMsg);

                           |

IpManager:mCallback.onReachabilityLost(String logMsg)

                           |

WifiStateMachine:sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);

                           |

WifiStateMachine:handleIpReachabilityLost()

最终从清除当前网路在WifiInfo中Ip地址信息,并置其mMeteredHint属性为false,然后下发Supplicant断开当前网络。


<think>好的,我需要帮助用户了解在Android 13中如何为第三方应用添加DISPATCH_PROVISIONING_MESSAGE权限。首先,我需要确认这个权限的具体信息。根据用户提到的引用内容,权限的配置通常涉及AndroidManifest.xml中的声明和使用。 DISPATCH_PROVISIONING_MESSAGE权限可能是一个系统权限或者签名权限,因为Android中的某些高级权限需要特定的保护级别。根据引用[1],android:protectionLevel决定了权限的使用方式,特别是在Android 6.0+的动态权限管理中。因此,我需要检查这个权限的保护级别是否为signature或privileged,这会影响第三方应用是否能直接声明和使用它。 接下来,用户可能需要在AndroidManifest.xml中添加权限声明。通常,使用<uses-permission>标签,但如果权限是系统或签名级别,普通应用可能无法直接获得。如果是签名权限,应用需要使用与系统相同的签名,这对于第三方应用来说通常不可行。因此,可能需要寻找其他方法,如成为特权应用或与设备制造商合作。 此外,用户可能需要动态请求权限,尽管对于系统权限,动态请求可能无效。需要查阅Android 13的官方文档,确认DISPATCH_PROVISIONING_MESSAGE权限的具体保护级别和使用条件。如果该权限属于危险权限,可能需要运行时请求;如果是正常权限,只需在清单中声明即可。 最后,用户可能需要处理权限未授予的情况,确保应用在缺少权限时优雅降级。需要编写相应的代码检查权限状态,并在必要时提示用户或调整功能。同时,测试在不同设备上的兼容性也很重要,因为厂商可能有不同的实现。 总结步骤:确认权限保护级别,修改清单文件,处理动态请求(如果适用),测试和适配。需要提醒用户,某些权限可能无法被第三方应用获取,除非有特殊权限或系统签名。</think>在Android 13中为第三方应用配置`DISPATCH_PROVISIONING_MESSAGE`权限,需要遵循以下步骤: ### 1. **确认权限属性** 该权限属于系统级权限,定义在`android.Manifest.permission`中,其保护级别为`signature|privileged`[^1],意味着需要满足以下条件之一: - 应用需与系统签名一致(系统应用) - 应用需放置在`/system/priv-app`目录(特权应用) ### 2. **声明权限** 在`AndroidManifest.xml`中添加以下声明: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.yourapp"> <!-- 声明权限使用 --> <uses-permission android:name="android.permission.DISPATCH_PROVISIONING_MESSAGE"/> <!-- 如果是自定义权限需定义,但系统权限无需重复定义 --> </manifest> ``` ### 3. **权限申请限制** 由于该权限的保护级别为`signature|privileged`,普通第三方应用**无法直接获取**。需通过以下方式实现: - **系统应用**:使用与设备系统相同的签名证书编译应用 - **特权应用**:将应用预置到设备的`/system/priv-app`目录(需Root或厂商合作) ### 4. **动态请求权限(可选)** 对于非特权应用,即使声明权限也会被系统自动拒绝。若拥有特权身份,可添加权限检查: ```kotlin if (ContextCompat.checkSelfPermission( this, Manifest.permission.DISPATCH_PROVISIONING_MESSAGE ) != PackageManager.PERMISSION_GRANTED) { // 处理无权限情况 } ``` ### 5. **厂商适配建议** 与设备制造商合作,通过以下方式实现: - **定制ROM**:将应用集成到系统镜像中 - **白名单机制**:厂商在框架层为特定包名授权该权限 ### 6. **备选方案** 如果无法获得权限,可考虑使用Android Enterprise API或设备策略控制器(DPC)的合法接口实现类似功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值