在当前网络成为必不可少的条件时,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;
至此为止,整个连接过程完成。