概要
android中以太網(wǎng)常被用作共享網(wǎng)絡(luò),或者是定制化設(shè)備連接網(wǎng)線的需求。
本章將會詳細(xì)分析該模塊對以太網(wǎng)的邏輯實現(xiàn),是大家對此有更深入認(rèn)識。
整體架構(gòu)流程
初始化
Systemserver
在安卓系統(tǒng)中有一個關(guān)于以太網(wǎng)的服務(wù),在systemserver中啟動 frameworks/base/services/java/com/android/server/SystemServer.java
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
t.traceBegin("StartEthernet");
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
t.traceEnd();
}
EthernetService
這個EthernetService類的內(nèi)容很少,重點主要看他這里初始化了EthernetServiceImpl這個類然后調(diào)用其start方法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);
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) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.start();
}
}
}
EthernetServiceImpl
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
public class EthernetServiceImpl extends IEthernetManager.Stub {
首先可以看出他繼承了IEthernetManager接口,應(yīng)該是系統(tǒng)api的服務(wù)實現(xiàn)類
繼續(xù)看他的start方法
創(chuàng)建了一個handler但也只是作為入?yún)魅氲紼thernetTracker構(gòu)造中,之后在啟動EthernetTracker這個類
猜測EthernetTracker還有更重要的地方,繼續(xù)追蹤其啟動
public void start() {
Log.i(TAG, "Starting Ethernet service");
HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
mTracker = new EthernetTracker(mContext, mHandler);
mTracker.start();
mStarted.set(true);
}
EthernetTracker
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
構(gòu)造方法
EthernetTracker(Context context, Handler handler) {
mContext = context;
mHandler = handler;
// The services we use.
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); //獲取了網(wǎng)絡(luò)管理的服務(wù),這個服務(wù)是直接和netd進(jìn)行交互的
mNMService = INetworkManagementService.Stub.asInterface(b);
// Interface match regex.
updateIfaceMatchRegexp(); //更新以太網(wǎng)卡篩選規(guī)則,通常是‘eth\\d’
// Read default Ethernet interface configuration from resources
final String[] interfaceConfigs = context.getResources().getStringArray(
com.android.internal.R.array.config_ethernet_interfaces);
for (String strConfig : interfaceConfigs) {
parseEthernetConfig(strConfig);//從資源文件中獲取并解析默認(rèn)的以太網(wǎng)絡(luò)配置 (1)
}
mConfigStore = new EthernetConfigStore();//初始化網(wǎng)絡(luò)配置類
NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */);//(2)
mFactory = new EthernetNetworkFactory(handler, context, nc);
mFactory.register();//(3)重點是這個mFactory,我們后續(xù)講道,知道是在這里初始化的
}
parseEthernetConfig的這個解析系統(tǒng)的xml文件,然后讀到該類的對象數(shù)組中,具體格式如下
<string-array translatable="false" name="config_ethernet_interfaces">
<item>eth1;12,13,14,15;ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8</item>
<item>eth2;;ip=192.168.0.11/24</item>
<item>eth3;12,13,14,15;ip=192.168.0.12/24;1</item>
</string-array>
createNetworkCapabilities是分析網(wǎng)絡(luò)功能的靜態(tài)列表作用,傳入?yún)?shù)true代表清除緩存
該方法作用主要是指定當(dāng)前網(wǎng)絡(luò)的一個能力和一些相關(guān)參數(shù)的初始化
start方法
void start() {
mConfigStore.read();
// Default interface is just the first one we want to track.
mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface();
final ArrayMap<String, IpConfiguration> configs = mConfigStore.getIpConfigurations();
for (int i = 0; i < configs.size(); i++) {
mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i));
}
try {
mNMService.registerObserver(new InterfaceObserver());
} catch (RemoteException e) {
Log.e(TAG, "Could not register InterfaceObserver " + e);
}
mHandler.post(this::trackAvailableInterfaces);
}
mConfigStore會去讀/misc/ethernet/ipconfig.txt這個下面的網(wǎng)絡(luò)配置,如果用戶沒有指定,那這塊就為空
registerObserver(new InterfaceObserver())主要是監(jiān)聽down up remove add這幾個狀態(tài)然后做對應(yīng)的處理
private class InterfaceObserver extends BaseNetworkObserver {
@Override
public void interfaceLinkStateChanged(String iface, boolean up) {
if (DBG) {
Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
}
mHandler.post(() -> updateInterfaceState(iface, up));
}
@Override
public void interfaceAdded(String iface) {
mHandler.post(() -> maybeTrackInterface(iface));
}
@Override
public void interfaceRemoved(String iface) {
mHandler.post(() -> stopTrackingInterface(iface));
}
}
最后執(zhí)行trackAvailableInterfaces這個方法
private void trackAvailableInterfaces() {
try {
final String[] ifaces = mNMService.listInterfaces(); //遍歷當(dāng)前網(wǎng)卡接口,返回字符數(shù)組
for (String iface : ifaces) {
maybeTrackInterface(iface);//挨個做處理
}
} catch (RemoteException | IllegalStateException e) {
Log.e(TAG, "Could not get list of interfaces " + e);
}
}
繼續(xù)看maybeTrackInterface這個方法
private void maybeTrackInterface(String iface) {
if (!iface.matches(mIfaceMatch)) { //如果與設(shè)定的網(wǎng)卡名格式不匹配直接返回,例如eth0\eth1可以
return;
}
// If we don't already track this interface, and if this interface matches
// our regex, start tracking it.
if (mFactory.hasInterface(iface) || iface.equals(mDefaultInterface)) { //如果當(dāng)前初始化過了該網(wǎng)卡直接返回
if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface);
return;
}
if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface);
Intent intent = new Intent("android.net.action.ETH_DEVICE_ENABLED");
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Log.e(TAG, "Send broadcast: ETH_DEVICE_ENABLED");
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);//發(fā)送廣播,以太網(wǎng)設(shè)備可用
// TODO: avoid making an interface default if it has configured NetworkCapabilities.
//如果已配置NetworkCapabilities,請避免將接口設(shè)為默認(rèn)接口。
if (mDefaultInterface == null) {
mDefaultInterface = iface;
}
if (mIpConfigForDefaultInterface != null) { //第一次時這塊還是空的 所以沒走這
updateIpConfiguration(iface, mIpConfigForDefaultInterface);
mIpConfigForDefaultInterface = null;
}
addInterface(iface);//執(zhí)行下一步的方法
}
addInterface
private void addInterface(String iface) {
InterfaceConfiguration config = null;
// Bring up the interface so we get link status indications.
try {
mNMService.setInterfaceUp(iface);//先告訴netd加載上這個網(wǎng)卡并且獲取配置
config = mNMService.getInterfaceConfig(iface);
} catch (RemoteException | IllegalStateException e) {
// Either the system is crashing or the interface has disappeared. Just ignore the
// error; we haven't modified any state because we only do that if our calls succeed.
Log.e(TAG, "Error upping interface " + iface, e);
}
if (config == null) {
Log.e(TAG, "Null interface config for " + iface + ". Bailing out.");
return;
}
final String hwAddress = config.getHardwareAddress();
NetworkCapabilities nc = mNetworkCapabilities.get(iface);//測試相關(guān),先不管
if (nc == null) {
// Try to resolve using mac address
nc = mNetworkCapabilities.get(hwAddress);
if (nc == null) {
final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP);
nc = createDefaultNetworkCapabilities(isTestIface);
}
}
final int mode = getInterfaceMode(iface);//設(shè)置該網(wǎng)卡的這個模式,是客戶端還是服務(wù)端
if (mode == INTERFACE_MODE_CLIENT) {//一般都會走到這
IpConfiguration ipConfiguration = mIpConfigurations.get(iface);
if (ipConfiguration == null) {
ipConfiguration = createDefaultIpConfiguration();//創(chuàng)建一個默認(rèn)的數(shù)據(jù)對象
}
Log.d(TAG, "Tracking interface in client mode: " + iface);
mFactory.addInterface(iface, hwAddress, nc, ipConfiguration);//繼續(xù)調(diào)用該工廠類中的方法
} else {
maybeUpdateServerModeInterfaceState(iface, true);
}
// Note: if the interface already has link (e.g., if we crashed and got
// restarted while it was running), we need to fake a link up notification so we
// start configuring it.
if (config.hasFlag("running")) {
updateInterfaceState(iface, true);最后更新狀態(tài)
}
}
EthernetNetworkFactory
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
是時候看這個類了,之前在EthernetTracker的構(gòu)造方法中就有他,現(xiàn)在我們來看
因為EthernetNetworkFactory注冊了NetworkFactory 但是在子類并沒有register方法,所以調(diào)的都是他父類的
public class EthernetNetworkFactory extends NetworkFactory {
來看其父類的注冊方法都做了什么frameworks/libs/net/common/src_servicescommon/android/net/NetworkFactory.java
public void register() { //向系統(tǒng)注冊此NetworkFactory。每個工廠只能調(diào)用一次
if (mProvider != null) {
throw new IllegalStateException("A NetworkFactory must only be registered once");
}
if (DBG) log("Registering NetworkFactory");
mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {
@Override
public void onNetworkRequested(@NonNull NetworkRequest request, int score,//不同的網(wǎng)絡(luò)請求回調(diào)
int servingProviderId) {
handleAddRequest(request, score, servingProviderId);
}
@Override
public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {//網(wǎng)絡(luò)請求撤回
handleRemoveRequest(request);
}
};
((ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);//向connectivityService注冊改回調(diào)函數(shù),也就是和CONNECTIVITY_SERVICE進(jìn)行交互
}
所以上層fw的CONNECTIVITY_SERVICE服務(wù)到ethernet服務(wù)再到nmms(netd)服務(wù)之間的鏈路是這樣來的
繼續(xù)看EthernetNetworkFactory的構(gòu)造方法
public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) {
super(handler.getLooper(), context, NETWORK_TYPE, filter);
mHandler = handler;
mContext = context;
setScoreFilter(NETWORK_SCORE); //主要是設(shè)置分?jǐn)?shù),以太網(wǎng)的分?jǐn)?shù)大于為wifi大于mobile
}
回到初始化中的addInterface方法
void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities,
IpConfiguration ipConfiguration) {
if (mTrackingInterfaces.containsKey(ifaceName)) {//如果當(dāng)前打開的列表里有了,直接返回
Log.e(TAG, "Interface with name " + ifaceName + " already exists.");
return;
}
if (DBG) {
Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities);
}
NetworkInterfaceState iface = new NetworkInterfaceState(//這個NetworkInterfaceState是個內(nèi)部類
ifaceName, hwAddress, mHandler, mContext, capabilities, this);
iface.setIpConfig(ipConfiguration);//設(shè)置ip地址,等參數(shù)
mTrackingInterfaces.put(ifaceName, iface);//放進(jìn)容器內(nèi)保存
updateCapabilityFilter();//更新
}
繼續(xù)看
private void updateCapabilityFilter() {
NetworkCapabilities capabilitiesFilter = new NetworkCapabilities();
capabilitiesFilter.clearAll();//清空
for (NetworkInterfaceState iface: mTrackingInterfaces.values()) {
capabilitiesFilter.combineCapabilities(iface.mCapabilities);//根據(jù)現(xiàn)有打開的網(wǎng)卡初始化NetworkCapabilities對象
}
if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter);
setCapabilityFilter(capabilitiesFilter);//調(diào)用父類方法,第一次初始化不會執(zhí)行具體的邏輯
}
執(zhí)行完這些之后,就可以回到EthernetTracker繼續(xù)執(zhí)行updateInterfaceState方法frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
private void updateInterfaceState(String iface, boolean up) {
final int mode = getInterfaceMode(iface);
final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) //true
&& mFactory.updateInterfaceLinkState(iface, up);
//調(diào)用EthernetNetworkFactory里邊的updateInterfaceLinkState
if (factoryLinkStateUpdated) {
//*如果給定接口被配置為受限(不具有NET_CAPABILITY_NOT_RESTRICED)功能,則返回true。否則,返回false。
boolean restricted = isRestrictedInterface(iface);
int n = mListeners.beginBroadcast();//開始廣播
for (int i = 0; i < n; i++) {
try {
if (restricted) {
ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i);
if (!listenerInfo.canUseRestrictedNetworks) {
continue;
}
}
mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up);//執(zhí)行網(wǎng)卡可用回調(diào)
} catch (RemoteException e) {
// Do nothing here.
}
}
mListeners.finishBroadcast();
}
}
前面會執(zhí)行這里的updateInterfaceLinkStateframeworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
/** Returns true if state has been modified */
boolean updateInterfaceLinkState(String ifaceName, boolean up) {
if (!mTrackingInterfaces.containsKey(ifaceName)) {//前面執(zhí)行addInterface添加的,如果沒有返回false,沒有更新
return false;
}
if (DBG) {
Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up);
}
NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
return iface.updateLinkState(up);//執(zhí)行內(nèi)部類方法
}
/** Returns true if state has been modified */
boolean updateLinkState(boolean up) {
if (mLinkUp == up) return false; //不同狀態(tài)才會執(zhí)行
mLinkUp = up;
stop(); // (1)
if (up) {
start(); //(2)
}
return true;
}
sotp() 就是把各種變量和狀態(tài)清空
void stop() {
// Invalidate all previous start requests
if (mIpClient != null) {
shutdownIpClient(mIpClient);
mIpClientCallback.awaitIpClientShutdown();
mIpClient = null;
}
mIpClientCallback = null;
if (mNetworkAgent != null) {
mNetworkAgent.unregister();
mNetworkAgent = null;
}
mLinkProperties.clear();
}
IpClient下面有解釋
start() 開始執(zhí)行初始化網(wǎng)卡邏輯
private void start() {
if (mIpClient != null) {
if (DBG) Log.d(TAG, "IpClient already started"); //之前已經(jīng)初始化了就返回
return;
}
if (DBG) {
Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name));
}
mIpClientCallback = new IpClientCallbacksImpl();//與IpClient通信的回調(diào)
IpClientUtil.makeIpClient(mContext, name, mIpClientCallback);
mIpClientCallback.awaitIpClientStart(); //等待IpClient開啟
if (sTcpBufferSizes == null) {//緩存設(shè)置
sTcpBufferSizes = mContext.getResources().getString(
com.android.internal.R.string.config_ethernet_tcp_buffers);
}
provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);//設(shè)置各種網(wǎng)絡(luò)參數(shù)
}
provisionIpClient這個方法主要是進(jìn)行網(wǎng)絡(luò)具體參數(shù)的一些設(shè)置,但要依靠IpClient
private static void provisionIpClient(IIpClient ipClient, IpConfiguration config,
String tcpBufferSizes) {
if (config.getProxySettings() == ProxySettings.STATIC ||
config.getProxySettings() == ProxySettings.PAC) {
try {
ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy()));//設(shè)置代理根據(jù)入?yún)onfig中的參數(shù)
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
if (!TextUtils.isEmpty(tcpBufferSizes)) {
try {
ipClient.setTcpBufferSizes(tcpBufferSizes);//不為空就設(shè)置
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
final ProvisioningConfiguration provisioningConfiguration;
if (config.getIpAssignment() == IpAssignment.STATIC) { //靜態(tài)ip就設(shè)置咱們自己指定的
provisioningConfiguration = new ProvisioningConfiguration.Builder()
.withStaticConfiguration(config.getStaticIpConfiguration())
.build();
} else {
provisioningConfiguration = new ProvisioningConfiguration.Builder()//動態(tài)ip就由系統(tǒng)自動生成
.withProvisioningTimeoutMs(0)
.build();
}
try {
ipClient.startProvisioning(provisioningConfiguration.toStableParcelable());//最后調(diào)用IpClient開始設(shè)置
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
IpClientManager
frameworks/base/services/net/java/android/net/ip/IpClientManager.java
/**
* Start provisioning with the provided parameters.
*/
public boolean startProvisioning(ProvisioningConfiguration prov) {
final long token = Binder.clearCallingIdentity();
try {
mIpClient.startProvisioning(prov.toStableParcelable());
return true;
} catch (RemoteException e) {
log("Error starting IpClient provisioning", e);
return false;
} finally {
Binder.restoreCallingIdentity(token);
}
}
這也不是具體實現(xiàn),繼續(xù)看
IpClient
packages/modules/NetworkStack/src/android/net/ip/IpClient.java
@Override
public void startProvisioning(ProvisioningConfigurationParcelable req) {
enforceNetworkStackCallingPermission();
IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req));
}
調(diào)用其內(nèi)部類的方法
/**
* Start provisioning with the provided parameters.
*/
public void startProvisioning(ProvisioningConfiguration req) {
if (!req.isValid()) {
doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
return;
}
final ScanResultInfo scanResultInfo = req.mScanResultInfo;
mCurrentBssid = null;
if (scanResultInfo != null) {
try {
mCurrentBssid = MacAddress.fromString(scanResultInfo.getBssid());//獲取并保存該網(wǎng)絡(luò)的mac地址
} catch (IllegalArgumentException e) {
Log.wtf(mTag, "Invalid BSSID: " + scanResultInfo.getBssid()
+ " in provisioning configuration", e);
}
}
if (req.mLayer2Info != null) {
mL2Key = req.mLayer2Info.mL2Key;
mCluster = req.mLayer2Info.mCluster;
}
sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req));//發(fā)送msg
}
case CMD_START:
mConfiguration = (android.net.shared.ProvisioningConfiguration) msg.obj;//保存到本地
transitionTo(mClearingIpAddressesState);//轉(zhuǎn)移狀態(tài),
break;
mClearingIpAddressesState是ClearingIpAddressesState這個內(nèi)部類new出來的
先進(jìn)入其enter方法
class ClearingIpAddressesState extends State {
@Override
public void enter() {
// Ensure that interface parameters are fetched on the handler thread so they are
// properly ordered with other events, such as restoring the interface MTU on teardown.
mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName);//在系統(tǒng)中獲取該網(wǎng)卡的硬件參數(shù)
if (mInterfaceParams == null) { //如果是空,改變成停止?fàn)顟B(tài)直接返回
logError("Failed to find InterfaceParams for " + mInterfaceName);
doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND);
deferMessage(obtainMessage(CMD_STOP,
DisconnectCode.DC_INTERFACE_NOT_FOUND.getNumber()));
return;
}
mLinkObserver.setInterfaceParams(mInterfaceParams);//設(shè)置參數(shù)
if (readyToProceed()) {//查看是否有ip地址,這是true
deferMessage(obtainMessage(CMD_ADDRESSES_CLEARED));//發(fā)送:自發(fā)自收
} else {
// Clear all IPv4 and IPv6 before proceeding to RunningState.
// Clean up any leftover state from an abnormal exit from
// tethering or during an IpClient restart.
stopAllIP();
}
mCallback.setNeighborDiscoveryOffload(true);
}
}
發(fā)送CMD_ADDRESSES_CLEARED,看接收端
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_ADDRESSES_CLEARED: //在這處理,改變狀態(tài)。這里分析isUsingPreconnection為false的情況
transitionTo(isUsingPreconnection() ? mPreconnectingState : mRunningState);//直接進(jìn)入mRunningState狀態(tài)
break;
case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
handleLinkPropertiesUpdate(NO_CALLBACKS);
if (readyToProceed()) {
transitionTo(isUsingPreconnection() ? mPreconnectingState : mRunningState);
}
break;
case CMD_STOP:
case EVENT_PROVISIONING_TIMEOUT:
// Fall through to StartedState.
return NOT_HANDLED;
default:
// It's safe to process messages out of order because the
// only message that can both
// a) be received at this time and
// b) affect provisioning state
// is EVENT_NETLINK_LINKPROPERTIES_CHANGED (handled above).
deferMessage(msg);
}
return HANDLED;
}
private boolean readyToProceed() {
return !mLinkProperties.hasIpv4Address() && !mLinkProperties.hasGlobalIpv6Address();
}
看一下RunningState的enter方法
@Override
public void enter() {
ApfFilter.ApfConfiguration apfConfig = new ApfFilter.ApfConfiguration();
apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
apfConfig.multicastFilter = mMulticastFiltering;
// Get the Configuration for ApfFilter from Context
apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
mCallback.setFallbackMulticastFilter(mMulticastFiltering);
}
mPacketTracker = createPacketTracker();
if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName);
if (mConfiguration.mEnableIPv6 && !startIPv6()) {
doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV6);
return;
}
if (mConfiguration.mEnableIPv4 && !isUsingPreconnection() && !startIPv4()) {//關(guān)鍵是這個startIPv4方法
doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV4);
return;
}
final InitialConfiguration config = mConfiguration.mInitialConfig;
if ((config != null) && !applyInitialConfig(config)) {//應(yīng)用初始化值,沒有就跳過
// TODO introduce a new IpManagerEvent constant to distinguish this error case.
doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
enqueueJumpToStoppingState(DisconnectCode.DC_INVALID_PROVISIONING);
return;
}
if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) {//默認(rèn)不走這
doImmediateProvisioningFailure(
IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR);
enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPREACHABILITYMONITOR);
return;
}
}
來看這個startIPv4()
private boolean startIPv4() {
// If we have a StaticIpConfiguration attempt to apply it and
// handle the result accordingly.
if (mConfiguration.mStaticIpConfig != null) {//預(yù)先分配的話走這
if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.getIpAddress())) {//繼續(xù)去調(diào)mInterfaceCtrl
//設(shè)置成功回調(diào)
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
return false;
}
} else {
if (mDhcpClient != null) {
Log.wtf(mTag, "DhcpClient should never be non-null in startIPv4()");
}
startDhcpClient();
}
return true;
}
InterfaceController
packages/modules/NetworkStack/common/moduleutils/src/android/net/ip/InterfaceController.java
/**
* Set the IPv4 address of the interface.
*/
public boolean setIPv4Address(final LinkAddress address) {
return setInterfaceConfiguration(address, null);
}
/**
* Set the IPv4 address and also optionally bring the interface up or down.
*/
public boolean setInterfaceConfiguration(final LinkAddress ipv4Addr,
final Boolean setIfaceUp) {
if (!(ipv4Addr.getAddress() instanceof Inet4Address)) {//參數(shù)校驗
throw new IllegalArgumentException("Invalid or mismatched Inet4Address");
}
// Note: currently netd only support INetd#IF_STATE_UP and #IF_STATE_DOWN.
// Other flags would be ignored.
//參數(shù)包裝,為了跨進(jìn)程傳遞給netd
final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
ifConfig.ifName = mIfName;
ifConfig.ipv4Addr = ipv4Addr.getAddress().getHostAddress();
ifConfig.prefixLength = ipv4Addr.getPrefixLength();
// Netd ignores hwaddr in interfaceSetCfg.
ifConfig.hwAddr = "";
if (setIfaceUp == null) {//默認(rèn)走這
// Empty array means no change.
ifConfig.flags = new String[0];
} else {
// Netd ignores any flag that's not IF_STATE_UP or IF_STATE_DOWN in interfaceSetCfg.
ifConfig.flags = setIfaceUp.booleanValue()
? new String[] {IF_STATE_UP} : new String[] {IF_STATE_DOWN};
}
try {
mNetd.interfaceSetCfg(ifConfig);//接著把參數(shù)給到netd繼續(xù)執(zhí)行就可以了
} catch (RemoteException | ServiceSpecificException e) {
logError("Setting IPv4 address to %s/%d failed: %s",
ifConfig.ipv4Addr, ifConfig.prefixLength, e);
return false;
}
return true;
}
別忘了之前還有一個startIPv4()方法內(nèi)還有個handleIPv4Success回調(diào)packages/modules/NetworkStack/src/android/net/ip/IpClient.java
private void handleIPv4Success(DhcpResults dhcpResults) {
mDhcpResults = new DhcpResults(dhcpResults);//填充的分配好的ip地址
final LinkProperties newLp = assembleLinkProperties();
final int delta = setLinkProperties(newLp); //更新配置然后返回一個狀態(tài)值,這個狀態(tài)值會通知到其他監(jiān)聽該狀態(tài)改變的類
if (mDhcpResults.vendorInfo == null && detectUpstreamHotspotFromVendorIe()) {
mDhcpResults.vendorInfo = DhcpPacket.VENDOR_INFO_ANDROID_METERED;
}
if (DBG) {
Log.d(mTag, "onNewDhcpResults(" + Objects.toString(mDhcpResults) + ")");
Log.d(mTag, "handleIPv4Success newLp{" + newLp + "}");
}
mCallback.onNewDhcpResults(mDhcpResults);//回調(diào)ip參數(shù)
maybeSaveNetworkToIpMemoryStore();//空的
dispatchCallback(delta, newLp);//重要是這里
}
protected final IpClientCallbacksWrapper mCallback;
這個mCallback是IpClientCallbacksWrapper靜態(tài)內(nèi)部類
dispatchCallback開始分發(fā)配置結(jié)果
private void dispatchCallback(int delta, LinkProperties newLp) {
switch (delta) {
case PROV_CHANGE_GAINED_PROVISIONING:
if (DBG) {
Log.d(mTag, "onProvisioningSuccess()");
}
recordMetric(IpManagerEvent.PROVISIONING_OK);
mCallback.onProvisioningSuccess(newLp); //如果正確設(shè)置后會走這
break;
case PROV_CHANGE_LOST_PROVISIONING:
if (DBG) {
Log.d(mTag, "onProvisioningFailure()");
}
recordMetric(IpManagerEvent.PROVISIONING_FAIL);
mCallback.onProvisioningFailure(newLp);
break;
default:
if (DBG) {
Log.d(mTag, "onLinkPropertiesChange()");
}
mCallback.onLinkPropertiesChange(newLp);
break;
}
}
public static class IpClientCallbacksWrapper {
private static final String PREFIX = "INVOKE ";
private final IIpClientCallbacks mCallback;
//...省略
/**
* Indicates that provisioning was successful.
*/
public void onProvisioningSuccess(LinkProperties newLp) {
log("onProvisioningSuccess({" + newLp + "})");
try {
mCallback.onProvisioningSuccess(mShim.makeSensitiveFieldsParcelingCopy(newLp));
} catch (RemoteException e) {
log("Failed to call onProvisioningSuccess", e);
}
}
最后則會回調(diào)到EthernetNetworkFactory中frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
@Override
public void onProvisioningSuccess(LinkProperties newLp) {
mHandler.post(() -> onIpLayerStarted(newLp));
}
繼續(xù)調(diào)到這
void onIpLayerStarted(LinkProperties linkProperties) {
if (mNetworkAgent != null) {
Log.e(TAG, "Already have a NetworkAgent - aborting new request");
stop(); //重復(fù),直接返回
return;
}
mLinkProperties = linkProperties;
// Create our NetworkAgent.
final NetworkAgentConfig config = new NetworkAgentConfig.Builder()
.setLegacyType(mLegacyType)
.setLegacyTypeName(NETWORK_TYPE) //ethernet
.build();
mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), //初始化這個NetworkAgent對象
NETWORK_TYPE, mCapabilities, mLinkProperties,
getNetworkScore(), config, mNetworkFactory.getProvider()) {
public void unwanted() {
if (this == mNetworkAgent) {
stop();
} else if (mNetworkAgent != null) {
Log.d(TAG, "Ignoring unwanted as we have a more modern " +
"instance");
} // Otherwise, we've already called stop.
}
};
mNetworkAgent.register();//注冊到ConnectivityService
mNetworkAgent.setLegacyExtraInfo(mHwAddress);
mNetworkAgent.markConnected(); //建立鏈接
}
參數(shù)申請完了就開始建立網(wǎng)絡(luò)連接了,這一部分將放到下一章來講
上層framework就分析到這,后續(xù)netd的部分如感興趣可以自行了解
技術(shù)名詞解釋
IPClient
-
Android的IpClient是一個用于管理網(wǎng)絡(luò)連接的類。它是Android系統(tǒng)中的一個重要組件,用于處理與網(wǎng)絡(luò)連接相關(guān)的任務(wù)。IpClient負(fù)責(zé)獲取IP地址、配置網(wǎng)絡(luò)接口、處理DHCP請求和響應(yīng)等操作。
-
IpClient使用了DHCP協(xié)議來獲取IP地址。它會通過發(fā)送DHCP請求來與DHCP服務(wù)器進(jìn)行通信,并獲取分配給設(shè)備的IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)和DNS服務(wù)器等信息。一旦獲取到這些信息,IpClient會將其配置到設(shè)備的網(wǎng)絡(luò)接口上,使設(shè)備能夠正常與網(wǎng)絡(luò)進(jìn)行通信。
-
除了處理DHCP請求和響應(yīng)外,IpClient還負(fù)責(zé)監(jiān)測網(wǎng)絡(luò)連接狀態(tài)的變化。它會監(jiān)聽網(wǎng)絡(luò)狀態(tài)的改變,并在網(wǎng)絡(luò)連接斷開或重新連接時觸發(fā)相應(yīng)的操作。例如,當(dāng)設(shè)備從無線網(wǎng)絡(luò)切換到移動數(shù)據(jù)網(wǎng)絡(luò)時,IpClient會重新獲取IP地址并更新網(wǎng)絡(luò)配置。
-
總的來說,Android的IpClient是一個用于管理網(wǎng)絡(luò)連接的重要組件,它通過DHCP協(xié)議獲取IP地址并配置網(wǎng)絡(luò)接口,同時監(jiān)測網(wǎng)絡(luò)連接狀態(tài)的變化。這樣可以確保設(shè)備能夠順暢地進(jìn)行網(wǎng)絡(luò)通信。
IpAssignment
- 在Android中,可以使用IpAssignment枚舉來設(shè)置IP地址分配模式。IpAssignment有以下幾個選項:
- STATIC:靜態(tài)IP地址分配模式。在這種模式下,你可以手動指定設(shè)備的IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)和DNS服務(wù)器。
- DHCP:動態(tài)主機(jī)配置協(xié)議(DHCP)模式。在這種模式下,設(shè)備會自動通過DHCP服務(wù)器獲取IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)和DNS服務(wù)器。
LinkProperties
這個網(wǎng)絡(luò)鏈接參數(shù)
/**
* Describes the properties of a network link.
*
* A link represents a connection to a network.
* It may have multiple addresses and multiple gateways,
* multiple dns servers but only one http proxy and one
* network interface.
*
* Note that this is just a holder of data. Modifying it
* does not affect live networks.
*
*/
public final class LinkProperties implements Parcelable {
// The interface described by the network link.
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private String mIfaceName;
private final ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
private final ArrayList<InetAddress> mDnses = new ArrayList<>();
// PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service.
private final ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>();
private final ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
private boolean mUsePrivateDns;
private String mPrivateDnsServerName;
private String mDomains;
private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
private Inet4Address mDhcpServerAddress;
private ProxyInfo mHttpProxy;
private int mMtu;
// in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
private String mTcpBufferSizes;
private IpPrefix mNat64Prefix;
private boolean mWakeOnLanSupported;
private Uri mCaptivePortalApiUrl;
private CaptivePortalData mCaptivePortalData;
NetworkAgent
Android NetworkAgent 是一個用于管理網(wǎng)絡(luò)連接的類。它允許應(yīng)用程序在 Android 設(shè)備上監(jiān)控和控制網(wǎng)絡(luò)連接狀態(tài)。NetworkAgent 可以用于創(chuàng)建、配置和管理網(wǎng)絡(luò)連接,并提供與網(wǎng)絡(luò)相關(guān)的信息。
通過 NetworkAgent,應(yīng)用程序可以:
- 監(jiān)聽網(wǎng)絡(luò)連接狀態(tài)的變化,例如連接建立、斷開和切換連接等。
- 獲取當(dāng)前活動的網(wǎng)絡(luò)連接的詳細(xì)信息,如網(wǎng)絡(luò)類型、信號強(qiáng)度和 IP 地址等。
- 請求建立新的網(wǎng)絡(luò)連接或關(guān)閉現(xiàn)有的網(wǎng)絡(luò)連接。
- 設(shè)置網(wǎng)絡(luò)連接的參數(shù),如代理設(shè)置、數(shù)據(jù)使用限制和網(wǎng)絡(luò)優(yōu)先級等。
- 使用 NetworkAgent API,開發(fā)人員可以實現(xiàn)更高級的網(wǎng)絡(luò)管理功能,例如在多個網(wǎng)絡(luò)之間自動切換、
小結(jié)
本章分析了安卓以太網(wǎng)這個模塊的初始化流程,后續(xù)會對網(wǎng)卡的開啟,路由的設(shè)置等網(wǎng)絡(luò)策略進(jìn)行分析
文章來源:http://www.zghlxwxcb.cn/news/detail-756185.html
謝謝文章來源地址http://www.zghlxwxcb.cn/news/detail-756185.html
到了這里,關(guān)于Android 11 Ethernet以太網(wǎng)架構(gòu)分析(1)——初始化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!