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断开当前网络。





......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 简介 本文主要介绍基于Android 7.0 的IpReachabilityMonitor机制 IpReachab...
    ChangeALittle阅读 4,492评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,723评论 0 33
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,357评论 0 17
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,573评论 18 399