以太网在Android各种终端设备形态中是一个小众化的东西,通常出现在各种多媒体,机顶盒等特殊设备形态下,既然有需求,并且正好最近这阵子我也在调试以太网相关的东西,所以就分析分析以太网的框架结构。如果仅仅是添加以太网的相关功能,还是比较简单的,但是如果想真的搞懂以太网及其涉及到的Android网络框架还是比较复杂的。
本篇章演示的源码是在Android 7.1 msm8953平台上,其中涉及的源码路径如下所示:
frameworks/base/services/java/com/android/server/
---ConnectivityService.java
---INativeDaemonConnectorCallbacks.java
---NativeDaemonConnector.java
---NetworkManagementService.java
---SystemServer.java
---SystemServiceManager.java
frameworks/base/core/java/android/net/
---ConnectivityManager.java
---EthernetManager.java
---IConnectivityManager.aidl
---IEthernetManager.aidl
---LinkProperties.java
---NetworkPolicy.java
---NetworkAgent.java
---NetworkFactory.java
---NetworkInfo.java
---ProxyInfo.java
frameworks/opt/net/ethernet/java/com/android/server/ethernet/
---EthernetConfigStore.java
---EthernetNetworkFactory.java
---EthernetServiceImpl.java
---EthernetService.java
对于Android以太网框架情景分析这个篇章,我将会从三个维度来进行分析分别如下,本来是打算将以太网框架情景分析的放在一个篇章中,但是发现由于涉及的知识点太多了,真的搞不下,所以只能做成一个系列了。
我们已经从整体上概括了我们本篇章要讲解的维度了,我们先从整体流程图来看下这个三个维度,流程图如下所示:
整体的关系类图如下:
在正式开始分析以太网服务启动流程之前,我们得先储备一些基本的关于以太网以及Android Framework及Native层的网络框架知识点,这样才能做到磨刀不误砍柴工。
这四个服务涉及的内容非常多,这个不影响本篇的分析,这个会在后续有时间需要专门的篇章来分析,虽然整理了一些资料,并且详尽的分析了,但是总感觉还不到位,所以这个还需要时日。
ConnectivityService是系统网络连接管理服务,也是整个整个Android Framework层网络框架的核心类。主要处理APP网络监听和请求,通知网络变化;处理WiFi/Telephony/Ethernet等各个链路的网络注册,更新链路信息;网络检测/评分与网络选择。
NetworkPolicyManagerService是网络策略管理服务,这些策略一般指对APP的网络和限制和放行,通过netfilter来实现。
NetworkManagementService是网络管理服务。NetworkManagementService为ConnectivityService和其他Framework中的服务建立了与Netd之间通信的渠道,NetworkPolicyManagerService对各个UID的策略最终都会通过 NetworkManagementService向Netd发送;另外,NetworkManagementService还会监听Netd服务的状态,处理Socket返回的消息,如 Bandwidth/Iface/Route/Address/Dns Server等的变化,同时将这些变化通知“感兴趣”的模块。
这个服务主要收集网络数据,如各个Iface上下行网络流量的字节数等。APP或者其他服务可以通过该服务获取网络流量信息等。
Netd 负责Android网络的管理和控制。监听Kernel消息并通知NMPS;防火墙设置(Firewall);处理网络地址转换(NAT);进行网络共享配置(Tethering,如softap,usb网络共享)等。这个只先做简单介绍,后续会有专门章节讲解。
在前面的篇章中Android 9 §系统启动之SystemServer大揭秘(虽然Android的版本有所区别,但是其他其它服务的逻辑部分基本相同)中我们讲解了system_server进程在启动的过程中会在startOtherServices启动其它服务,这其中就包括了以太网(EthernetService)服务。下面我们就按照这个流程来一一介绍。
通过前面的分析我们知道EthernetService是在system_server进程的startOtherServices的方法中启动的,下面让我们看就着代码分析一下,源码的路径为frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer {
private static final String ETHERNET_SERVICE_CLASS =
"com.android.server.ethernet.EthernetService";
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
startOtherServices();
}
private void startOtherServices() {
//feather特性,这个通常定义在Android源码的frameworks/native/data/etc中
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
}
}
}
这里补充一点就是Android的feather特性通常定义在frameworks/native/data/etc中,这里不做过多的说明,可以参见博客Android Feature特性。这里借助SystemServiceManager的startService方法通过类名启动了EthernetService服务,关于SystemServiceManager在前面篇章的system_server进程启动的章节中有过介绍了,就不细说了。
该源码的路径为frameworks/base/services/java/com/android/server/EthernetService.java,其代码逻辑如下所示:
public final class EthernetService extends SystemService {
private static final String TAG = "EthernetService";
final EthernetServiceImpl mImpl;//这才是以太网真的核心服务,为应用层提供以太网服务能力
public EthernetService(Context context) {
super(context);
mImpl = new EthernetServiceImpl(context);
}
@Override
public void onStart() {//这个会在2.1章节的startService中调用到
Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
publishBinderService(Context.ETHERNET_SERVICE, mImpl);
}
@Override
public void onBootPhase(int phase) {//onBootPhase()可以在boot的各个阶段被调用。在EthernetService中,当系统处于PHASE_SYSTEM_SERVICES_READY阶段时,会调用EthernetServiceImpl.start()方法,做一些Ethernet的初始化工作
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.start();//启动EthernetServiceImpl服务
}
}
}
-在EthernetService的构造函数中创建一个EthernetServiceImpl对象,它是EthernetManager的Binde服务端。再调用EthernetService的onStart()方法后,会将该服务注册到ServiceManager中以供客户端使用。至此用户可以通过对外暴露的EthernetManager接口使用以太网相关的服务了,而这里的EthernetServiceImpl又像EthernetManager提供服务,并且最终EthernetServiceImpl又讲相关的事务委托给EthernetNetworkFactory来包揽所有的以太网网络管理操作。
-onBootPhase()可以在boot的各个阶段被调用。在EthernetService中,当系统处于PHASE_SYSTEM_SERVICES_READY阶段时,会调用EthernetServiceImpl.start()方法,做一些Ethernet的初始化工作,此处即启动EthernetServiceImpl服务
该源码的路径为frameworks/base/services/java/com/android/server/EthernetServiceImpl.java,其逻辑可以细分为两部分如下所示:
public class EthernetServiceImpl extends IEthernetManager.Stub {
//EthernetServiceImpl默认构造函数
public EthernetServiceImpl(Context context) {
mContext = context;
Log.i(TAG, "Creating EthernetConfigStore");
mEthernetConfigStore = new EthernetConfigStore();//以太网配置信息存储类
mIpConfiguration = mEthernetConfigStore.readIpAndProxyConfigurations();//从/misc/ethernet/ipconfig.txt读取以太网默认配置信息
Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration);
mTracker = new EthernetNetworkFactory(mListeners);//创建EthernetNetworkFactory以太网网络链接的管理类
}
}
该构造方法比较简单,其主要执行了如下逻辑:
创建EthernetConfigStore对象mEthernetConfigStore ,并调用其readIpAndProxyConfigurations方法从/misc/ethernet/ipconfig.txt读取以太网默认配置信息,譬如DNS,网管信息,代理信息等
创建EthernetNetworkFactoryEthernetNetworkFactory以太网网络链接的管理类对象mTracker,该对象在以太网服务中扮演着非常重要的角色。
public class EthernetServiceImpl extends IEthernetManager.Stub {
public void start() {
Log.i(TAG, "Starting Ethernet service");
HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");//创建HandlerThread对象
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
mTracker.start(mContext, mHandler);//将Handler对象通过start方法传入到EthernetNetworkFactory中
mStarted.set(true);
}
}
该方法比较简单,其主要执行了如下逻辑:
这里有一个知识点,就是假如想保存上次以太网的状态,即保存上次关机前以太网的开启或者关闭的状态,可以在start这里做一个判断(前提是每次开启和关闭以太网将状态持久化保存,可以使用persist属性),大致逻辑如下所示
public class EthernetServiceImpl extends IEthernetManager.Stub {
public void start() {
mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
mEnabled = getPersistedState();//获取持久化状态
Log.i(TAG, "Ethernet Persisted Enabled " + mEnabled);
setState(mEnabled);
}
//根据持久化状态,判断是否要开启以太网服务
public synchronized void setState(int state) {
enforceChangePermission();
Log.i(TAG, "setState from mState=" + mState + " to state=" + state);
if (mState != state) {
mState = state;
if (state == EthernetManager.ETHERNET_STATE_DISABLED) {
setPersistedState(EthernetManager.ETHERNET_STATE_DISABLED);
mTracker.stopInterface();
mStarted.set(false);
} else {
setPersistedState(EthernetManager.ETHERNET_STATE_ENABLED);
mTracker.stop();
mTracker.start(mContext, mHandler);
mStarted.set(true);
}
}
}
}
至此以太网服务已经在ServiceManager中注册成功了,用户可以通过EthernetManager来操作以太网相关的服务了。在后面的篇章中我们将会接着继续分析以太网的框架,希望大伙能感兴趣。关于后续EthernetNetworkFactory章节移步至博客Android以太网框架情景分析之EthernetNetworkFactory深入剖析。
本来打算是将所有的以太网的框架放在一个章节里面讲透彻,但是发现涉及的内容实在是太多了,所以决定做成一个系列的篇章,尽力的做到将每个知识点分析透彻。