wifi基礎知識及原理


wifi相關的文件位置:

WIFI Settings應用程序位於

       packages/apps/Settings/src/com/android/settings/wifi/

JAVA部分:

        frameworks/base/services/java/com/android/server/

        frameworks/base/wifi/java/android/net/wifi/

JNI部分:

       frameworks/base/core/jni/android_net_wifi_Wifi.cpp

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 的實例,

classServerThread 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.JavaConnectivityService.Java。

下面看下ConnectivityService.Java中的  

 public static ConnectivityServicegetInstance(Context context) {

       return ConnectivityThread.getServiceInstance(context);

   }函數, 繼續往下看:

       public static ConnectivityService getServiceInstance(Context context) {

           ConnectivityThread thread = newConnectivityThread(context);

            thread.start();

           synchronized (thread) {

               while (sServiceInstance == null) {

                    try {

                        // Wait until sServiceInstance has beeninitialized.

                        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;

        }

       @Override

        public void run() {

           Looper.prepare();

           synchronized (this) {

               sServiceInstance = newConnectivityService(mContext);

               notifyAll();

           }

            Looper.loop();

        }

       public static ConnectivityService getServiceInstance(Context context) {

           ConnectivityThread thread = new ConnectivityThread(context);

           thread.start();

           synchronized (thread) {

                while (sServiceInstance == null) {

                    try {

                        // Wait untilsServiceInstance has been initialized.

                        thread.wait();

                    } catch(InterruptedException ignore) {

                        Slog.e(TAG,

                            "UnexpectedInterruptedException while waiting"+

                            " forConnectivityService thread");

                    }

               }

           }

           return sServiceInstance;

        }

    }

繼續newConnectivityService(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 = newWifiStateTracker(context, mHandler);

               WifiService wifiService = newWifiService(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 {

            returnmService.setWifiEnabled(enabled);

        } catch(RemoteException e) {

            returnfalse;

        }

    }

 

      當用戶按下 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 WifiHandlerextends Handler {

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

public voidhandleMessage(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地址的配置
流程如圖:

 

到此結束。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM