阅读本文需要对Android系统的启动流程有一定的了解。如果读者还没有这方面的知识,建议大家先了解一下这方面的知识,鄙人后面也会专门做相关系列文章。这里先大概简单阐述一下(这里我们重点关注init以上的进程服务),方便阅读本文章。Android 在kernel内核启动后会加载启动Init进程,在Init进程中启动各种服务,包括显示系统的SurfaceFlinger,音频系统AudioFlinger,网络守护进程Netd等等,其中最重要一个进程是system_server进程,其是所有Framework层级系统服务的发动机。Init启动system_server后,会进入system_server的主方法,并且在主方法中调用startOtherService方法启动非关键的一些服务,而我们以太网服务就是从该方法启动。图1-1所示是以太网服务启动的整体流程。下面我们将具体分析各个服务的启动以及相互之间作用关系。
名称解释:
ENF:EthernetNetworkFactory;
ES:EthernetService
ESI:EthernetServiceImpl
CS:ConnectivityService
NMS:NetworkManagementService
NF:NetworkFactory
根据前面的分析及图1-1的流程图,我们知道EthernetService是在SystemServer的startOtherService的方法中启动,下面我们来具体分析一下启动流程。
//framework/base/services/java/com/android/server/SystemServer.java
public final class SystemServer {
private static final String ETHERNET_SERVICE_CLASS =
"com.android.server.ethernet.EthernetService";
//Init进程启动System_Server,进入SystemServer的主方法
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
startOtherService()
}
private void startOtherServices() {
//Feature特性,具体定义在Android源码的frameworks/native/data/etc/下
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
traceBeginAndSlog("StartEthernet");
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
traceEnd();
}
}
}
这里是通过SystemServiceManager的方式启动ES服务的,这里就不详细介绍。这里在启动ES的时候使用了Feature控制,具体定义在Android源码/frameworks/native/data/etc/下。
android.hardware.ethernet.xml
<permissions>
<feature name="android.hardware.ethernet" />
permissions>
在设备中的位置是在/vendor/etc/permissions/,该目录保存了大部分厂商的配置的文件:
130|DTEN_Mate:/ # ls -l ./vendor/etc/permissions/
total 80
-rw-r--r-- 1 root root 820 2009-01-01 08:00 android.hardware.bluetooth.xml
-rw-r--r-- 1 root root 830 2009-01-01 08:00 android.hardware.bluetooth_le.xml
-rw-r--r-- 1 root root 877 2009-01-01 08:00 android.hardware.camera.front.xml
-rw-r--r-- 1 root root 877 2009-01-01 08:00 android.hardware.camera.xml
-rw-r--r-- 1 root root 834 2009-01-01 08:00 android.hardware.ethernet.xml
-rw-r--r-- 1 root root 870 2009-01-01 08:00 android.hardware.opengles.aep.xml
-rw-r--r-- 1 root root 824 2009-01-01 08:00 android.hardware.sensor.accelerometer.xml
-rw-r--r-- 1 root root 1035 2009-01-01 08:00 android.hardware.touchscreen.multitouch.xml
-rw-r--r-- 1 root root 845 2009-01-01 08:00 android.hardware.usb.accessory.xml
-rw-r--r-- 1 root root 868 2009-01-01 08:00 android.hardware.usb.host.xml
-rw-r--r-- 1 root root 904 2009-01-01 08:00 android.hardware.vulkan.version.xml
-rw-r--r-- 1 root root 843 2009-01-01 08:00 android.hardware.wifi.direct.xml
-rw-r--r-- 1 root root 845 2009-01-01 08:00 android.hardware.wifi.passpoint.xml
-rw-r--r-- 1 root root 829 2009-01-01 08:00 android.hardware.wifi.xml
-rw-r--r-- 1 root root 747 2009-01-01 08:00 android.software.backup.xml
-rw-r--r-- 1 root root 875 2009-01-01 08:00 android.software.ipsec_tunnels.xml
-rw-r--r-- 1 root root 745 2009-01-01 08:00 android.software.midi.xml
-rw-r--r-- 1 root root 753 2009-01-01 08:00 android.software.verified_boot.xml
-rw-r--r-- 1 root root 1093 2009-01-01 08:00 sensor_feature.xml
-rw-r--r-- 1 root root 2555 2009-01-01 08:00 tablet_core_hardware.xml
设备在系统开机过程中会读取/vendor/etc/permissions/目录下对应的配置文件,然后在SystemServer中启动相关服务的时候会通过该配置文件进行匹配,依此来决定是否启动相关服务,正如我们ES一样。我们平时系统服务裁剪,就可以通过配置Feature的方式决定是否启动对应的服务。
下面我们具体看下ES的启动流程:
//frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetService.java
public final class EthernetService extends SystemService {
private static final String TAG = "EthernetService";
//这里是以太网服务的真正核心实现
final EthernetServiceImpl mImpl;
public EthernetService(Context context) {
super(context);
//初始化EthernetServiceImpl服务
mImpl = new EthernetServiceImpl(context);
}
@Override
public void onStart() {
Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
publishBinderService(Context.ETHERNET_SERVICE, mImpl);
}
@Override
public void onBootPhase(int phase) {
//在系统SYSTEM_SERVICES_READY阶段,调用EthernetServiceImpl服务的start方法
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.start();
}
}
}
ES服务并不复杂,真正起作用的是ESImpl服务。在EthernetService服务的构造方法中创建了ESI对象。该对象在ES的onStart方法中通过publishBinderService将其注册到SystemManager中以供客户端使用。至此用户就可以通过对外暴露接口来使用以太网的服务了。然后在系统SYSTEM_SERVICES_READY阶段,调用ESI服务的start方法进行初始化的工作。而ESImpl又委托给EthernetTracker来完成以太网的具体工作。
//frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImp.java
public class EthernetServiceImpl extends IEthernetManager.Stub {
private static final String TAG = "EthernetServiceImpl";
private EthernetTracker mTracker;
public void start() {
Log.i(TAG, "Starting Ethernet service");
HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
//创建EthernetTracker对象,注意此时的mHandler的looper,后面ENS和CS之间的通信会用的着
mTracker = new EthernetTracker(mContext, mHandler);
mTracker.start();
}
}
该构造方法比较简单,主要创建一个EthernetTracker这个对象。该类是以太网络连接的管理对象,Android 以太网框架源码分析启动篇正如中介绍一样,该对象在以太网服务中扮演着重要角色。EthernetTracker可以持有NMS对象mNMService,通过mNMService可以访问到Netd的接口。另外mFactory对象又可以和CS进行相互通信。因此,该对象是整个以太网的中枢所在。
//frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
final class EthernetTracker {
//NMS对象,通过该对象访问Netd的相关接口
private final INetworkManagementService mNMService;
private final Handler mHandler;
//主要更新网络连接状,链路配置,网络能力给ConnectivityService,同时接受来自ConnectivityService
//禁止自动连接,网络有效性等信息
private final EthernetNetworkFactory mFactory;
//存储以太网配置信息,
private final EthernetConfigStore mConfigStore;
EthernetTracker(Context context, Handler handler) {
// The services we use.
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNMService = INetworkManagementService.Stub.asInterface(b);
mFactory = new EthernetNetworkFactory(handler, context, nc);
//注册NetworkFactory到CS中,从而创建从CS到ENF(NF)的通道
mFactory.register();
mConfigStore = new EthernetConfigStore();
}
void start() {
try {
//注册InterfaceObserver,监听来自底层的状态更新,例如interface的创建与删除等
mNMService.registerObserver(new InterfaceObserver());
} catch (RemoteException e) {
Log.e(TAG, "Could not register InterfaceObserver " + e);
}
}
}
EthernetTracker的构造方法中也不是很复杂,主要完成以下五件事:
至此,ES服务就启动完成了, App层如果需要操作以太网,可以通过EthernetManger的Binder调用到ESI中,进而进入中枢枢纽EthernetTracker完成相关操作。下面我们重点看下ENF和CS的之间的双向通道的建立。
通过上一节我们知道ENF是通过register方法向CS中注册单向通道。这一节我们就从这个方法开始分析。注册目的是为了通信,通常的做法是通过注册到目的端,当目的端状态发生变化是回调相关的方法,从而同步到目的端的状态,这样就可以达到从目的端到源端的调用。
//frameworks/base/core/java/android/net/NetworkFactory.java
public class NetworkFactory extends Handler {
private AsyncChannel mAsyncChannel;
private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
public static final int CMD_REQUEST_NETWORK = BASE;
private final SparseArray<NetworkRequestInfo> mNetworkRequests =
new SparseArray<NetworkRequestInfo>();
public NetworkFactory(Looper looper, Context context, String logTag
NetworkCapabilities filter) {
super(looper);
mContext = context;
mCapabilityFilter = filter;
}
public void register() {
if (mMessenger == null) {
mMessenger = new Messenger(this);
//注意这里是Messenger不是Messege,最后将其注册到CS中
mSerialNumber = ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger,
LOG_TAG);
}
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
//在接收到来自CS的CMD_CHANNEL_FULL_CONNECTION消息后创建AsyncChnannel,并且发送
//CMD_CHANNEL_FULLY_CONNECTED消息给CS,这样就建立双向通道。
AsyncChannel ac = new AsyncChannel();
ac.connected(null, this, msg.replyTo);
ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_SUCCESSFUL);
mAsyncChannel = ac;
for (Message m : mPreConnectedQueue) {
ac.sendMessage(m);
}
break;
}
case CMD_REQUEST_NETWORK: {
//接收来自CS的CMD_REQUEST_NETWORK消息。
handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
break;
}
}
}
从NF的名称可以看出,该类是一个网络工厂类,所有注册的网络都会继承该类,例如WiFI/Phone,以及本文中的Ethernet。NF会将自己到CS中。这样每个注册的网络都可以和CS进行通信,方便CS统一管理网络状态。这里需要注意的是此处是Messenger不是Message,这里用到了Android中的AsyncChannel的机制,下面我们可以通过AsyncChannel创建单向和双向的通信通道。AsyncChannel还可以创建跨进程的双向通信,这里就不再详细阐述,感兴趣的读者可以查看相关文章。这里的Messenger对象是一个可以跨进程传递的实例对象,所以是可序列化的,主要为了AsyncChannel可以跨进程通信而设计的类,可以理解为对Handler的封装,而对应的looper是在ESI中创建传递的。
下面我们继续分析registerNetworkFactory方法,代码如下所示:
//framework/base/core/java/android/net/ConnectivityManager.java
public class ConnectivityManager {
public static ConnectivityManager from(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
}
//frameworks/base/services/core/java/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub
implements PendingIntent.OnFinished {
final private InternalHandler mHandler;
private static class NetworkFactoryInfo {
public final String name;//要注册的网络名称,例如Ethernet/wifi等
public final Messenger messenger;
public final AsyncChannel asyncChannel;
public final int factorySerialNumber;
NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
int factorySerialNumber) {
this.name = name;
this.messenger = messenger;
this.asyncChannel = asyncChannel;
this.factorySerialNumber = factorySerialNumber;
}
}
//注意此处的Messenger对象是NetworkFactory中传递过来的
public int registerNetworkFactory(Messenger messenger, String name) {
NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
NetworkFactory.SerialNumber.nextSerialNumber());
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
return nfi.factorySerialNumber;
}
}
这里NetworkFactoryInfo是CS的一个内部类,主要用户封装一些信息,例如要注册的网络名称,以及要传递的Messenger,以及AysncChannel对象。
下面通过Handler发送一个EVENT_REGISTER_NETWORK_FACTORY消息,并且携带NetworkFactoryInfo对象。这里的Handler是CS的一个内部类InternelHandler的一个实例对象,其继承自Handler,具有处理消息的能力。下面我们直捣黄龙看下EVENT_REGISTER_NETWORK_FACTORY这个事件的处理。
//ConnectivityService.java
private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos = new HashMap<>();
private class InternalHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_REGISTER_NETWORK_FACTORY: {
handleRegisterNetworkFactory((Messenger)msg.obj);
break;
}
}
}
}
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
mNetworkFactoryInfos.put(nfi.messenger, nfi);
nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
}
这里的mNetworkFactoryInfos是一个HashMap对象,key为前面NetworkFactoryInfo的messenger对象,value为NetworkFactoryInfo。此处将NetworkFactoryInfo添加到mNetworkFactoryInfos中,接着调用NetworkFactoryInfo的实例asynChannel对象的connect方法来创建连接。AsyncChannel其实是Goolge专门为Android开发的通信通道,可以在同进程内传递数据,也可以在不同进程中传递数据。下面我们简单看下起连接过程。
//frameworks/base/core/java/com/android/internal/util/AsyncChannel.java
public class AsyncChannel {
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
//初始化AsyncChannel中的一些变量,包括mSrcHandler和mSrcMessenger
connected(srcContext, srcHandler, dstMessenger);
//先创建单向连接,单向连接成功后,在创建双向连接。
replyHalfConnected(STATUS_SUCCESSFUL);
}
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(mSrcHandler);
// Initialize destination fields
mDstMessenger = dstMessenger;
}
private void replyHalfConnected(int status) {
Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
msg.arg1 = status;
msg.obj = this;
msg.replyTo = mDstMessenger;
if (!linkToDeathMonitor()) {
// Override status to indicate failure
msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
}
mSrcHandler.sendMessage(msg);
}
}
通过对上面connect的流程的分析,我们可以得出以下结论:
//ConnectivityService.java
private class NetworkStateTrackerHandler extends Handler {
private boolean maybeHandleAsyncChannelMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
handleAsyncChannelHalfConnect(msg);
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
if (nai != null) nai.asyncChannel.disconnect();
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
handleAsyncChannelDisconnected(msg);
break;
}
}
}
private void handleAsyncChannelHalfConnect(Message msg) {
AsyncChannel ac = (AsyncChannel) msg.obj;
mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, serial,
nri.request);
}
这里NetworkStateTrackerHandler处理很简单,在接收到CMD_CHANNEL_HALF_CONNECTED消息后,直接调用handleAsyncChannelHalfConnect处理,然后通过AsyncChannel对象ac的mDstMessenger发送CMD_CHANNEL_FULL_CONNECTION消息,创建双向通信通道。最后发送CMD_REQUEST_NETWORK消息创建网络。我们先看CMD_CHANNEL_FULL_CONNECTION消息的处理,此处的mDstMessenger指向的是NF的Messenge中。具体如下:
//NetworkFactory.java
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
//在接收到来自CS的CMD_CHANNEL_FULL_CONNECTION消息后创建AsyncChnannel,并且发送
//CMD_CHANNEL_FULLY_CONNECTED消息给CS,这样就建立双向通道。
AsyncChannel ac = new AsyncChannel();
ac.connected(null, this, msg.replyTo);
ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_SUCCESSFUL);
mAsyncChannel = ac;
for (Message m : mPreConnectedQueue) {
ac.sendMessage(m);
}
break;
}
NF在接收来自CS的CMD_CHANNEL_FULL_CONNECTION消息后,先创建一个AsyncChannel对象,然后发送CMD_CHANNEL_FULLY_CONNECTED消息。registerNetworkFactory将NF注册到CS的流程就结束了,至此CS可以向NF传递网络连接状态等信息。其实此时已经建立了双向通道,即NF也是可以通过mAsyncChannel对象向CS发送消息的。只不过ENF没有使用mAsyncChannel这个对象,而是使用了一个新的类NetworkAgent,该类内部也有个AsyncChannel的实例对象mAsyncChannel,可以通过对象向CS发送消息。
在分析ENF与CS的注册流程之前,先看下上一节在NetworkStateTrackerHandler中发送完CMD_CHANNEL_FULL_CONNECTION这个消息后,又发送了CMD_REQUEST_NETWORK消息来Request网络,而处理该消息的地方是在NF的handleMessage方法中:
//NetworkFactory.java
case CMD_REQUEST_NETWORK: {
//接收来自CS的CMD_REQUEST_NETWORK消息。
handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
break;
}
这里处理很简单,直接调用handleAddRequest,这里需要注意的是NetworkRequest类,该类是一个网络请求的封装类,其中包括网络能力,网络请求id以及网络类型等:
public class NetworkRequest implements Parcelable {
public final @NonNull NetworkCapabilities networkCapabilities;
public final int requestId;
public final Type type;
public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) {
if (nc == null) {
throw new NullPointerException();
}
requestId = rId;
networkCapabilities = nc;
this.legacyType = legacyType;
this.type = type;
}
/**
* @hide
*/
public NetworkRequest(NetworkRequest that) {
networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
requestId = that.requestId;
this.legacyType = that.legacyType;
this.type = that.type;
}
}
我们回到上面,直接看NF中handleAddRequest方法,具体代码如下:
protected void handleAddRequest(NetworkRequest request, int score,
int servingFactorySerialNumber) {
//创建NetworkRequestInfo对象,并将其保存到mNetworkRequests中
NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
if (n == null) {
n = new NetworkRequestInfo(request, score, servingFactorySerialNumber);
mNetworkRequests.put(n.request.requestId, n);
} else {
n.score = score;
n.factorySerialNumber = servingFactorySerialNumber;
}
//调用该方法继续请求网络
evalRequest(n);
}
这里主要完成以下几件事:
//NetFactory.java
private void evalRequest(NetworkRequestInfo n) {
//判断是否需要启动该网络
if (shouldNeedNetworkFor(n)) {
//如果满足条件,则使能该网络,否则释放该网络
needNetworkFor(n.request, n.score);
n.requested = true;
} else if (shouldReleaseNetworkFor(n)) {
releaseNetworkFor(n.request);
n.requested = false;
} else {
if (VDBG) log(" done");
}
}
private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
return !n.requested //如果该网络已经请求,则不作处理
//如果该注册网络的score小于NF的mScore,说明该网络优先级最高
&& (n.score < mScore || n.factorySerialNumber == mSerialNumber)
//如果该注册网络不满足网络能了,也不作处理
&& n.request.networkCapabilities.satisfiedByNetworkCapabilities(mCapabilityFilter)
// 判断该注册网络的底层interface正常
&& acceptRequest(n.request, n.score);
}
private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
return n.requested //如果网络已经注册过,并且:
//如果该注册网络得分大于NF的mScore,说明该网络不是最高优先级,所以需要释放该网络;
//如果该注册注册网络能力不满足网络能力,则释放该网络;
//如果该注册网络的底层interface异常,则释放该网络
&& ((n.score > mScore && n.factorySerialNumber != mSerialNumber)
|| !n.request.networkCapabilities.satisfiedByNetworkCapabilities(
mCapabilityFilter)
|| !acceptRequest(n.request, n.score));
}
这里是整个网络注册系统的关键,其逻辑可以分为两条线:
如果NetworkRequestInfo满足网络使能的条件,则调用needNetworkFor使能该网络,且将NetworkRequestInfo.requested 设置为true。该注册网络使能的条件如下:
如果NetworkRequestInfo满足网络释放的条件,则调用needNetworkFor释放该网络,且将NetworkRequestInfo.requested 设置为false。该注册网络释放的条件如下:
此处ethernet初始化来看,NetworkRequestInfo是新创建的,因此此处requested为false,且此时mScore传入70,而CMD_REQUEST_NETWORK传入的是0, 所以满足网络使能条件,则会调用needNetworkFor方法,而该方法在ENF中实现的。
protected void needNetworkFor(NetworkRequest networkRequest, int score) {
NetworkInterfaceState network = networkForRequest(networkRequest);
if (++network.refCount == 1) {
network.start();
}
}
这里需要注意NetworkInterfaceState这个对象,该类是ENF的内部类,其是ENF向CS传递网络状态,链路配置等信息的核心,其中属性变量NetworkAgent是CS和ENF建立通道的关键。
private static class NetworkInterfaceState {
final String name; //注册网络名称,ethernet/wifi
private final String mHwAddress;//硬件mac地址
private final NetworkCapabilities mCapabilities; //网络能力
private final Handler mHandler;
private final Context mContext;
private final NetworkInfo mNetworkInfo; //网络状态信息
private boolean mLinkUp; //链路信息
private LinkProperties mLinkProperties = new LinkProperties();
private volatile IIpClient mIpClient;//静态IP相关配置
private IpClientCallbacksImpl mIpClientCallback;
private NetworkAgent mNetworkAgent;
private IpConfiguration mIpConfig;
private void start() {
mIpClientCallback = new IpClientCallbacksImpl();
//创建IpClient的回调
IpClientUtil.makeIpClient(mContext, name, mIpClientCallback);
....
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (mIpClient != null) {
//处理静态Ip相关请求
provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
}
}
}, 1000);
}
private class IpClientCallbacksImpl extends IpClientCallbacks {
public void onProvisioningSuccess(LinkProperties newLp) {
mHandler.post(() -> onIpLayerStarted(newLp));
}
}
NetworkInterfaceState的start中注册了IpClientCallbacksImpl的callback,当Ip设置成功后会回调到IpClientCallbacksImpl的onIpLayerStarted方法,并且在改方法中初始化mNetworkAgent变量。
//EthernetNetworkFactory.java
mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext,
NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties,
getNetworkScore(){});
至此我们分析到本节的核心NetworkAgent,我们直接看其初始化:
//frameworks/base/core/java/android/net/NetworkAgent.java
public abstract class NetworkAgent extends Handler {
private volatile AsyncChannel mAsyncChannel;
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc,
int factorySerialNumber) {
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc,
factorySerialNumber);
}
}
这里创建CS的Binder引用对象,并且调用registerNetworkAgent方法注册到CS中,在CS的方法中最后调用handleRegisterNetworkAgent方法进行处理,我们直捣黄龙看下这个方法
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
nai.onNetworkMonitorCreated(networkMonitor);
mNetworkAgentInfos.put(nai.messenger, nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.put(nai.network.netId, nai);
}
try {
networkMonitor.start();
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
NetworkInfo networkInfo = nai.networkInfo;
nai.networkInfo = null;
updateNetworkInfo(nai, networkInfo);
updateUids(nai, null, nai.networkCapabilities);
}
这里的NetworkAgentInfo对象和NetworkFactoryInfoy一样,封装了需要ENF传递给CS的信息对象,包括网络状态,链路管理,网络得分等等,最后调用NetworkAgentInfo的connect建立ENF到CS的通信,这个AsyncChannel的connect原理和CS到NF一样,此处就不再分析,CS的接收端是NetworkAgentInfo的Handler中处理。
至此CS与NF以及ENF与CS之间都建立了双向通道,路已经铺好,就差使用了。
NMS的启动ES类似,我们重点关注其构造方法,
public class NetworkManagementService extends INetworkManagementService.Stub {
static NetworkManagementService create(Context context, SystemServices services)
throws InterruptedException {
final NetworkManagementService service =
new NetworkManagementService(context, services);
service.connectNativeNetdService();
return service;
}
private NetworkManagementService(
Context context, SystemServices services) {
mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
synchronized (mTetheringStatsProviders) {
mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
}
}
}
其构造方法主要做了以下几件事:
至此,我们以太网服务的启动流程就分析了,其中ENF和CS之间的通双向通信比较复杂,不过理解了AsyncChanel的工作原理后,就不会那么吃力了,尽情启动下一篇应用层使能ethernet功能源码流程分析。今天先打完收工。