本文主要是介绍Android Ethernet从上至下解析一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
http://www.2cto.com/kf/201508/438539.html
最近遇到不少框架问题,比如关于网口的,开机后拔掉有线网,状态栏和设置项中有线网显示图标不会更新,还有双网口的需求,下面就带着这个问题,以跟踪网络状态问题为引线,本篇将贯穿分析Ethernet从上至下的框架结构。因能力和时间有限,文中有分析不到位的地方,十分欢迎大侠们拍砖。
首先看下应用层网络监听相关的app 网络监听一:设置 packages/apps/Settings/src/com/android/settings/ethernet/EthernetEnabler.java
设置项网络按钮类定义
网络监听二:statusbar frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
NetworkController本身是个BroadcastReceiver,其中关于网络状态变化的监听消息为EthernetManager.NETWORK_STATE_CHANGED_ACTION,可以猜测这个消息是framework发出来的,往下看。
网络服务框架层 通过整理,网络框架管理器和服务相关代码和基本解释如下: frameworks/base/ethernet/java/com/android/internal/ethernet/
1 2 3 4 5 | EthernetStateMachine.java -> 网络状态机,用于管理网络状态变化及动作逻辑 EthernetManager.java -> 网络管理器,是app和EthernetService信息交互的桥梁 EthernetInfo.java -> 网络状态参数类,是Parcelable的一个实现 EthernetInfo.aidl -> aidl文件,Manager和service统一使用的数据结构 IEthernetManager.aidl -> aidl文件,用于Manager和service通信 |
在此可以发现网络状态机也在监听NETWORK_STATE_CHANGED_ACTION广播,广播发送者不再这里,那应该就是在service那了,继续往下。 frameworks/base/services/java/com/android/server/EthernetService.java
1 2 3 4 5 6 7 8 | private class InterfaceStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(EthernetManager.INTERFACE_STATE_CHANGED_ACTION)) { ... Intent newIntent = new Intent(EthernetManager.NETWORK_STATE_CHANGED_ACTION); newIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); newIntent.putExtra(EthernetManager.EXTRA_ETHERNET_INFO, ei); |
我们知道statemachine的特点是有一个rootstate,然后向下由多个state发展而成一个树状结构, state之间的转换会伴随着enter(),processMessage()等动作 。EthernetStateMachine的状态初始化如下:
1 2 3 4 5 6 | addState(mRootState); addState(mIdleState, mRootState); //addState(mObtainingLinkState, mRootState); addState(mObtainingIpState, mRootState); addState(mIPConnectedState, mRootState); addState(mDisconnectingState, mRootState); |
接着前面说到的INTERFACE_STATE_CHANGED_ACTION广播继续来看下状态机中的逻辑。 在ethernetstatemachine中, state状态的变化控制着网络状态的广播通知 ,部分代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private void sendInterfaceStateChangedBroadcast() { if (DBG) Slog.d(TAG, Sending INTERFACE_STATE_CHANGED_ACTION for + mEthernetInfo.getName()); Intent intent = new Intent(EthernetManager.INTERFACE_STATE_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(EthernetManager.EXTRA_ETHERNET_INFO, new EthernetInfo(mEthernetInfo)); mContext.sendBroadcast(intent); } private void setNetworkDetailedState(DetailedState state) { if (DBG) Slog.d(TAG, mEthernetInfo.getName() + setDetailed state, old = + mEthernetInfo.getDetailedState() + and new state= + state); if (state != mEthernetInfo.getDetailedState()) { mEthernetInfo.setDetailedState(state, null , null ); mEthernetInfo.setIsAvailable( true ); sendInterfaceStateChangedBroadcast(); } } void dhcpSuccess(DhcpResults dr) { if (DBG) Slog.d(TAG, mEthernetInfo.getName() + DHCP successful); LinkProperties lp = dr.linkProperties; ... setNetworkDetailedState(DetailedState.CONNECTED); } |
上面就是网络状态机的逻辑功能,而状态机的消息来源是service,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public void updateInterface(EthernetInfo newInfo) { if (newInfo == null ) { Slog.e(TAG, Null EthernetInfo); return ; } if (mAvailableInterface == null ) { Slog.e(TAG, Unable to find statemachine for interface + newInfo.getName()); return ; } sendMessage(mAvailableInterface, EthernetStateMachine.CMD_UPDATE_INTERFACE, newInfo); if (DBG) Slog.d(TAG, newInfo.getName() + updateInterface done); } |
我们可以这么理解:网络状态机是EthernetService的辅助逻辑处理单元,service通过给状态机发送消息并等待状态机处理结果,然后将结果发送给应用程序。这个就是网络部分framework层的大致逻辑,了解这个之后,我们继续分析service是从哪里取得网络状态消息的。 来看下EthernetService的构造函数:
1 2 3 4 5 6 7 8 9 10 11 | public EthernetService(Context context) { mContext = context; mNetd = INetworkManagementService.Stub.asInterface( ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE) ); try { mNetd.registerObserver( new NetworkManagementEventObserver()); } catch (RemoteException e) { Slog.e(TAG, Remote NetworkManagementService error: + e); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | private class NetworkManagementEventObserver extends INetworkManagementEventObserver.Stub { public void interfaceAdded(String iface) { if (DBG) Slog.d(TAG, interfaceAdded: + iface); addInterface(iface); } public void interfaceRemoved(String iface) { if (DBG) Slog.d(TAG, interfaceRemoved: + iface); removeInterface(iface); } public void limitReached(String limitName, String iface) {} public void interfaceClassDataActivityChanged(String label, boolean active) {} public void interfaceLinkStateChanged(String iface, boolean up) { if (DBG) Slog.d(TAG, interfaceLinkStateChanged for + iface + , up = + up); if (mAvailableInterface != null && up) { //sendMessage(mAvailableInterface, //EthernetStateMachine.CMD_LINK_UP); } } public void interfaceStatusChanged(String iface, boolean up) { if (DBG) Slog.d(TAG, interfaceStatusChanged for + iface + , up = + up); //addInterface(iface); } public void addressUpdated(String address, String iface, int flags, int scope) {} public void addressRemoved(String address, String iface, int flags, int scope) {} } |
1 2 3 4 5 6 7 | SystemServer.java try { Slog.i(TAG, NetworkManagement Service); networkManagement = NetworkManagementService.create(context); ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement); } catch (Throwable e) { reportWtf(starting NetworkManagement Service, e); } |
我们按照图示的最上层来看看NetworkManagementService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private static final String NETD_SOCKET_NAME = netd; private NetworkManagementService(Context context, String socket) { mContext = context; if (simulator.equals(SystemProperties.get(ro.product.device))) { return ; } mConnector = new NativeDaemonConnector( new NetdCallbackReceiver(), socket, 10 , NETD_TAG, 160 ); mThread = new Thread(mConnector, NETD_TAG); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor( this ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { @Override public void onDaemonConnected() { @Override public boolean onEvent( int code, String raw, String[] cooked) { switch (code) { case NetdResponseCode.InterfaceChange: } else if (cooked[ 2 ].equals(linkstate) && cooked.length == 5 ) { // 网络状态变化事件在这里回调处理 notifyInterfaceLinkStateChanged(cooked[ 3 ], cooked[ 4 ].equals(up)); return true ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * Notify our observers of an interface link state change * (typically, an Ethernet cable has been plugged-in or unplugged). */ private void notifyInterfaceLinkStateChanged(String iface, boolean up) { final int length = mObservers.beginBroadcast(); for ( int i = 0 ; i < length; i++) { try { mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up); } catch (RemoteException e) { } catch (RuntimeException e) { } } mObservers.finishBroadcast(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | @Override public void run() { mCallbackHandler = new Handler(FgThread.get().getLooper(), this ); while ( true ) { try { listenToSocket(); } catch (Exception e) { loge(Error in NativeDaemonConnector: + e); SystemClock.sleep( 5000 ); } } } private void listenToSocket() throws IOException { LocalSocket socket = null ; try { // 创建一个socket socket = new LocalSocket(); LocalSocketAddress address = determineSocketAddress(); socket.connect(address); // 从socket中获取流数据并处理 InputStream inputStream = socket.getInputStream(); synchronized (mDaemonLock) { mOutputStream = socket.getOutputStream(); } ... mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage( event.getCode(), event.getRawEvent())); // 收到流数据时,直接发给主线程,通过NetdCallbackReceiver 对象进行回调处理 @Override public boolean handleMessage(Message msg) { String event = (String) msg.obj; try { if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) { log(String.format(Unhandled event '%s' , event)); } } catch (Exception e) { loge(Error handling ' + event + ' : + e); } return true ; } private LocalSocketAddress determineSocketAddress() { // If we're testing, set up a socket in a namespace that's accessible to test code. // In order to ensure that unprivileged apps aren't able to impersonate native daemons on // production devices, even if said native daemons ill-advisedly pick a socket name that // starts with __test__, only allow this on debug builds. if (mSocket.startsWith(__test__) && Build.IS_DEBUGGABLE) { return new LocalSocketAddress(mSocket); } else { return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED); } } |
|->LocalSocketAddress.java |->LocalSocketImpl.java 这里重点看下LocalSocketImpl类,其中就可以看到大量的native函数了,也就是通过jni完成java到C++的交互,有些人可能会有疑问,既然这里使用jni调用了C++库函数,但是这里没有看到System.loadlibary字眼啊。通过jni的基础我们知道这里java类使用的jni名字应该是android_net_LocalSocket*样子的,那么在android工程代码中也确实存在这个名字的cpp文件,路径是frameworks/base/core/jni/。可以确认我们这里的java层就是调用这里的lib库了,而编译后我们知道这个库名为libandroid_runtime.so。那么这个库在哪里load的呢?下面简要提一下。 我们知道android启动时,第一个进程init在解析init.rc时创建了app_process,app_process在创建zygote进程前首先建立dalvikvm 虚拟机 环境,初始化android runtime,这里就在C环境下预先加载了libandroid_runtime.so库。如下: frameworks/base/core/jni/ Android Runtime.cpp
1 2 | static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_net_LocalSocketImpl), |
1 2 3 | connect() getInputStream() getOutputStream() |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ {getOption_native, (Ljava/io/FileDescriptor;I)I, ( void *)socket_getOption}, {setOption_native, (Ljava/io/FileDescriptor;III)V, ( void *)socket_setOption}, {connectLocal, (Ljava/io/FileDescriptor;Ljava/lang/String;I)V, ( void *)socket_connect_local}, {bindLocal, (Ljava/io/FileDescriptor;Ljava/lang/String;I)V, ( void *)socket_bind_local}, {listen_native, (Ljava/io/FileDescriptor;I)V, ( void *)socket_listen}, {accept, (Ljava/io/FileDescriptor;Landroid/net/LocalSocketImpl;)Ljava/io/FileDescriptor;, ( void *)socket_accept}, {shutdown, (Ljava/io/FileDescriptor;Z)V, ( void *)socket_shutdown}, {available_native, (Ljava/io/FileDescriptor;)I, ( void *) socket_available}, {pending_native, (Ljava/io/FileDescriptor;)I, ( void *) socket_pending}, {read_native, (Ljava/io/FileDescriptor;)I, ( void *) socket_read}, {readba_native, ([BIILjava/io/FileDescriptor;)I, ( void *) socket_readba}, {writeba_native, ([BIILjava/io/FileDescriptor;)V, ( void *) socket_writeba}, {write_native, (ILjava/io/FileDescriptor;)V, ( void *) socket_write}, {getPeerCredentials_native, (Ljava/io/FileDescriptor;)Landroid/net/Credentials;, ( void *) socket_get_peer_credentials} //,{getSockName_native, (Ljava/io/FileDescriptor;)Ljava/lang/String;, // (void *) socket_getSockName} }; int register_android_net_LocalSocketImpl(JNIEnv *env){} |
这篇关于Android Ethernet从上至下解析一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!