1. 程式人生 > >android 框架之WIFI系統和系統架構全面總結(一)。

android 框架之WIFI系統和系統架構全面總結(一)。

知識就本來就是滾雪球,越滾才越大!

在瞭解WIFI模組的系統架構之前。我心中就有一個疑問,那麼android的系統架構是怎樣的呢。其實現在網路中有很多關於android系統架構的描述和解釋,在這裡我不做詳細的研究了,只是貼張圖重新溫故一下。具體細節還要檢視android原始碼,多問度娘和google大神。




一、wpa_supplicant是什麼?

 wpa_supplicant本是開源專案原始碼,被谷歌修改後加入android移動平臺,它主要是用來支援WEP,WPA/WPA2和WAPI無線協議加密認證的,而實際上的工作內容是通過socket(不管是wpa_supplicant與上層還是wpa_supplicant與驅動都採用socket通訊)與驅動互動上報資料給使用者,而使用者可以通過socket傳送命令給wpa_supplicant調動驅動來對WiFi晶片操作。 簡單的說,wpa_supplicant就是WiFi驅動和使用者的中轉站外加對協議和加密認證的支援。


Android WiFi系統架構如下圖所示:


wpa_supplicant 程序實現的入口函式為:external/wpa_supplicant_8/wpa_supplicant/main.c中的main函式, 此程式在hardware/libhardware_legacy/wifi/wifi.c中的wifi_start_supplicant_common中被啟動(property_set("ctl.start", daemon_cmd))。

二:Android Wifi 系統架構

        Android WiFi系統引入了wpa_supplicant,它的整個WiFi系統以wpa_supplicant為核心來定義上層使用者介面和下層驅動介面。整個WiFi系統架構如下圖所示:


下面對上圖部分細節做出詳細分析

1.1 WifiService 

     由SystemServer啟動的時候生成的ConnecttivityService建立,負責啟動關閉wpa_supplicant,啟動和關閉WifiMonitor執行緒,把命令下發給wpa_supplicant以及更新WIFI的狀態。

     處理其它模組通過IWifiManager介面傳送過來的遠端WiFi操作。

1.2 WifiMonitor

    負責從wpa_supplicant接收事件通知。

1.3 wpa_supplicant

  1) 讀取配置檔案
  2) 初始化配置引數,驅動函式
  3) 讓驅動scan當前所有的bssid
  4) 檢查掃描的引數是否和使用者設定的相符
  5) 如果相符,通知驅動進行許可權和認證操作
  6) 連上AP

1.4 Wifi驅動模組

     廠商提供的source,主要進行load firware和kernel的wireless進行通訊

1.5 Wifi電源管理模組

     主要控制硬體的GPIO和上下電,讓CPU和Wifi模組之間通過sdio介面或USB介面通訊

1.6 Wifi工作步驟

  1) Wifi啟動
  2) 開始掃描
  3) 顯示掃描的AP
  4) 配置AP
  5) 連線AP
  6) 獲取IP地址
  7) 上網

1.7 Wifi模組程式碼

   1) Wifi Settings應用程式
       packages/apps/Settings/src/com/android/settings/wifi

2) Wifi Framework
       frameworks/base/wifi/java/android/net/wifi (UI通過android.net.wifi package
傳送命令給wifi.c)

       frameworks/base/core/java/android/net(更高一級的網路管理)
       frameworks/base/services/java/com/android/server

   3) Wifi JNI
       frameworks/base/core/jni/android_net_wifi_Wifi.cpp
   
4) Wifi Hardware (wifi管理庫)
       hardware/libhardware_legacy/wifi/wifi.c

   5) wpa_supplicant(wifi  tool)

       external/wpa_supplicant8
    (1) wpa_client (生成庫libwpaclient.so)

            external/wpa_supplicant_8/wpa_supplicant/src/common/wpa_ctrl.c

       (2) wpa_server (生成守護程序wpa_supplicant)

            external/wpa_supplicant_8/wpa_supplicant/main.c
 
  6) Wifi kernel
       net/wireless     drivers/wlan_xxx       arch/arm/mach-xxx/wlan_pm.c


三:WifiService和wpa_supplicant啟動流程。

WifiService和wpa_supplicant啟動流程如下圖所示:


 2.1 狀態變化

• 載入wifi驅動的狀態變化流程如下:

初始狀態:mInitialState

                         |
          mDriverUnloadedState

                         |
      mWaitForP2pDisableState

                         |
mDriverLoadingState(其enter中呼叫WifiNative.loadDriver)

• 啟動wpa_supplicant的狀態變化如下:
   在DriverLoadedState狀態的processMessage中呼叫WifiNative.startSupplicant

3. 生產時自動開啟Wifi

在生產時, 預設Wifi是關閉的,如果需要預設開啟,可修改wifiservice.java中的如下程式碼:

    /**
     * Check if Wi-Fi needs to be enabled and start
     * if needed
     *
     * This function is used only at boot time
     */
    public void checkAndStartWifi() {
        mAirplaneModeOn.set(isAirplaneModeOn());
        mPersistWifiState.set(getPersistedWifiState());
        /* Start if Wi-Fi should be enabled or the saved state indicates Wi-Fi was on */
        boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState();
        Slog.i(TAG, "WifiService starting up with Wi-Fi " +
                (wifiEnabled ? "enabled" : "disabled"));
        setWifiEnabled(wifiEnabled); //強制設定為true

        mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
               makeWifiWatchdogStateMachine(mContext);

    }


 在Android裡,所有的wifi操作都在android.net.wifi包裡,而常用的類也就只用幾個,對於一般的開發人員來說,常用的操作也是有限的,不需要刻意的去記,用的時候現查就ok了。以下是官方API 網址:



以下是一些wifi應用的常用功能程式碼:

package com.yarin.android.Examples_08_08;  
import java.util.List;  
import android.content.Context;  
import android.net.wifi.ScanResult;  
import android.net.wifi.WifiConfiguration;  
import android.net.wifi.WifiInfo;  
import android.net.wifi.WifiManager;  
import android.net.wifi.WifiManager.WifiLock;  
public class WifiAdmin  
{  
    //定義WifiManager物件   
    private WifiManager mWifiManager;  
    //定義WifiInfo物件   
    private WifiInfo mWifiInfo;  
    //掃描出的網路連線列表   
    private List<ScanResult> mWifiList;  
    //網路連線列表   
    private List<WifiConfiguration> mWifiConfiguration;  
    //定義一個WifiLock   
    WifiLock mWifiLock;  
    //構造器   
    public  WifiAdmin(Context context)  
    {  
        //取得WifiManager物件   
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);  
        //取得WifiInfo物件   
        mWifiInfo = mWifiManager.getConnectionInfo();  
    }  
    //開啟WIFI   
    public void OpenWifi()  
    {  
        if (!mWifiManager.isWifiEnabled())  
        {  
            mWifiManager.setWifiEnabled(true);  
              
        }  
    }  
    //關閉WIFI   
    public void CloseWifi()  
    {  
        if (!mWifiManager.isWifiEnabled())  
        {  
            mWifiManager.setWifiEnabled(false);   
        }  
    }  
    //鎖定WifiLock   
    public void AcquireWifiLock()  
    {  
        mWifiLock.acquire();  
    }  
    //解鎖WifiLock   
    public void ReleaseWifiLock()  
    {  
        //判斷時候鎖定   
        if (mWifiLock.isHeld())  
        {  
            mWifiLock.release();  
        }  
    }  
    //建立一個WifiLock   
    public void CreatWifiLock()  
    {  
        mWifiLock = mWifiManager.createWifiLock("Test");  
    }  
    //得到配置好的網路   
    public List<WifiConfiguration> GetConfiguration()  
    {  
        return mWifiConfiguration;  
    }  
    //指定配置好的網路進行連線   
    public void ConnectConfiguration(int index)  
    {  
        //索引大於配置好的網路索引返回   
        if(index > mWifiConfiguration.size())  
        {  
            return;  
        }  
        //連線配置好的指定ID的網路   
        mWifiManager.enableNetwork(mWifiConfiguration.get(index).networkId, true);  
    }  
    public void StartScan()  
    {  
        mWifiManager.startScan();  
        //得到掃描結果   
        mWifiList = mWifiManager.getScanResults();  
        //得到配置好的網路連線   
        mWifiConfiguration = mWifiManager.getConfiguredNetworks();  
    }  
    //得到網路列表   
    public List<ScanResult> GetWifiList()  
    {  
        return mWifiList;  
    }  
    //檢視掃描結果   
    public StringBuilder LookUpScan()  
    {  
        StringBuilder stringBuilder = new StringBuilder();  
        for (int i = 0; i < mWifiList.size(); i++)  
        {  
            stringBuilder.append("Index_"+new Integer(i + 1).toString() + ":");  
            //將ScanResult資訊轉換成一個字串包   
            //其中把包括:BSSID、SSID、capabilities、frequency、level   
            stringBuilder.append((mWifiList.get(i)).toString());  
            stringBuilder.append("/n");  
        }  
        return stringBuilder;  
    }  
    //得到MAC地址   
    public String GetMacAddress()  
    {  
        return (mWifiInfo == null) ? "NULL" : mWifiInfo.getMacAddress();  
    }  
    //得到接入點的BSSID   
    public String GetBSSID()  
    {  
        return (mWifiInfo == null) ? "NULL" : mWifiInfo.getBSSID();  
    }  
    //得到IP地址   
    public int GetIPAddress()  
    {  
        return (mWifiInfo == null) ? 0 : mWifiInfo.getIpAddress();  
    }  
    //得到連線的ID   
    public int GetNetworkId()  
    {  
        return (mWifiInfo == null) ? 0 : mWifiInfo.getNetworkId();  
    }  
    //得到WifiInfo的所有資訊包   
    public String GetWifiInfo()  
    {  
        return (mWifiInfo == null) ? "NULL" : mWifiInfo.toString();  
    }  
    //新增一個網路並連線   
    public void AddNetwork(WifiConfiguration wcg)  
    {  
        int wcgID = mWifiManager.addNetwork(wcg);   
        mWifiManager.enableNetwork(wcgID, true);   
    }  
    //斷開指定ID的網路   
    public void DisconnectWifi(int netId)  
    {  
        mWifiManager.disableNetwork(netId);  
        mWifiManager.disconnect();  
    }  
}  

轉自:http://blog.csdn.net/myarrow/article/category/1269709