设为首页 收藏本站
查看: 1260|回复: 0

[经验分享] android wifi之ConnectivityService

[复制链接]

尚未签到

发表于 2015-9-30 11:18:52 | 显示全部楼层 |阅读模式
  在查看了wifiStateTracker源码之后,发现在startMonitoring函数注册的广播里向connectivityService的handler发送了message,我们已知在ConnectivityService的构造函数里面曾经开启了wifiStateTracker的startMonitoring函数以接受广播,现在就来看看connectivityService类。
  首先看它的内部类MyHandler。handleMessage方法中的case方法,1.EVENT_STATE_CHANGED 它接收了所有的stateTracker中发送的消息,



case NetworkStateTracker.EVENT_STATE_CHANGED:                                                                                                                       
if (info.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
         handleConnectionFailure(info);
    } else if (state == NetworkInfo.State.DISCONNECTED) {
handleDisconnect(info);
} else if (state == NetworkInfo.State.SUSPENDED) {
        handleDisconnect(info);            
    } else if (state == NetworkInfo.State.CONNECTED) {
        handleConnect(info);
  }
   break;
  DISCONNECTED和SUSPENDED處理方法基本相同只不过在处理sunpended时发送了一个广播。我们先来了解下handleDisconnect()方法,源码中对着个函数是这样介绍的:我将该方法进行拆块分析,贴源码:



        int prevNetType = info.getType();
        mNetTrackers[prevNetType].setTeardownRequested(false);
/*
* If the disconnected network is not the active one, then don't report
* this as a loss of connectivity. What probably happened is that we're
* getting the disconnect for a network that we explicitly disabled
* in accordance with network preference policies.
*/
if (!mNetConfigs[prevNetType].isDefault()) {
List pids = mNetRequestersPids[prevNetType];
for (int i = 0; i<pids.size(); i++) {
Integer pid = (Integer)pids.get(i);
// will remove them because the net's no longer connected
// need to do this now as only now do we know the pids and
// can properly null things that are no longer referenced.
reassessPidDns(pid.intValue(), false);
}
}
  首先获得网络类型,这里先了解下mNetRequestersPids ,它是在函数public int startUsingNetworkFeature(int networkType, String feature,IBinder binder)里面添加进去的,至于这个函数对应ConnecTivityManager里面的函数,在做网络开发时应该会用到,下面再研究这个函数吧,现在先看遍历这些pids调用了reassessPidDns(pid.intValue(), false); 函数都干什么了:



private void reassessPidDns(int myPid, boolean doBump)
{
if (VDBG) log("reassessPidDns for pid " + myPid);
for(int i : mPriorityList) {
if (mNetConfigs.isDefault()) {
continue;
}
NetworkStateTracker nt = mNetTrackers;
if (nt.getNetworkInfo().isConnected() &&
!nt.isTeardownRequested()) {
LinkProperties p = nt.getLinkProperties();
if (p == null) continue;
List pids = mNetRequestersPids;
for (int j=0; j<pids.size(); j++) {
Integer pid = (Integer)pids.get(j);
if (pid.intValue() == myPid) {
Collection<InetAddress> dnses = p.getDnses();
writePidDns(dnses, myPid);
if (doBump) {
bumpDns();
}
return;
}
}
}
}
// nothing found - delete
for (int i = 1; ; i++) {
String prop = "net.dns" + i + "." + myPid;
if (SystemProperties.get(prop).length() == 0) {
if (doBump) {
bumpDns();
}
return;
}
SystemProperties.set(prop, "");
}
}
  对该函数的说明为 Adjust the per-process dns entries (net.dns<x>.<pid>) based on the highest priority active net which this process requested. If there aren't any, clear it out。
第一个for以优先权遍历所有网络类型找到符合条件(该网络链接存在,有可能传输数据,且没有被tear down)的网络,再对该网络遍历所有的pids(process id 是system server所有)找到目标参数mypid执行函数writePidDns(dnses, myPid);这个函数是向android系统属性里的开机导入的cache属性写入该网络的ip地址及dns等(前提是该网络没有被写进这个属性)。写入之后changed属性就变为true,这样在每次开机init之后,会执行一个loop循环然后若有改变则会更新。这里doBump为false不执行,因此看下面的那个for循环,这个循环里bumpDns也不执行,而只是将有该pid的所有ip链接清空(第一个for循环return了,就不会执行它了)。bumpDns函数是用以提醒重新从系统属性里面读DNS服务器名单。
下面继续handleDisconnect函数讲解,接下来给参数doReset赋值决定是否改变网络接口名称,(若网络中有重名接口则doReset赋值为false)随后调用了handleConnectivityChange方法(prevNetType, doReset),并发送了一个广播该广播是发送给NetWorkStateService的通知网络接口名称改变了。
  至于handleConnecthandleConnect(NetworkInfo info)函数首先判断传进的网络是否为默认网络,若是,且mActiveDefaultNetwork已经设置,且目标type网络不是mActiveDefaultNetwork网络则进入



         if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
if ((type != mNetworkPreference &&
mNetConfigs[mActiveDefaultNetwork].priority >
mNetConfigs[type].priority) ||
mNetworkPreference == mActiveDefaultNetwork) {
// don't accept this one
if (VDBG) {
log("Not broadcasting CONNECT_ACTION " +
"to torn down network " + info.getTypeName());
}
teardown(thisNet);
return;
//    sunxz begin 2012-2-4 for pppoe
} else if(type != ConnectivityManager.TYPE_PPPOE){
//    sunxz end 2012-2-4 for pppoe
// tear down the other
NetworkStateTracker otherNet =
mNetTrackers[mActiveDefaultNetwork];
if (DBG) {
log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
" teardown");
}
if (!teardown(otherNet)) {
loge("Network declined teardown request");
teardown(thisNet);
return;
}
}}
  在该段函数里(第一个if里)第一个判断是说如果目标type网络不是preference网络且正在运行的网络优先级大于type网络则,或者正在运行的网络是preference网络则关闭(tear down)type网络。else if判断是说若type网络类型若不是pppoe就tear down otherNet或者typeNet,注意进入这两个都会执行return若没有被return则会继续往下执行,看源码:



            synchronized (ConnectivityService.this) {
                 if (mNetTransitionWakeLock.isHeld()) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(
EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
mNetTransitionWakeLockSerialNumber, 0),
1000);
}
}
  这段代码首先判断屏幕是否亮着,若亮着,一秒种之后关闭屏幕,之所以一秒钟之后关闭是留给应用程序连接新网络所用的时间。这里面我的想法:代码能执行到这里是因为没有被return,也就是没有关闭type网络(新网络),也就是说新的网络被允许链接了。首先wpa_supplicant扫描出网络状态改变了,然后发消息给wifiStatemachine,然后wifistatemachine收到消息,用wifiNative enable新的网络,然后发广播给wifistateTRacker,在wifiStateTracker的onReiceive方法里面再给connectivityService的handler发送message就到了这里了,应该说这个函数的处理就是看连接上的网络是否符合条件若不符合就直接tear down。
       继续往下看代码:



            mActiveDefaultNetwork = type;            
            // this will cause us to come up initially as unconnected and switching
// to connected after our normal pause unless somebody reports us as reall
// disconnected
mDefaultInetConditionPublished = 0;
mDefaultConnectionSequence++;
mInetConditionChangeInFlight = false;
// Don't do this - if we never sign in stay, grey
//reportNetworkCondition(mActiveDefaultNetwork, 100);
        }
thisNet.setTeardownRequested(false);
updateNetworkSettings(thisNet);
handleConnectivityChange(type, false);
sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
     }
  首先将正在运行的网络的类型改为type,然后再更新一下变量。updateNetworkSettings(thisNet)函数是从系统属性里面读出该网络的属性信息然后把它写到"/sys/kernel/ipv4/tcp_"里面。至此handleConnect函数已经分析完毕了。
  下面看函数handleConnectionFailure(NetworkInfo info)  Called when an attempt to fail over to another network has failed. @param info the {@link NetworkInfo} for the failed network



if (mNetConfigs[info.getType()].isDefault()) {
tryFailover(info.getType());
if (mActiveDefaultNetwork != -1) {
NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
mDefaultInetConditionPublished = 0;
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
  该段代码的核心是tryFailover(info.getType()); 它会依次对记录的所有网络都尝试进行连接,mActiveDefaultNetwork != -1说明在handleConnect函数里已经修改了它的值,即有可用的连接,随后发一条广播通知说已经连接上网络了。handleConnectionFailure不同于handleDisconnected,前者是连接失败,后者是IP连接不可用,前者里面相对与后者没有向SystemProperty里面写信息,也没有改网络接口名称,也没有执行handleConnectivityChange函数。
  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-120873-1-1.html 上篇帖子: 一个用C#实现的虚拟WiFi设置程序 下篇帖子: 手机共享电脑Wifi软件网络抓包
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表