在網上找的一篇好文章,分析的很詳細,本身再加了些東西,圖片有點大,不能徹底顯示,點擊圖像拖動鼠標直接查看圖像。
java
wifi相關的文件位置:android
WIFI Settings應用程序位於app
packages/apps/Settings/src/com/android/settings/wifi/less
JAVA部分:ide
frameworks/base/services/java/com/android/server/函數
frameworks/base/wifi/java/android/net/wifi/oop
JNI部分:ui
frameworks/base/core/jni/android_net_wifi_Wifi.cppthis
wifi管理庫。編碼
hardware/libhardware_legary/wifi/
wifi用戶空間的程序和庫:
external/wpa_supplicant/
生成庫libwpaclient.so和守護進程wpa_supplicant。
調用流程:
wifi模塊的初始化:
(frameworks/base/services/java/com/android/server/SystemServer.Java)
在 SystemServer 啓動的時候,會生成一個ConnectivityService 的實例,
class ServerThread extends Thread {
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
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);
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
其中 ,ConnectivityService.getInstance(context); 對應於(frameworks/base/services/java/com/android/server/ ConnectivityService.Java)ConnectivityService.Java。
下面看下ConnectivityService.Java中的
public static ConnectivityService getInstance(Context context) {
return ConnectivityThread.getServiceInstance(context);
}函數, 繼續往下看:
public static ConnectivityService getServiceInstance(Context context) {
ConnectivityThread thread = new ConnectivityThread(context);
thread.start();
synchronized (thread) {
while (sServiceInstance == null) {
try {
// Wait until sServiceInstance has been initialized.
thread.wait();
} catch (InterruptedExceptionignore) {
Slog.e(TAG,
"UnexpectedInterruptedException while waiting"+
" forConnectivityService thread");
}
}
}
return sServiceInstance;
}
}
繼續往下跟:
private static class ConnectivityThread extends Thread {
private Context mContext;
private ConnectivityThread(Context context) {
super("ConnectivityThread");
mContext = context;
}
public void run() {
Looper.prepare();
synchronized (this) {
sServiceInstance = new ConnectivityService(mContext);
notifyAll();
}
Looper.loop();
}
繼續new ConnectivityService(mContext)
private ConnectivityService(Context context) {
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
for(int netType : mPriorityList) {
switch (mNetAttributes[netType].mRadio) {
case ConnectivityManager.TYPE_WIFI:
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();//啓動wifiservice
mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
wst.startMonitoring();//啓動Monitoring
break; 。。。。。
}//endfor
。。。。。。。。。。。。。。。。。。。。。。。。。。
}
到這裏模塊初始化的工做完成,具體流程圖以下:
WifiStateTracker 會建立 WifiMonitor 接收來自底層的事件, WifiService 和 WifiMonitor 是整個模塊的核心。WifiService 負責啓動關閉 wpa_supplicant、啓動關閉 WifiMonitor 監視線程和把命令下發給 wpa_supplicant,而 WifiMonitor 則負責從 wpa_supplicant 接收事件通知。
也就是說WifiService負責wifi整個流程的控制,而WifiMonitor負責監視底層的事件。
此時WifiService starting up withWi-Fi disabled,
Wifi模塊的啓動(Enable):
(packages/apps/Settings/src/com/android/settings/wifi/ WirelessSettings.java)
WirelessSettings 在初始化的時候配置了由WifiEnabler 來處理Wifi 按鈕,
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
mWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (getIntent().getBooleanExtra("only_access_points",false)) {
addPreferencesFromResource(R.xml.wifi_access_points);
} else {
addPreferencesFromResource(R.xml.wifi_settings);
mWifiEnabler = new WifiEnabler(this,
(CheckBoxPreference)findPreference("enable_wifi"));
mNotifyOpenNetworks =
(CheckBoxPreference)findPreference("notify_open_networks");
mNotifyOpenNetworks.setChecked(Secure.getInt(getContentResolver(),
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,0) == 1);
}
mAccessPoints = (ProgressCategory)findPreference("access_points");
mAccessPoints.setOrderingAsAdded(false);
mAddNetwork =findPreference("add_network");
registerForContextMenu(getListView());
}
而後調用:(packages/apps/Settings/src/com/android/settings/wifi/ WifiEnabler.java)
publicclass WifiEnabler implements Preference.OnPreferenceChangeListener {
。。。。。。。。。。。。。。。。。。。。。。
public boolean onPreferenceChange(Preferencepreference, Object value) {
。。。。。。。。。。。。。。。。。。。。。。。。。。。
if (mWifiManager.setWifiEnabled(enable)){
mCheckBox.setEnabled(false);
} else {
mCheckBox.setSummary(R.string.wifi_error);
}
。。。。。。。。。。。。。。。。。。。。。。
}
。。。。。。。。。。。。。。。。。。。。。
}
調用:
(packages/apps/Settings/src/com/android/settings/wifi/ WifiManager.java)
public boolean setWifiEnabled(booleanenabled) {
try {
return mService.setWifiEnabled(enabled);
} catch(RemoteException e) {
return false;
}
}
當用戶按下 Wifi 按鈕後, Android 會調用 WifiEnabler 的onPreferenceChange, 再由 WifiEnabler調用 WifiManager 的 setWifiEnabled 接口函數,經過 AIDL,實際調用的是 WifiService 的setWifiEnabled 函數,WifiService 接着向自身發送一條 MESSAGE_ENABLE_WIFI 消息,在處理該消息的代碼中作真正的使能工做:首先裝載 WIFI 內核模塊(該模塊的位置硬編碼爲"/system/lib/modules/wlan.ko" ), 然 後 啓 動 wpa_supplicant ( 配 置 文 件 硬 編 碼 爲"/data/misc/wifi/wpa_supplicant.conf")再經過 WifiStateTracker 來啓動 WifiMonitor 中的監視線程。
WifiService(WifiService.java) 收到MESSAGE_ENABLE_WIFI 消息後的操做以下:
AIDL:
Android Interface Definition Language,即Android接口描述語言。Android系統中的進程之間不能共享內存,所以,須要提供一些機制在不一樣進程之間進行數據通訊。
爲了使其餘的應用程序也能夠訪問本應用程序提供的服務,Android系統採用了遠程過程調用(Remote Procedure Call,RPC)方式來實現。與不少其餘的基於RPC的解決方案同樣,Android使用一種接口定義語言(InterfaceDefinition Language,IDL)來公開服務的接口。所以,能夠將這種能夠跨進程訪問的服務稱爲AIDL(Android Interface Definition Language)服務。
接下來繼續道wifiService.Java
(frameworks/base/services/java/com/android/server/ wifiService.Java)
public boolean setWifiEnabled(boolean enable) {
enforceChangePermission();
if (mWifiHandler == null) return false;
synchronized (mWifiHandler) {
// caller may not have WAKE_LOCKpermission - it's not required here
long ident =Binder.clearCallingIdentity();
sWakeLock.acquire();
Binder.restoreCallingIdentity(ident);
mLastEnableUid =Binder.getCallingUid();
// set a flag if the user isenabling Wifi while in airplane mode
mAirplaneModeOverwridden = (enable&& isAirplaneModeOn() && isAirplaneToggleable());
sendEnableMessage(enable, true,Binder.getCallingUid()); // here send a mesage to himself
}
return true;
}
繼續往下:
private void sendEnableMessage(boolean enable,boolean persist, int uid) {
Message msg= Message.obtain(mWifiHandler,
(enable ?MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
(persist ? 1 : 0), uid);
msg.sendToTarget();
}
WifiHandler會收到消息:
private class WifiHandler extends Handler {
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_ENABLE_WIFI:
setWifiEnabledBlocking(true, msg.arg1 == 1,msg.arg2);
if (mWifiWatchdogService ==null) {
mWifiWatchdogService = newWifiWatchdogService(mContext, mWifiStateTracker);
}
sWakeLock.release();
break;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
privateboolean setWifiEnabledBlocking(booleanenable, boolean persist, int uid) {
。。。。。。。。。。。。
setWifiEnabledState(enable ?WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
if (enable) {
if (!mWifiStateTracker.loadDriver()){
Slog.e(TAG, "Failed toload Wi-Fi driver.");
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return false;
}
if (!mWifiStateTracker.startSupplicant()){
mWifiStateTracker.unloadDriver();
Slog.e(TAG, "Failed tostart supplicant daemon.");
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
return false;
}
registerForBroadcasts();
mWifiStateTracker.startEventLoop();
} else {
mContext.unregisterReceiver(mReceiver);
// Remove notification (it willno-op if it isn't visible)
mWifiStateTracker.setNotificationVisible(false,0, false, 0);
booleanfailedToStopSupplicantOrUnloadDriver = false;
if (!mWifiStateTracker.stopSupplicant()){
Slog.e(TAG, "Failed tostop supplicant daemon.");
setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);
failedToStopSupplicantOrUnloadDriver = true;
}
/**
* Reset connections and disableinterface
* before we unload the driver
*/
mWifiStateTracker.resetConnections(true);
if (!mWifiStateTracker.unloadDriver()){
Slog.e(TAG, "Failed tounload Wi-Fi driver.");
if(!failedToStopSupplicantOrUnloadDriver) {
setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
failedToStopSupplicantOrUnloadDriver = true;
}
}
if(failedToStopSupplicantOrUnloadDriver) {
return false;
}
}
。。。。。。。。。。。。。。。。。。。。。。
}
具體流程以下流程圖所示:
掃描查找熱點(AP)
上一節中講到Wifi模塊開啓後會對外發送WIFI_STATE_CHANGED_ACTION。WifiLayer中註冊了Action的Receiver。
當WifiLayer收到此Action後開始scan的流程,具體以下:
當wpa_supplicant 處理完SCAN 命令後,它會向控制通道發送事件通知掃描完成,從wifi_wait_for_event函數會接收到該事件,由此WifiMonitor 中的MonitorThread會被執行來出來這個事件:
配置 AP 參數
當用戶在WifiSettings 界面上選擇了一個AP 後,會顯示配置AP 參數的一個對話框:
Wifi鏈接
具體流程參見如下流程圖:
IP地址的配置
流程如圖:
到此結束。