您的位置:首页 > 理论基础 > 计算机网络

android网络监听事件机制(kernel, c++, java)

2013-10-21 10:17 211 查看
在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)

二,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);

connectivity = new ConnectivityService( context, networkManagement, networkStats, networkPolicy);

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);

}

}

}
从上面的处理函数可以看出,会循环调用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发送广播过程中的数据对象关联上了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: