Android- IP LOST_PROVISIONING

简介

本文主要基于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断开当前网络。





......

你可能感兴趣的:(Android- IP LOST_PROVISIONING)