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

来源:互联网 发布:霍华德为什么废了知乎 编辑:程序博客网 时间:2024/06/06 20:22
在android上层应用中,有可以监听网络状态的listener功能,这个功能是监听网络的断开与变化事件的,前些日子花了些时间,研究了下这个事件的整体流程,希望通过这个机制的研究,能帮助以后增加其它事件监听。
我们先看下android的网络监听,它是用BroadcastReceiver来接收网络状态改变的广播的,具体实现如下:

 首先要定义一个新的BroadcastReceriver类,并且要重写自己的onrecerver()函数,以实现在监听到新的事件后,做什么样的响应
  1. public class ConnectionChangeReceiver extends BroadcastReceiver {  
  2.   
  3.     private static final String TAG =ConnectionChangeReceiver.class.getSimpleName();  
  4.       
  5.     @Override   
  6.     public void onReceive(Context context, Intent intent) {   
  7.     Log.e(TAG, "网络状态改变");   
  8.   
  9.     boolean success = false;   
  10.   
  11.     //获得网络连接服务    
  12.     ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);   
  13.     // State state = connManager.getActiveNetworkInfo().getState();    
  14.     // 获取WIFI网络连接状态   
  15.     State state = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();   
  16.     // 判断是否正在使用WIFI网络    
  17.     if (State.CONNECTED == state) {  
  18.     success = true;   
  19.     }   
  20.     // 获取GPRS网络连接状态    
  21.     state = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();  
  22.     // 判断是否正在使用GPRS网络    
  23.     if (State.CONNECTED != state) {   
  24.     success = true;   
  25.     }   
  26.   
  27.     if (!success) {   
  28.     Toast.makeText(context, context.getString(R.string.your_network_has_disconnected), Toast.LENGTH_LONG).show();   
  29.     }    
  30.     } 
然后再将新定义的类生成一个对象,并注册到管理系统中(activitymanagerservice):
  1. mNetworkStateReceiver   ConnectionChangeReceiver  ;
  2. IntentFilter filter = new IntentFilter();  
  3. filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 
  4. 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发送广播过程中的数据对象关联上了。
 
原创粉丝点击