Framework中的连接管理机制(转载)

来源:互联网 发布:apache java 编辑:程序博客网 时间:2024/05/20 07:13

本文转载仅限自己学习,欢迎访问原博客

http://blog.csdn.net/u010961631/article/details/48629601

        上一节《Wifi服务框架介绍》介绍了WIFI的大致框架,本文主要介绍连接管理中的几个重要角色,包括:NetworkInfo、NetworkAgent、ConnectivityService、ConnectivityManager等。
        为了便于讨论,本文选取一个具体问题展开分析,那就是:当当前的网络连接变为不可用时,系统如何自动切换其他可用的网络连接的

        我们知道,当手机在使用移动数据上网时,如果进入WIFI环境,手机将会自动连上WIFI使用数据,而当WIFI失去覆盖或者关闭WIFI时,手机又会自动连上移动数据,那么这个机制是如何实现的呢?本文从WIFI框架触发,跟踪当WIFI被disconnect时,如何切换为数据网络。


一、WifiStateMachine更新状态


        WifiStateMachine利用setNetworkDetailedState()方法更新WIFI状态,如果WIFI网络被断开后,就会将DISCONNECTED的状态传递给setNetworkDetailedState(),此时WifiStateMachine就会把状态先同步到NetworkInfo,然后再更新到NetworkAgent对象:

[java] view plain copy
print?
  1. private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {  
  2.     boolean hidden = false;  
  3.     if (state != mNetworkInfo.getDetailedState()) {  
  4.         //更新NetworkInfo的状态  
  5.         mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());  
  6.         if (mNetworkAgent != null) {  
  7.             //将最新状态发送到NetworkAgent  
  8.             mNetworkAgent.sendNetworkInfo(mNetworkInfo);  
  9.         }  
  10.         sendNetworkStateChangeBroadcast(null);  
  11.         return true;  
  12.     }  
  13.     return false;  
  14. }  
        private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {            boolean hidden = false;            if (state != mNetworkInfo.getDetailedState()) {                //更新NetworkInfo的状态                mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());                if (mNetworkAgent != null) {                    //将最新状态发送到NetworkAgent                    mNetworkAgent.sendNetworkInfo(mNetworkInfo);                }                sendNetworkStateChangeBroadcast(null);                return true;            }            return false;        }

        到这里就不得不介绍一下NetworkInfo和NetworkAgent了。


二、NetworkInfo介绍


        NetworkInfo用于标识一个网络连接的状态、类型等属性的,从其提供的public方法我们就能看出其提供了一个网络连接最基本的信息:
[java] view plain copy
print?
  1. @NetworkInfo.java  
  2. //获取网络类型,TYPE_MOBILE/TYPE_WIFI/TYPE_MOBILE_MMS等  
  3. public int getType() {}  
  4. //获取网络类型名称  
  5. public String getTypeName() {}  
  6. //网络是否是CONNECTED或者CONNECTING状态  
  7. public boolean isConnectedOrConnecting() {}  
  8. //网络是否是CONNECTED状态  
  9. public boolean isConnected() {}  
  10. //设置网络是否可用  
  11. public void setIsAvailable(boolean isAvailable) {}  
  12. //判断网络是否可用  
  13. public boolean isAvailable() {}  
  14. //是否漫游状态  
  15. public boolean isRoaming() {}  
  16. //设置漫游状态  
  17. public void setRoaming(boolean isRoaming) {}  
  18. //获取网络的state、mReason等信息  
  19. public DetailedState getDetailedState() {}  
        @NetworkInfo.java        //获取网络类型,TYPE_MOBILE/TYPE_WIFI/TYPE_MOBILE_MMS等        public int getType() {}        //获取网络类型名称        public String getTypeName() {}        //网络是否是CONNECTED或者CONNECTING状态        public boolean isConnectedOrConnecting() {}        //网络是否是CONNECTED状态        public boolean isConnected() {}        //设置网络是否可用        public void setIsAvailable(boolean isAvailable) {}        //判断网络是否可用        public boolean isAvailable() {}        //是否漫游状态        public boolean isRoaming() {}        //设置漫游状态        public void setRoaming(boolean isRoaming) {}        //获取网络的state、mReason等信息        public DetailedState getDetailedState() {}
        应用程序可以通过ConnectivityManager的getNetworkInfo()方法获取到该对象,并通过该对象查询当前的网络状态,比如可以这样获取当前是否有网络连接:
[java] view plain copy
print?
  1. private boolean isNetworkConnected() {  
  2.     final ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);  
  3.     if (connectivity == null) {  
  4.         return false;  
  5.     }  
  6.     final NetworkInfo info = connectivity.getActiveNetworkInfo();  
  7.     return info != null && info.isConnected();  
  8. }  
        private boolean isNetworkConnected() {            final ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);            if (connectivity == null) {                return false;            }            final NetworkInfo info = connectivity.getActiveNetworkInfo();            return info != null && info.isConnected();        }
        上面是应用读取NetworkInfo的方法,那么当网络变化时,就应该由WIFI或者DATA去更新当前的NetworkInfo,而WifiStateMachine在setNetworkDetailedState中做的就是把当前的网络状态更新到NetworkInfo,即:
[java] view plain copy
print?
  1. mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());  
        mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());

        更新完NetworkInfo之后,需要将其更新到ConnectivityManager才可被其他应用读取到,那么如何将其更新到ConnectivityManager呢?这就需要NetworkAgent来完成了。


三、NetworkAgent介绍


        NetworkAgent的作用可以从其官方描述中略知一二:
[html] view plain copy
print?
  1. ”A Utility class for handling for communicating between bearer-specific code and ConnectivityService.”  
        "A Utility class for handling for communicating between bearer-specific code and ConnectivityService."
        这句话描述了NetworkAgent的作用:他是某个网络连接与ConnectivityService之间的通讯的工具
        接下来我们通过代码来认识一下他究竟如何在网络连接与ConnectivityService之间进行通讯。
        先来看一下这个类的定义:
[java] view plain copy
print?
  1. public abstract class NetworkAgent extends Handler {}  
        public abstract class NetworkAgent extends Handler {}
        我们发现,这是一个Handler的子类,并且他是一个抽象类(abstract),需要在子类中被实例化
        然后来看其构造方法:
[java] view plain copy
print?
  1. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) {  
  2.     this(looper, context, logTag, ni, nc, lp, score, null);  
  3. }  
  4. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {  
  5.     super(looper);  
  6.     mContext = context;  
  7.     if (ni == null || nc == null || lp == null) {  
  8.         throw new IllegalArgumentException();  
  9.     }  
  10.     //获取ConnectivityManager对象,并向其注册自己  
  11.     ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);  
  12.     cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);  
  13. }  
        public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) {            this(looper, context, logTag, ni, nc, lp, score, null);        }        public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {            super(looper);            mContext = context;            if (ni == null || nc == null || lp == null) {                throw new IllegalArgumentException();            }            //获取ConnectivityManager对象,并向其注册自己            ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);            cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);        }
        我们看到其构造方法里面主要做了一件事情,获取ConnectivityManager对象,并通过registerNetworkAgent方式注册当前的NetworkAgent。

        接下来我们插入两节来分别介绍另外两个对象:ConnectivityManager和ConnectivityService,然后再回头来看这里的registerNetworkAgent()方法。


四、ConnectivityService介绍


        ConnectivityService是负责连接管理的大总管,他以Service的形式在系统初始化时就被创建:
[java] view plain copy
print?
  1. @SystemServer.java  
  2. public static final String CONNECTIVITY_SERVICE = “connectivity”;  
  3. private void startOtherServices() {  
  4.     try {  
  5.         //创建ConnectivityService  
  6.         connectivity = new ConnectivityService(context, networkManagement, networkStats, networkPolicy);  
  7.         //注册的name为”connectivity”  
  8.         ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);  
  9.         networkStats.bindConnectivityManager(connectivity);  
  10.         networkPolicy.bindConnectivityManager(connectivity);  
  11.     } catch (Throwable e) {  
  12.         reportWtf(”starting Connectivity Service”, e);  
  13.     }  
  14. }  
        @SystemServer.java        public static final String CONNECTIVITY_SERVICE = "connectivity";        private void startOtherServices() {            try {                //创建ConnectivityService                connectivity = new ConnectivityService(context, networkManagement, networkStats, networkPolicy);                //注册的name为"connectivity"                ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);                networkStats.bindConnectivityManager(connectivity);                networkPolicy.bindConnectivityManager(connectivity);            } catch (Throwable e) {                reportWtf("starting Connectivity Service", e);            }        }

        从上面知道,该Service在SystemServer中的name为”Connectivity”。知道了这一点就够了,至于ConnectivityService本身我们暂且不去关注。


五、ConnectivityManager介绍


        与其他众多Manager一样,ConnectivityManager也是在ContextImpl中被创建的:
[java] view plain copy
print?
  1. @ContextImpl.java  
  2. registerService(CONNECTIVITY_SERVICE, new ServiceFetcher() {  
  3.     public Object createService(ContextImpl ctx) {  
  4.         IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);  
  5.         return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));  
  6.     }});  
        @ContextImpl.java        registerService(CONNECTIVITY_SERVICE, new ServiceFetcher() {            public Object createService(ContextImpl ctx) {                IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);                return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));            }});
        从这里我们看到,创建ConnectivityManager时传递了一个name为CONNECTIVITY_SERVICE的服务对象,这个对象就是刚才我们向SystemServer注册的ConnectivityService。然后来看ConnectivityManager的构造方法:
[java] view plain copy
print?
  1. @ConnectivityManager.java  
  2. public ConnectivityManager(IConnectivityManager service) {  
  3.     mService = checkNotNull(service, ”missing IConnectivityManager”);  
  4. }  
        @ConnectivityManager.java        public ConnectivityManager(IConnectivityManager service) {            mService = checkNotNull(service, "missing IConnectivityManager");        }
        这里我们看到,构造方法里面只是将参数ConnectivityService传递给mService对象就完了。

        好了,ConnectivityManager我们了解这么多就够了。下面继续我们NetworkAgent的初始化流程。


六、继续NetworkAgent初始化流程


        现在我们继续NetworkAgent的初始化流程,这个流程中包含AsyncChannel的使用,不了解的同学可以在这里了解其使用方法和机制。


6.1、NetworkAgent向ConnectivityService注册过程


        前面我们说道,NetworkAgent初始化的时候只做了一个事情,就是向ConnectivityManager注册自己,现在我们继续看该注册过程:
[java] view plain copy
print?
  1. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {  
  2.     super(looper);  
  3.     mContext = context;  
  4.     if (ni == null || nc == null || lp == null) {  
  5.         throw new IllegalArgumentException();  
  6.     }  
  7.     //获取ConnectivityManager对象,并向其注册自己  
  8.     ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);  
  9.     cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);  
  10. }  
        public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {            super(looper);            mContext = context;            if (ni == null || nc == null || lp == null) {                throw new IllegalArgumentException();            }            //获取ConnectivityManager对象,并向其注册自己            ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);            cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);        }
        在调用注册方法时传递了六个参数,其中有三个比较重要的参数,都是从构造方法的参数中获取并重新new出来的,其分别是:
        1、new Messenger(this)
        2、new NetworkAgent(ni)
        3、new NetworkCapabilities(nc)

        需要注意的是,这里new出来的三个对象的来源,都应该是NetworkAgent子类被初始化时传递给构造方法的。
        然后我们继续来看ConnectivityManager的registerNetworkAgent()方法。
[java] view plain copy
print?
  1. @ConnectivityManager.java  
  2. public void registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkMisc misc) {  
  3.     try {  
  4.         mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);  
  5.     } catch (RemoteException e) { }  
  6. }  
        @ConnectivityManager.java        public void registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkMisc misc) {            try {                mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);            } catch (RemoteException e) { }        }
        经过前面的介绍我们现在知道,这里的mService就是ConnectivityService,继续来看接下来的流程:
[java] view plain copy
print?
  1. @ConnectivityService.java  
  2. public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc) {  
  3.     //权限检查  
  4.     enforceConnectivityInternalPermission();  
  5.     //创建NetworkAgentInfo对象  
  6.     NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),  
  7.             new NetworkInfo(networkInfo), new LinkProperties(linkProperties),  
  8.             new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,  
  9.             new NetworkMisc(networkMisc));  
  10.     synchronized (this) {  
  11.         nai.networkMonitor.systemReady = mSystemReady;  
  12.     }  
  13.     //向自己Handler发送EVENT_REGISTER_NETWORK_AGENT消息  
  14.     mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));  
  15. }  
        @ConnectivityService.java        public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc) {            //权限检查            enforceConnectivityInternalPermission();            //创建NetworkAgentInfo对象            NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),                    new NetworkInfo(networkInfo), new LinkProperties(linkProperties),                    new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler,                    new NetworkMisc(networkMisc));            synchronized (this) {                nai.networkMonitor.systemReady = mSystemReady;            }            //向自己Handler发送EVENT_REGISTER_NETWORK_AGENT消息            mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));        }
        在ConnectivityService的registerNetworkAgent中做了两件事情:
        1、创建NetworkAgentInfo对象;
        2、向Handler发送EVENT_REGISTER_NETWORK_AGENT消息;

        其中创建NetworkAgentInfo时,传递了九个参数,我们只关注其中三个,分别是:
        1、messenger —-这个参数是registerNetworkAgent的参数,从NetworkAgent传递过来
        2、new AsyncChannel()   —-这是现在创建的新对象
        3、new NetworkCapabilities(NetworkCapabilities) —-这也是用NetworkAgent传递过来的参数创建的对象

        然后我们来看ConnectivityService对EVENT_REGISTER_NETWORK_AGENT的处理:
[java] view plain copy
print?
  1. private class InternalHandler extends Handler {  
  2.     public void handleMessage(Message msg) {  
  3.         NetworkInfo info;  
  4.         switch (msg.what) {  
  5.             case EVENT_REGISTER_NETWORK_AGENT: {  
  6.                handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);  
  7.                break;  
  8.             }  
  9.         }  
  10.     }  
  11. }  
        private class InternalHandler extends Handler {            public void handleMessage(Message msg) {                NetworkInfo info;                switch (msg.what) {                    case EVENT_REGISTER_NETWORK_AGENT: {                       handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);                       break;                    }                }            }        }
        继续看handleRegisterNetworkAgent():
[java] view plain copy
print?
  1. private void handleRegisterNetworkAgent(NetworkAgentInfo na) {  
  2.     mNetworkAgentInfos.put(na.messenger, na);  
  3.     assignNextNetId(na);  
  4.     //向NetworkAgentInfo的asyncChannel对象发起连接请求  
  5.     na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);  
  6.     NetworkInfo networkInfo = na.networkInfo;  
  7.     na.networkInfo = null;  
  8.     updateNetworkInfo(na, networkInfo);  
  9. }  
        private void handleRegisterNetworkAgent(NetworkAgentInfo na) {            mNetworkAgentInfos.put(na.messenger, na);            assignNextNetId(na);            //向NetworkAgentInfo的asyncChannel对象发起连接请求            na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);            NetworkInfo networkInfo = na.networkInfo;            na.networkInfo = null;            updateNetworkInfo(na, networkInfo);        }
        这里我们看到,ConnectivityService向NetworkAgentInfo的asyncChannel对象发起connect请求,并且该AsyncChannel的srcHandler是mTrackerHandler,而dstMessenger对象是NetworkAgentInfo的messenger,那么这里的NetworkAgentInfo是哪里来的呢?
        其实不难看出,这里的NetworkAgentInfo就是在registerNetworkAgent()中创建的,而dstMessenger自然就是NetworkAgent调用registerNetworkAgent()时传递进来的。

        接下来,ConnectivityService将会利用获取到的NetworkAgent对象创建AsyncChannel双向通道。


6.2、ConnectivityService向NetworkAgent申请双向AsyncChannel过程


        我们记得,NetworkAgent当初是这样调用registerNetworkAgent()的:
[java] view plain copy
print?
  1. @NetworkAgent.java  
  2. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {  
  3.     ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);  
  4.     cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);  
  5. }  
        @NetworkAgent.java        public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {            ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE);            cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);        }
        因此ConnectivityService中的dstMessenger其实就是NetworkAgent,准确来说应该是NetworkAgent的子类
        从AsyncChannel的机制我们知道,当利用其发起connect请求时,其将会触发单向连接过程,此时srcHandler(也就是mTrackerHandler)将会收到CMD_CHANNEL_HALF_CONNECTED的消息:
[java] view plain copy
print?
  1. private class NetworkStateTrackerHandler extends Handler {  
  2.     public void handleMessage(Message msg) {  
  3.         NetworkInfo info;  
  4.         switch (msg.what) {  
  5.             case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {  
  6.                 handleAsyncChannelHalfConnect(msg);  
  7.                 break;  
  8.             }  
  9.         }  
  10.     }  
  11. }  
        private class NetworkStateTrackerHandler extends Handler {            public void handleMessage(Message msg) {                NetworkInfo info;                switch (msg.what) {                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {                        handleAsyncChannelHalfConnect(msg);                        break;                    }                }            }        }
        继续来看handleAsyncChannelHalfConnect:
[java] view plain copy
print?
  1. private void handleAsyncChannelHalfConnect(Message msg) {  
  2.     AsyncChannel ac = (AsyncChannel) msg.obj;  
  3.     if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {  
  4.     } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {  
  5.         if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {  
  6.             //向AsyncChannel发送消息  
  7.             mNetworkAgentInfos.get(msg.replyTo).asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);  
  8.         } else {  
  9.         }  
  10.     }  
  11. }  
        private void handleAsyncChannelHalfConnect(Message msg) {            AsyncChannel ac = (AsyncChannel) msg.obj;            if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {            } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {                if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {                    //向AsyncChannel发送消息                    mNetworkAgentInfos.get(msg.replyTo).asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);                } else {                }            }        }
        这里我们看到,此刻ConnectivityService通过AsyncChannel向dstMessenger发送了CMD_CHANNEL_FULL_CONNECTION的消息,从AsyncChannel的机制我们想到,这个消息应该是在向NetworkAgent申请双向通道
        那么NetworkAgent究竟会如何处理该请求呢?
        由于前面我们介绍过,NetworkAgent是抽象类,他需要在子类中被实例化,那么对于WIFI环境来说,他的子类就是在WifiStateMachine中的WifiNetworkAgent对象
        现在我们再回到WifiStateMachine中,我们可以看到,在L2ConnectedState状态机被初始化时将会创建WifiNetworkAgent对象:
[java] view plain copy
print?
  1. class L2ConnectedState extends State {  
  2.     @Override  
  3.     public void enter() {  
  4.         mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, “WifiNetworkAgent”, mNetworkInfo, mNetworkCapabilitiesFilter, mLinkProperties, 60);  
  5.     }  
  6. }   
        class L2ConnectedState extends State {            @Override            public void enter() {                mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, mLinkProperties, 60);            }        } 
        然后来看该WifiNetworkAgent的定义:
[java] view plain copy
print?
  1. @WifiStateMachine.java  
  2. private class WifiNetworkAgent extends NetworkAgent {  
  3.     public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) {  
  4.         super(l, c, TAG, ni, nc, lp, score);  
  5.     }  
  6.     protected void unwanted() {  
  7.         if (this != mNetworkAgent) return;  
  8.         unwantedNetwork(network_status_unwanted_disconnect);  
  9.     }  
  10.   
  11.   
  12.     protected void networkStatus(int status) {  
  13.         if (status == NetworkAgent.INVALID_NETWORK) {  
  14.             unwantedNetwork(network_status_unwanted_disable_autojoin);  
  15.         }  
  16.     }  
  17. }  
        @WifiStateMachine.java        private class WifiNetworkAgent extends NetworkAgent {            public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) {                super(l, c, TAG, ni, nc, lp, score);            }            protected void unwanted() {                if (this != mNetworkAgent) return;                unwantedNetwork(network_status_unwanted_disconnect);            }            protected void networkStatus(int status) {                if (status == NetworkAgent.INVALID_NETWORK) {                    unwantedNetwork(network_status_unwanted_disable_autojoin);                }            }        }
        从这里我们看到,WifiNetworkAgent并没有覆盖父类NetworkAgent中的handleMessage方法,那么也就是说,当ConnectivityService向WifiNetworkAgent发送AsyncChannel请求时,该请求应该在NetworkAgent中被处理,也就是这里:
[java] view plain copy
print?
  1. @NetworkAgent.java  
  2. public void handleMessage(Message msg) {  
  3.     switch (msg.what) {  
  4.         case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {  
  5.            if (mAsyncChannel != null) {  
  6.            } else {  
  7.                //创建WifiNetworkAgent中的AsyncChannel对象  
  8.                AsyncChannel ac = new AsyncChannel();  
  9.                //完成双向通道连接动作  
  10.                ac.connected(nullthis, msg.replyTo);  
  11.                ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL);  
  12.                synchronized (mPreConnectedQueue) {  
  13.                    mAsyncChannel = ac;  
  14.                    for (Message m : mPreConnectedQueue) {  
  15.                        ac.sendMessage(m);  
  16.                    }  
  17.                    mPreConnectedQueue.clear();  
  18.                }  
  19.            }  
  20.            break;  
  21.        }  
  22.     }  
  23. }  
        @NetworkAgent.java        public void handleMessage(Message msg) {            switch (msg.what) {                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {                   if (mAsyncChannel != null) {                   } else {                       //创建WifiNetworkAgent中的AsyncChannel对象                       AsyncChannel ac = new AsyncChannel();                       //完成双向通道连接动作                       ac.connected(null, this, msg.replyTo);                       ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL);                       synchronized (mPreConnectedQueue) {                           mAsyncChannel = ac;                           for (Message m : mPreConnectedQueue) {                               ac.sendMessage(m);                           }                           mPreConnectedQueue.clear();                       }                   }                   break;               }            }        }
        从这个handleMessage()中我们看到,对于ConnectivityService发起的CMD_CHANNEL_FULLY_CONNECTED申请,WifiNetworkAgent创建了自己的AsyncChannel对象并连接上然后发送了STATUS_SUCCESSFUL的消息。
        经过以上过程,在ConnectivityService与WifiNetworkAgent之间就建立了双向的AsyncChannel通道
        以下是整个WifiNetworkAgent的初始化流程:

        


七、WIFI的断开过程


        现在我们再回到WifiStateMachine对当前WIFI状态的更新过程中。当WIFI断开时,WifiStateMachine将会通过setNetworkDetailedState()更新当前WIFI的NetworkInfo对象,并将其传递给WifiNetworkAgent:
[java] view plain copy
print?
  1. private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {  
  2.     boolean hidden = false;  
  3.     if (state != mNetworkInfo.getDetailedState()) {  
  4.         //更新NetworkInfo的状态  
  5.         mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());  
  6.         if (mNetworkAgent != null) {  
  7.             //将最新状态发送到NetworkAgent  
  8.             mNetworkAgent.sendNetworkInfo(mNetworkInfo);  
  9.         }  
  10.         sendNetworkStateChangeBroadcast(null);  
  11.         return true;  
  12.     }  
  13.     return false;  
  14. }  
        private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {            boolean hidden = false;            if (state != mNetworkInfo.getDetailedState()) {                //更新NetworkInfo的状态                mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());                if (mNetworkAgent != null) {                    //将最新状态发送到NetworkAgent                    mNetworkAgent.sendNetworkInfo(mNetworkInfo);                }                sendNetworkStateChangeBroadcast(null);                return true;            }            return false;        }
        然后我们来看NetworkAgent如何将最新的networkInfo传递到ConnectivityService中去:
[java] view plain copy
print?
  1. @NetworkAgent.java  
  2. public void sendNetworkInfo(NetworkInfo networkInfo) {  
  3.     queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));  
  4. }  
        @NetworkAgent.java        public void sendNetworkInfo(NetworkInfo networkInfo) {            queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));        }
        继续:
[java] view plain copy
print?
  1. private void queueOrSendMessage(int what, Object obj) {  
  2.     synchronized (mPreConnectedQueue) {  
  3.         if (mAsyncChannel != null) {  
  4.             //通过AsyncChannel发送请求  
  5.             mAsyncChannel.sendMessage(what, obj);  
  6.         } else {  
  7.             Message msg = Message.obtain();  
  8.             msg.what = what;  
  9.             msg.obj = obj;  
  10.             mPreConnectedQueue.add(msg);  
  11.         }  
  12.     }  
  13. }  
        private void queueOrSendMessage(int what, Object obj) {            synchronized (mPreConnectedQueue) {                if (mAsyncChannel != null) {                    //通过AsyncChannel发送请求                    mAsyncChannel.sendMessage(what, obj);                } else {                    Message msg = Message.obtain();                    msg.what = what;                    msg.obj = obj;                    mPreConnectedQueue.add(msg);                }            }        }
        到这里我们发现,NetworkAgent将最新的NetworkInfo作为一个Object放入一个EVENT_NETWORK_INFO_CHANGED的消息中,然后通过AsyncChannel发送出去。那么这个消息发送到哪里了呢?
        此时我们应该能够想到,当初是ConnectivityService与WifiNetworkAgent创建了双向的AsyncChannel通道,那么此时的消息当然就会发送给ConnectivityService了,并且该消息将会在其NetworkStateTrackerHandler中被处理:
[java] view plain copy
print?
  1. @ConnectivityService.java  
  2. private class NetworkStateTrackerHandler extends Handler {  
  3.     public void handleMessage(Message msg) {  
  4.         NetworkInfo info;  
  5.         switch (msg.what) {  
  6.             case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {  
  7.                   //拿到消息中最新的NetworkInfo信息  
  8.                   NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);  
  9.                   if (nai == null) {  
  10.                       loge(”EVENT_NETWORK_INFO_CHANGED from unknown NetworkAgent”);  
  11.                       break;  
  12.                   }  
  13.                   info = (NetworkInfo) msg.obj;  
  14.                   //通过updateNetworkInfo来进行更新  
  15.                   updateNetworkInfo(nai, info);  
  16.                   break;  
  17.               }  
  18.         }  
  19.     }  
  20. }  
        @ConnectivityService.java        private class NetworkStateTrackerHandler extends Handler {            public void handleMessage(Message msg) {                NetworkInfo info;                switch (msg.what) {                    case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {                          //拿到消息中最新的NetworkInfo信息                          NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);                          if (nai == null) {                              loge("EVENT_NETWORK_INFO_CHANGED from unknown NetworkAgent");                              break;                          }                          info = (NetworkInfo) msg.obj;                          //通过updateNetworkInfo来进行更新                          updateNetworkInfo(nai, info);                          break;                      }                }            }        }
        然后我们继续来看updateNetworkInfo()的操作:
[java] view plain copy
print?
  1. private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {  
  2.     NetworkInfo.State state = newInfo.getState();  
  3.     NetworkInfo oldInfo = null;  
  4.     synchronized (networkAgent) {  
  5.         oldInfo = networkAgent.networkInfo;  
  6.         //将最新的networkInfo更新到ConnectivityService  
  7.         networkAgent.networkInfo = newInfo;  
  8.     }  
  9.   
  10.   
  11.     if (state == NetworkInfo.State.CONNECTED && !networkAgent.created) {  
  12.     } else if (state == NetworkInfo.State.DISCONNECTED || state == NetworkInfo.State.SUSPENDED) {  
  13.         //断开WIFI的NetworkAgent中的AsyncChannel  
  14.         networkAgent.asyncChannel.disconnect();  
  15.     }  
  16. }  
        private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {            NetworkInfo.State state = newInfo.getState();            NetworkInfo oldInfo = null;            synchronized (networkAgent) {                oldInfo = networkAgent.networkInfo;                //将最新的networkInfo更新到ConnectivityService                networkAgent.networkInfo = newInfo;            }            if (state == NetworkInfo.State.CONNECTED && !networkAgent.created) {            } else if (state == NetworkInfo.State.DISCONNECTED || state == NetworkInfo.State.SUSPENDED) {                //断开WIFI的NetworkAgent中的AsyncChannel                networkAgent.asyncChannel.disconnect();            }        }
        在updateNetworkInfo()中,ConnectivityService将最新的NetworkInfo保存在networkAgent中,等待其他应用来获取。然后就向NetworkAgent的AsyncChannel发起disconnect()的请求,该请求将会在ConnectivityService中收到CMD_CHANNEL_DISCONNECTED的回应:
[java] view plain copy
print?
  1. private class NetworkStateTrackerHandler extends Handler {  
  2.     public void handleMessage(Message msg) {  
  3.         NetworkInfo info;  
  4.         switch (msg.what) {  
  5.             case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {  
  6.                 handleAsyncChannelDisconnected(msg);  
  7.                 break;  
  8.             }  
  9.   
  10.   
  11.         }  
  12.     }  
  13. }  
        private class NetworkStateTrackerHandler extends Handler {            public void handleMessage(Message msg) {                NetworkInfo info;                switch (msg.what) {                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {                        handleAsyncChannelDisconnected(msg);                        break;                    }                }            }        }
        继续来看handleAsyncChannelDisconnected():
[java] view plain copy
print?
  1. private void handleAsyncChannelDisconnected(Message msg) {  
  2.     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);  
  3.     if (nai != null) {  
  4.         final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>();  
  5.         for (int i = 0; i < nai.networkRequests.size(); i++) {  
  6.             //当前网络断开,寻找可替代的网络连接  
  7.             NetworkRequest request = nai.networkRequests.valueAt(i);  
  8.             NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);  
  9.             if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {  
  10.                 mNetworkForRequestId.remove(request.requestId);  
  11.                 sendUpdatedScoreToFactories(request, 0);  
  12.                 NetworkAgentInfo alternative = null;  
  13.             }  
  14.         }  
  15.     }  
  16. }  
        private void handleAsyncChannelDisconnected(Message msg) {            NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);            if (nai != null) {                final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>();                for (int i = 0; i < nai.networkRequests.size(); i++) {                    //当前网络断开,寻找可替代的网络连接                    NetworkRequest request = nai.networkRequests.valueAt(i);                    NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);                    if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {                        mNetworkForRequestId.remove(request.requestId);                        sendUpdatedScoreToFactories(request, 0);                        NetworkAgentInfo alternative = null;                    }                }            }        }
        在这里,将会取出当前断开的网络所能处理的NetworkRequest,然后在当前所有向ConnectivityService注册的列表中查找可替代的连接,并通过sendUpdatedScoreToFactories()向其发起连接请求:
[java] view plain copy
print?
  1. private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {  
  2.     for (int i = 0; i < nai.networkRequests.size(); i++) {  
  3.         NetworkRequest nr = nai.networkRequests.valueAt(i);  
  4.         if (!isRequest(nr)) continue;  
  5.         sendUpdatedScoreToFactories(nr, nai.getCurrentScore());  
  6.     }  
  7. }  
        private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {            for (int i = 0; i < nai.networkRequests.size(); i++) {                NetworkRequest nr = nai.networkRequests.valueAt(i);                if (!isRequest(nr)) continue;                sendUpdatedScoreToFactories(nr, nai.getCurrentScore());            }        }
        继续:
[java] view plain copy
print?
  1. private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {  
  2.     for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {  
  3.         nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, networkRequest);  
  4.     }  
  5. }  
        private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {            for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {                nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, networkRequest);            }        }
        到这里将会向新的连接的NetworkFactoryInfo对象发起CMD_REQUEST_NETWORK的请求,之后相应的连接对象就可以建立连接了。
        至此,从一个连接类型遍转换到另一个连接类型中。
        以下是该过程的流程图:
        
0 0
原创粉丝点击