android系統 Ethernet 解析
在公司一款產品上需要需要新增有線網口,所以系統需要做相應的支援,找到一個支援的有線網口的系統,將其中軟體部分做簡單分析:
首先:功能方面,要能夠設定有線網路的IP地址,子網掩碼,閘道器,DNS等資訊,這些功能由 Etnernet 這個 APP實現;
系統方面,對於已經設定好的資訊,斷電重啟之後不能丟失,還能繼續保持有效,所以需要新增一個系統服務 EthernetService
其次,EthernetService的啟動入口, \frameworks\base\services\java\com\android\server\ConnectivityService.java 其構造類
public ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
NetworkFactory netFactory)
。
。
for (int targetNetworkType : mPriorityList) {
final NetworkConfig config = mNetConfigs[targetNetworkType];
final NetworkStateTracker tracker;
try {
tracker = netFactory.createTracker(targetNetworkType, config);
mNetTrackers[targetNetworkType] = tracker;
if (targetNetworkType == ConnectivityManager.TYPE_ETHERNET) {
EthernetService ethernet = new EthernetService(context, (EthernetStateTracker)tracker);
ServiceManager.addService(Context.ETH_SERVICE, ethernet);
}
Slog.d(TAG, "*******targetNetworkType="+targetNetworkType);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
+ " tracker: " + e);
continue;
}
tracker.startMonitoring(context, mTrackerHandler);
if (config.isDefault()) {
tracker.reconnect();
}
}
上面的黑體字程式碼是實現Ethernet 功能的核心,具體分析如下
1. tracker = netFactory.createTracker(targetNetworkType, config);
建立 網路狀態追蹤器
@Override
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
switch (config.radio) {
case TYPE_WIFI:
return new WifiStateTracker(targetNetworkType, config.name);
case TYPE_MOBILE:
return new MobileDataStateTracker(targetNetworkType, config.name);
case TYPE_DUMMY:
return new DummyDataStateTracker(targetNetworkType, config.name);
case TYPE_BLUETOOTH:
return BluetoothTetheringDataTracker.getInstance();
case TYPE_WIMAX:
return makeWimaxStateTracker(mContext, mTrackerHandler);
case TYPE_ETHERNET:
//return EthernetDataTracker.getInstance();
return new EthernetStateTracker(targetNetworkType, config.name);
default:
throw new IllegalArgumentException(
"Trying to create a NetworkStateTracker for an unknown radio type: "
+ config.radio);
}
}
}
2. 建立並新增網路服務
EthernetService ethernet = new EthernetService(context, (EthernetStateTracker)tracker);
ServiceManager.addService(Context.ETH_SERVICE, ethernet);
\frameworks\base\services\java\com\android\server\EthernetService.java
private int mEthState= EthernetManager.ETH_STATE_UNKNOWN;
//public static final int ETH_STATE_UNKNOWN = 0;
public EthernetService(Context context, EthernetStateTracker Tracker){
mTracker = Tracker;
mContext = context;
isEthEnabled = getPersistedState();
Slog.v(TAG,"Ethernet dev enabled " + isEthEnabled );
getDeviceNameList();
setEthState(isEthEnabled);
//registerForBroadcasts();
Slog.v(TAG, "Trigger the ethernet monitor");
mTracker.StartPolling();
mDelayedHandler = new Handler();
isEthernetServiceInited = true;
}
其核心是 setEthState,即開關網路
3. tracker.startMonitoring(context, mTrackerHandler);
啟動網路狀態監控,核心是
frameworks\base\ethernet\java\android\net\ethernet\EthernetMonitor.java
class MonitorThread extends Thread {
public MonitorThread() {
super("EthMonitor");
}
public void run() {
int index;
int i;
//noinspection InfiniteLoopStatement
for (;;) {
if (DEBUG) Slog.i(TAG, "go poll events");
String eventName = EthernetNative.waitForEvent();
if (eventName == null) {
continue;
}
if (DEBUG) Slog.i(TAG, "got event " + eventName);
/*
* Map event name into event enum
*/
String [] events = eventName.split(":");
index = events.length;
if (index < 2)
continue;
i = 0;
while (index != 0 && i < index-1) {
int event = 0;
if (DEBUG) Slog.i(TAG,"dev: " + events[i] + " ev " + events[i+1]);
int cmd =Integer.parseInt(events[i+1]);
if ( cmd == DEL_LINK) {
event = DISCONNECTED;
handleEvent(events[i],event);
}
else if (cmd == ADD_ADDR ) {
event = CONNECTED;
handleEvent(events[i],event);
} else if (cmd == NEW_LINK) {
event = PHYUP;
handleEvent(events[i],event);
}
i = i + 2;
}
}
}
/**
* Handle all supplicant events except STATE-CHANGE
* @param event the event type
* @param remainder the rest of the string following the
* event name and " — "
*/
void handleEvent(String ifname,int event) {
switch (event) {
case DISCONNECTED:
mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED);
break;
case CONNECTED:
mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED);
break;
case PHYUP:
mTracker.notifyPhyConnected(ifname);
break;
default:
mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED);
}
}
監控程式啟動一個執行緒,呼叫native方法 String eventName = EthernetNative.waitForEvent();
通過 handleEvent(events[i],event); 將不同的網路狀態訊息傳到 mTracker ,mTracker對訊息作出響應
4. 實現真正的網路設定,
tracker.reconnect(); 其核心是 EthernetStateTracker ->resetInterface,在呼叫本地方法,
system/core/libnetutils/ifc_utils.c
(libcutils---ifc_utils.c)int ifc_reset_connections(const char *ifname, const int reset_mask)
這個檔案還包含一些網路介面,詳見 另一篇部落格
http://blog.csdn.net/liufuliang163/article/details/72729901
上面提到的相關程式碼:
http://download.csdn.net/detail/liufuliang163/9853456