在当前网络成为必不可少的条件时,android系统也集成的wifi,bluetooth,eth,cablemodem等等,为了将其它网络加入进来,大致浏览一下网络管理的相关分析,重点看了wifi的管理,还是绕了很多弯弯的。
public static final int TYPE_WIMAX = 6;
try {
Slog.i(TAG, "Connectivity Service");
connectivity = ConnectivityService.getInstance(context);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Connectivity Service", e);
}
if (connectivityF != null) connectivityF.systemReady();
private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
*/
public String mName;
public int mType;
public int mRadio;
public int mPriority;
public NetworkInfo.State mLastState;
public NetworkAttributes(String init) {
String fragments[] = init.split(",");
mName = fragments[0].toLowerCase();
mType = Integer.parseInt(fragments[1]);
mRadio = Integer.parseInt(fragments[2]);
mPriority = Integer.parseInt(fragments[3]);
mLastState = NetworkInfo.State.UNKNOWN;
}
public boolean isDefault() {
return (mType == mRadio);
}
}
private static class RadioAttributes {
public int mSimultaneity;
public int mType;
public RadioAttributes(String init) {
String fragments[] = init.split(",");
mType = Integer.parseInt(fragments[0]);
mSimultaneity = Integer.parseInt(fragments[1]);
}
}
// high priority first
mPriorityList = new int[mNetworksDefined];
{
int insertionPoint = mNetworksDefined-1;
int currentLowest = 0;
int nextLowest = 0;
while (insertionPoint > -1) {
for (NetworkAttributes na : mNetAttributes) {
if (na == null) continue;
if (na.mPriority < currentLowest) continue;
if (na.mPriority > currentLowest) {
if (na.mPriority < nextLowest || nextLowest == 0) {
nextLowest = na.mPriority;
}
continue;
}
mPriorityList[insertionPoint--] = na.mType;
}
currentLowest = nextLowest;
nextLowest = 0;
}
}
private void handleConnect(NetworkInfo info) {
int type = info.getType();
// snapshot isFailover, because sendConnectedBroadcast() resets it
boolean isFailover = info.isFailover();
NetworkStateTracker thisNet = mNetTrackers[type];
// if this is a default net and other default is running
// kill the one not preferred
if (mNetAttributes[type].isDefault()) {
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
if ((type != mNetworkPreference &&
mNetAttributes[mActiveDefaultNetwork].mPriority >
mNetAttributes[type].mPriority) ||
mNetworkPreference == mActiveDefaultNetwork) {
// don't accept this one
if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " +
"to torn down network " + info.getTypeName());
teardown(thisNet);
return;
} else {
// tear down the other
NetworkStateTracker otherNet =
mNetTrackers[mActiveDefaultNetwork];
if (DBG) Slog.v(TAG, "Policy requires " +
otherNet.getNetworkInfo().getTypeName() +
" teardown");
if (!teardown(otherNet)) {
Slog.e(TAG, "Network declined teardown request");
return;
}
if (isFailover) {
otherNet.releaseWakeLock();
}
}
}
mActiveDefaultNetwork = type;
// this will cause us to come up initially as unconnected and switching
// to connected after our normal pause unless somebody reports us as reall
// disconnected
mDefaultInetConditionPublished = 0;
mDefaultConnectionSequence++;
mInetConditionChangeInFlight = false;
// Don't do this - if we never sign in stay, grey
//reportNetworkCondition(mActiveDefaultNetwork, 100);
}
thisNet.setTeardownRequested(false);
thisNet.updateNetworkSettings();
handleConnectivityChange(type);
sendConnectedBroadcast(info);
}
/*
* Create the network state trackers for Wi-Fi and mobile
* data. Maybe this could be done with a factory class,
* but it's not clear that it's worth it, given that
* the number of different network types is not going
* to change very often.
*/
boolean noMobileData = !getMobileDataEnabled();
for (int netType : mPriorityList) {
switch (mNetAttributes[netType].mRadio) {
case ConnectivityManager.TYPE_WIFI:
if (DBG) Slog.v(TAG, "Starting Wifi Service.");
WifiStateTracker wst = new WifiStateTracker(context, mHandler);
WifiService wifiService = new WifiService(context, wst);
ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
wifiService.startWifi();
mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
wst.startMonitoring();
break;
...
在网络监视器中捕捉了settings中发出的相应的网络广播信息,网络监视器中注册了settings中网络变化的信息,有变化会做相应的处理,并将处理的结果存储在NetworkInfo类的一个对象中,在ConnectivityService中通过
public NetworkInfo getNetworkInfo(int networkType)方法可以得知当前networkType类型网络的连接情况。
wifi 图示层次:
ConnectivityService 的构造函数会将 WifiService 添加到 ServiceManager 中,使之需要服务者可以访问。
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_ENABLE_WIFI:
setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);
if (mWifiWatchdogService == null) {
mWifiWatchdogService = new WifiWatchdogService(mContext, mWifiStateTracker);
}
sWakeLock.release();
break;
private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) {
...
setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
if (enable) {
if (!mWifiStateTracker.loadDriver()) {
Slog.e(TAG, "Failed to load Wi-Fi driver.");
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return false;
}
if (!mWifiStateTracker.startSupplicant()) {
mWifiStateTracker.unloadDriver();
Slog.e(TAG, "Failed to start supplicant daemon.");
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return false;
}
registerForBroadcasts();
mWifiStateTracker.startEventLoop();
}
/**
* Registers to receive the necessary Wi-Fi broadcasts.
*/
private void registerForWifiBroadcasts() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mContext.registerReceiver(mReceiver, intentFilter);
}
/**
* see {@link android.net.wifi.WifiManager#startScan()}
*/
public void startScan(boolean forceActive) {
enforceChangePermission();
if (mWifiHandler == null) return;
Message.obtain(mWifiHandler, MESSAGE_START_SCAN, forceActive ? 1 : 0, 0).sendToTarget();
}
static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)
{
jboolean result;
// Ignore any error from setting the scan mode.
// The scan will still work.
if (forceActive && !sScanModeActive)
doSetScanMode(true);
result = doBooleanCommand("SCAN", "OK");
if (forceActive && !sScanModeActive)
doSetScanMode(sScanModeActive);
return result;
}
当 wpa_supplicant 处理完 SCAN 命令后,它会向控制通道发送事件通知扫描完成,从而wifi_wait_for_event 函数会接收到该事件,由此 WifiMonitor 中的 MonitorThread 会被执行来出来这个事件
static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject clazz)
{
char buf[256];
int nread = ::wifi_wait_for_event(buf, sizeof buf);
if (nread > 0) {
return env->NewStringUTF(buf);
} else {
return env->NewStringUTF(NULL);
}
}
void handleEvent(int event, String remainder) {
case SCAN_RESULTS:
mWifiStateTracker.notifyScanResultsAvailable();
break;
public void onAccessPointSetChanged(AccessPointState ap, boolean added) {
AccessPointPreference pref = mAps.get(ap);
if (added) {
if (pref == null) {
pref = new AccessPointPreference(this, ap);
mAps.put(ap, pref);
} else {
pref.setEnabled(true);
}
mApCategory.addPreference(pref);
}
}
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference
preference) {
if (preference instanceof AccessPointPreference) {
AccessPointState state=((AccessPointPreference)preference).getAccessPointState();
showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
}
}
private void handleConnect() {
String password = getEnteredPassword();
if (!TextUtils.isEmpty(password)) {
mState.setPassword(password);
}
mWifiLayer.connectToNetwork(mState);
}
private void handleConnectedState() {
setPollTimer();
mLastSignalLevel = -1;
if (!mHaveIPAddress && !mObtainingIPAddress) {
mObtainingIPAddress = true;
mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget();
}
}
private class DhcpHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_DHCP_START:
if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {
event = EVENT_DHCP_SUCCEEDED;
}
case EVENT_DHCP_SUCCEEDED:
mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);
setDetailedState(DetailedState.CONNECTED);
intent =new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);
mContext.sendStickyBroadcast(intent);
break;
至此为止,整个连接过程完成。