Framework中的连接管理机制
来源:互联网 发布:java管理系统有哪些 编辑:程序博客网 时间:2024/06/08 10:19
为了便于讨论,本文选取一个具体问题展开分析,那就是:当当前的网络连接变为不可用时,系统如何自动切换其他可用的网络连接的。
我们知道,当手机在使用移动数据上网时,如果进入WIFI环境,手机将会自动连上WIFI使用数据,而当WIFI失去覆盖或者关闭WIFI时,手机又会自动连上移动数据,那么这个机制是如何实现的呢?本文从WIFI框架触发,跟踪当WIFI被disconnect时,如何切换为数据网络。
一、WifiStateMachine更新状态
- 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.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() {}
- 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();
- }
- mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
更新完NetworkInfo之后,需要将其更新到ConnectivityManager才可被其他应用读取到,那么如何将其更新到ConnectivityManager呢?这就需要NetworkAgent来完成了。
三、NetworkAgent介绍
- "A Utility class for handling for communicating between bearer-specific code and ConnectivityService."
接下来我们通过代码来认识一下他究竟如何在网络连接与ConnectivityService之间进行通讯。
先来看一下这个类的定义:
- public abstract class NetworkAgent extends Handler {}
然后来看其构造方法:
- 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和ConnectivityService,然后再回头来看这里的registerNetworkAgent()方法。
四、ConnectivityService介绍
- @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介绍
- @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.java
- public ConnectivityManager(IConnectivityManager service) {
- mService = checkNotNull(service, "missing IConnectivityManager");
- }
好了,ConnectivityManager我们了解这么多就够了。下面继续我们NetworkAgent的初始化流程。
六、继续NetworkAgent初始化流程
现在我们继续NetworkAgent的初始化流程,这个流程中包含AsyncChannel的使用,不了解的同学可以在这里了解其使用方法和机制。
6.1、NetworkAgent向ConnectivityService注册过程
- 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);
- }
1、new Messenger(this)
2、new NetworkAgent(ni)
3、new NetworkCapabilities(nc)
需要注意的是,这里new出来的三个对象的来源,都应该是NetworkAgent子类被初始化时传递给构造方法的。
然后我们继续来看ConnectivityManager的registerNetworkAgent()方法。
- @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) { }
- }
- @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));
- }
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的处理:
- 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;
- }
- }
- }
- }
- 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);
- }
其实不难看出,这里的NetworkAgentInfo就是在registerNetworkAgent()中创建的,而dstMessenger自然就是NetworkAgent调用registerNetworkAgent()时传递进来的。
接下来,ConnectivityService将会利用获取到的NetworkAgent对象创建AsyncChannel双向通道。
6.2、ConnectivityService向NetworkAgent申请双向AsyncChannel过程
- @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);
- }
从AsyncChannel的机制我们知道,当利用其发起connect请求时,其将会触发单向连接过程,此时srcHandler(也就是mTrackerHandler)将会收到CMD_CHANNEL_HALF_CONNECTED的消息:
- private class NetworkStateTrackerHandler extends Handler {
- public void handleMessage(Message msg) {
- NetworkInfo info;
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
- handleAsyncChannelHalfConnect(msg);
- break;
- }
- }
- }
- }
- 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 {
- }
- }
- }
那么NetworkAgent究竟会如何处理该请求呢?
由于前面我们介绍过,NetworkAgent是抽象类,他需要在子类中被实例化,那么对于WIFI环境来说,他的子类就是在WifiStateMachine中的WifiNetworkAgent对象。
现在我们再回到WifiStateMachine中,我们可以看到,在L2ConnectedState状态机被初始化时将会创建WifiNetworkAgent对象:
- class L2ConnectedState extends State {
- @Override
- public void enter() {
- mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, mLinkProperties, 60);
- }
- }
- @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);
- }
- }
- }
- @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;
- }
- }
- }
经过以上过程,在ConnectivityService与WifiNetworkAgent之间就建立了双向的AsyncChannel通道。
以下是整个WifiNetworkAgent的初始化流程:
七、WIFI的断开过程
- 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.java
- public void sendNetworkInfo(NetworkInfo networkInfo) {
- queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
- }
- 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);
- }
- }
- }
此时我们应该能够想到,当初是ConnectivityService与WifiNetworkAgent创建了双向的AsyncChannel通道,那么此时的消息当然就会发送给ConnectivityService了,并且该消息将会在其NetworkStateTrackerHandler中被处理:
- @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;
- }
- }
- }
- }
- 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();
- }
- }
- private class NetworkStateTrackerHandler extends Handler {
- public void handleMessage(Message msg) {
- NetworkInfo info;
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
- handleAsyncChannelDisconnected(msg);
- break;
- }
- }
- }
- }
- 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;
- }
- }
- }
- }
- 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());
- }
- }
- private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, networkRequest);
- }
- }
至此,从一个连接类型遍转换到另一个连接类型中。
以下是该过程的流程图:
- Framework中的连接管理机制
- Framework中的连接管理机制
- Framework中的连接管理机制
- Framework中的连接管理机制
- Framework中的连接管理机制(原)
- Framework中的连接管理机制(转载)
- Framework中的连接管理机制(原)
- mongodb连接池管理机制
- Python中的内存管理机制
- Android中的内存管理机制
- ios中的内存管理机制
- iOS中的内存管理机制
- oc中的内存管理机制
- cocos2dx中的内存管理机制
- OC中的内存管理机制
- Android中的内存管理机制
- Android中的内存管理机制
- Android中的内存管理机制
- rand和srand的用法
- 高德地图marker事件监听-高德地图marker绑定事件就执行了[解决立即执行]
- 学习zero-shot learning中Xtest的分类去向的一点点小理解
- 分享若干种模态窗口的实现方法
- codeforce 777 C. Alyona and Spreadsheet (打表预处理)
- Framework中的连接管理机制
- Spring boot集成shiro使用Ajax方式,最详细教程
- shell脚本
- C++ 构造函数、赋值函数、析构函数、右值引用
- 网络编程复习(十):实践----数据通信
- Ubuntu14.04:安装JDK8
- Nginx源码剖析--ngx_cycle_s结构体分析
- GKObstacle
- rdd依赖关系、stage划分、stage任务执行揭秘