在android上层应用中,有可以监听网络状态的listener功能,这个功能是监听网络的断开与变化事件的,前些日子花了些时间,研究了下这个事件的整体流程,希望通过这个机制的研究,能帮助以后增加其它事件监听。
我们先看下android的网络监听,它是用BroadcastReceiver来接收网络状态改变的广播的,具体实现如下:
首先要定义一个新的BroadcastReceriver类,并且要重写自己的onrecerver()函数,以实现在监听到新的事件后,做什么样的响应
- public class ConnectionChangeReceiver extends BroadcastReceiver {
- private static final String TAG =ConnectionChangeReceiver.class.getSimpleName();
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.e(TAG, "网络状态改变");
- boolean success = false;
- //获得网络连接服务
- ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- // State state = connManager.getActiveNetworkInfo().getState();
- // 获取WIFI网络连接状态
- State state = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
- // 判断是否正在使用WIFI网络
- if (State.CONNECTED == state) {
- success = true;
- }
- // 获取GPRS网络连接状态
- state = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
- // 判断是否正在使用GPRS网络
- if (State.CONNECTED != state) {
- success = true;
- }
- if (!success) {
- Toast.makeText(context, context.getString(R.string.your_network_has_disconnected), Toast.LENGTH_LONG).show();
- }
- }
然后再将新定义的类生成一个对象,并注册到管理系统中(activitymanagerservice):
- mNetworkStateReceiver ConnectionChangeReceiver ;
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- registerReceiver(mNetworkStateReceiver, filter);
以上就算是完整的初始化一个网络监听对象,一旦有新的网络事件(插拨,变化)过来,就是运行onReceive里面的代码。
从android系统中,整个监听机制涉及到kernel, framework, application,下面我将分别从各层次进行分析。
我们的项目T082所使用的平台是samsung C110, android系统为4.0.3版本,kernel为3.0版本。
一, kernel
在kernel中,大部分事件都是由硬件产生中断,通过kobject_uevent_env(kobj, KOBJ_CHANGE, envp);将envp里面的字符串事件发出去,实际上是通过NETLINK类的SOCKET发到上层;
NETLINK的SOCKET的创建过程:kobject_uevent.c:uevent_net_init(struct net *net)--〉Af_netlink.c:netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
1, NULL, NULL, THIS_MODULE);--〉sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)
1, NULL, NULL, THIS_MODULE);--〉sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)
二,Framework之C++部分
第一部分是C++,netd服务,涉及的代码文件有:system/netd下的所有文件和system/core/libsysutils/src下面的所有文件。
main.c:main()--->nm = NetlinkManager::Instance()-->nm->start()--->
setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)---->*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)创建NETLINK类的SOCKET与KERNEL层创建的SOCKET进行对接;
然后 NetlinkManager.cpp:NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);根据已创建的SOCKET来创建处理模块,同时由于NetlinkHandler继承NetlinkListener继承SocketListener,也就是同时将NetlinkListener和SocketListener初始化了;
然后NetlinkManager.cpp:handler->start()-->SocketListener.cpp:startListener()--->pthread_create(&mThread, NULL, SocketListener::threadStart, this)---->runListener()循环监听事件,当有事件时,NetlinkListener.cpp:onDataAvailable(SocketClient *c)-->uevent_kernel_multicast_recv(socket, mBuffer, sizeof(mBuffer))从kernel中获取事件内容, 然后NetlinkEvent *evt = new NetlinkEvent()新建一个事件封装对象,evt->decode(mBuffer, count, mFormat)根据内容进行封装,然后NetlinkHandler::onEvent(NetlinkEvent *evt)进行处理,根据内容调用相应处理函数广播出去mNm->getBroadcaster()->sendBroadcast(ResponseCode::InterfaceChange,msg, false);
这里sendBroadcast()的对象实际上就是NetlinkManager::mBroadcaster, 下面看看这个mBroadcaster是在哪初始化的。mani.c:main()--->cl = new CommandListener();-->FrameworkListener("netd")-->SocketListener(socketName, true), 由于继承关系,最后返回的cl其实也就是一个SocketListener对象;
接着在new CommandListener();下面nm->setBroadcaster((SocketListener *) cl);就是将cl赋值给mBroadcaster;
cl->startListener()---->SocketListener::startListener()从系统环境变化中获取相应的监听SOCKET, SocketListener::threadStart()--->runListener()--->开始循环监听注册过来的客户端,当有新的客户端连接会放到SocketClient队列里,如果有命令消息则处理并通知底层,FrameworkListener::onDataAvailable(SocketClient *c)--->read(c->getSocket(), buffer, sizeof(buffer))---->dispatchCommand()---->调用相应的命令处理对象c->runCommand(cli, argc, argv)进行处理,这些对象是在构造CommandListener对象时初始化的。
三,Framework之JAVA部分
对于Framework 的JAVA部分,共涉及到三个服务,NetworkManagementService、ConnectivityService和ActivityManagerService,且这三个服务都是在systemserver.java中启动的,
networkManagement = NetworkManagementService.create(context);
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
connectivity = new ConnectivityService( context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
context = ActivityManagerService.main(factoryTest); //这个context是关联其它service的桥
ActivityManagerService.self().systemReady()正式启动相关服务进程
下面首先介绍下
NetworkManagementService, 在这个服务里面,
mConnector是关键对象,全靠它来获取C++层netd服务传上来的事件,
mConnector = new NativeDaemonConnector( new NetdCallbackReceiver(), "netd", 10, NETD_TAG);将监听SOCKET的对象名传进去,以进行后面创建SOCKET连接netd获取事件;
NetworkManagementService:create()--->mThread.start(),由于mThread = new Thread(mConnector, NETD_TAG);实际上也就是调用
mConnector.run()---->listenToSocket();创建SOCKET连接到netd服务,当有事件过来时,会调用
mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(code, event));将事件发送到
mConnector所在的Handle(也是LOOPER)消息队列中,而这个Handle会调用handleMessage()处理队列中的消息,也就是调用
mConnector.
handleMessage()--->mCallbacks.onEvent(msg.what, event, event.split(" ")),而
mCallbacks实际上就是
NativeDaemonConnector构造时传进来的
new NetdCallbackReceiver()(这个类的定义在
NetworkManagementService.java中,属于内部类
),所是实际上就是调用
NetdCallbackReceiver.
onEvent(),根据接收到的消息不同,调用不同处理函数,如下是增加网络接口时的处理函数:
private void notifyInterfaceAdded(String iface) {
for (INetworkManagementEventObserver obs : mObservers) {
try {
obs.interfaceAdded(iface);
} catch (Exception ex) {
Slog.w(TAG, "Observer notifier failed", ex);
}
}
}
for (INetworkManagementEventObserver obs : mObservers) {
try {
obs.interfaceAdded(iface);
} catch (Exception ex) {
Slog.w(TAG, "Observer notifier failed", ex);
}
}
}
从上面的处理函数可以看出,会循环调用
INetworkManagementEventObserver对象的相应处理函数,而这些对象是通过NetworkManagementService.registerObserver()注册进来的,接下来我们再看看注册过程:
public class NetworkManagementService extends INetworkManagementService.Stub,可见
NetworkManagementService继承了一个Binder的句柄
,可以通过
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);获取
NetworkManagementService的Binder句柄,这样,远程端就可以使用service来操作
NetworkManagementService了;
关于
NetworkManagementService模块结构基本上就是这个过程;
下面接着介绍下ConnectivityService, 其实上面的NetworkManagementService就是在这个服务里远程调用的。
public class ConnectivityService extends IConnectivityManager.Stub,同样可以看出,ConnectivityService对象也可以被其它服务远程调用;
在构造ConnectivityService时,会创建handlerThread = new HandlerThread()和mHandler = new MyHandler()对象,它们关联着同一MessageQueue;根据系统的config.xml配置信息,如果有以太网信息,则:mNetTrackers[netType] = EthernetDataTracker.getInstance(); mNetTrackers[netType].startMonitoring(context, mHandler); 在调用EthernetDataTracker.startMonitoring()时,首先会先关联上mHandler,实际上主要为了关联上MessageQueue,接着会IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);获取上面NetworkManagementService的操作binder句柄,同时mInterfaceObserver = new InterfaceObserver(this);service.registerObserver(mInterfaceObserver);将mInterfaceObserver注册到前面的NetworkManagementService里面去,到这里,也就是将NetworkManagementService与ConnecttivityService联系上了;
下面我们再看看private static class InterfaceObserver extends INetworkManagementEventObserver.Stub,它是EthernetDataTracker的内部类,可以看出,它也继承了一个binder句柄,也就是说也可以被别人远程调用,其实回去看看NetworkManagementService,也就明白了,这个句柄是被注册到NetworkManagementService中的mObservers,所以当NetworkManagementService接收到接口增加的事件后,会调用mObservers.interfaceAdded()----->InterfaceObserver.interfaceAdded()--->EthernetDataTracker.interfaceAdded()--->Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); msg.sendToTarget();也就是将事件信息装载到mCsHandler.MassageQueue==ConnectivityService.mHandler.MassageQueue中了,到这里,事件消息的接收基本完成;
下面是处理消息的过程,由于ConnectivityService的Handle处在一个looper中,当有事件消息时,Looper.loop()--->Message msg = queue.next();--->msg.target.dispatchMessage(msg);--->Handle.dispatchMessage()--->ConnectivityService.MyHandler.handleMessage(msg);这样,消息就到了真正进行处理的地方了。
如果是网络增加事件,则else if (state == NetworkInfo.State.CONNECTED) {handleConnect(info);}--->sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());--->sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);--->sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);---->sendStickyBroadcast(intent);--->mContext.sendStickyBroadcast(intent);===ContextImpl.sendStickyBroadcast(Intent intent)--->
ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, true);===(new Singleton<IActivityManager>()).broadcastIntent()===
IActivityManager.broadcastIntent()===(class ActivityManagerProxy implements IActivityManager)ActivityManagerProxy.broadcastIntent()--------
---BINDER--
----->ActivityManagerNative.onTransact(BROADCAST_INTENT_TRANSACTION)--->broadcastIntent()接下来就是看是谁来继承ActivityManagerNative了,继承它的对象中必然有broadcastIntent()函数,前面的调用其实就是通过binder直接调用派生类的broadcastIntent();
下面介绍ActivityManagerService,从它的类定义
public final class ActivityManagerService extends ActivityManagerNative,可以看出,它是ActivityManagerNative的派生类,自然上一部分的BINDER通信就是和这个模块了。
ContextImpl.sendStickyBroadcast(Intent intent)--
BINDER
->
ActivityManagerServic.broadcastIntent()--->
ActivityManagerServic.
broadcastIntentLocked()在这里,先做一系列的处理,然后从已经注册的mReceiverResolver中找出对应的registeredReceivers,根据
registeredReceivers
生成BroadcastRecord r = new BroadcastRecord(
registeredReceivers,....
),接着把r加入到mParallelBroadcasts.add(r)或者mOrderedBroadcasts.add(r),然后scheduleBroadcastsLocked();--->mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);同时将mBroadcastsScheduled = true;
接着在运行
ActivityManagerService的looper循环中的handleMessage(),case BROADCAST_INTENT_MSG:--->processNextBroadcast(true);--->循环找出所有的
mParallelBroadcasts 成员进行
deliverToRegisteredReceiverLocked()---->performReceiveLocked()----->app.thread.scheduleRegisteredReceiver()进行到这里,就关系到所有注册的application了;
四,Application
下面我们看下应用程序注册过程:
从上面的例子可以看出,app在注册广播的时候,会调用
registerReceiver(mNetworkStateReceiver, filter); 其实因为应用程序在构造类的时候,会继承Activity类,
而public class Activity extends ContextThemeWrapper----->
public class ContextThemeWrapper extends ContextWrapper----->
public class ContextWrapper extends Context
所以从上面的继承关系可以看出,其实就是调用
ContextWrapper .
registerReceiver()---->mBase.registerReceiver()---->
ContextImpl .
registerReceiver()---->
ContextImpl .
registerReceiverInternal()这里会 rd = new LoadedApk.ReceiverDispatcher对象,这个对象其实包含Ibinder句柄,它会以参数的形式传递给
ActivityManagerService,以备后面接收
ActivityManagerService的通知;然后ActivityManagerNative.getDefault().registerReceiver()====ActivityManagerProxy.
registerReceiver()---->mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);---->ActivityManagerNative.case REGISTER_RECEIVER_TRANSACTION:----->(由前面可以知道
ActivityManagerService是继承
ActivityManagerNative的
)
ActivityManagerService.
registerReceiver()将收到的注册信息mRegisteredReceivers.put(receiver.asBinder(), rl);和mReceiverResolver.addFilter(bf);中,这样就可以和前面的
ActivityManagerService发送广播过程中的数据对象关联上了。
![](https://img-my.csdn.net/uploads/201210/15/1350267553_9985.jpg)