wifi分析2

声明:本文纯属网上资料收集,版权归源作者所有,转载时请标明为转载文章

现在对android平台的wifi模块了解了一段时间,现在做一些简要总结,以便以后查阅和与修正,上正文。

【Wifi模块学习流程】

最近研究Wifi模块,查了不少的相关资料,但发现基本上是基于android2.0版本的的分析,而现在研发的android移动平台基本上都是2.3的版本,跟2.0版本的差别,在Wifi模块上也是显而易见的。2.3版本Wifi模块没有了WifiLayer,之前的WifiLayer主要负责一些复杂的Wifi功能,如AP选择等以提供给用户自定义,而新的版本里面的这块内容基本上被WifiSettings所代替

本文就是基于android2.3版本的Wifi分析,主要分为两部分来分别说明:

(a)    Wifi的启动流程(有代码供参考分析)

(b)    Wifi模块相关文件的解析

(c)    Wpa_supplicant解析


【A】wifi的基本运行流程(针对代码而言)

首先给一张我网上down下来的图,针对2.3版本之前的,由于不怎么擅长画这些,大家也就将就点,只要能助理解就可以了

(一)初始化

a.流程

1.在SystemServer启动的时候会生成一个ConnectivityService的实例

2.ConnectivityService的构造函数会创建WifiService

3.WifiStateTracker会创建WifiMonitor接受来自底层的事件,WifiService和WifiMonitor是整个wifi模块的核心,WifiService负责启动和关闭wpa_supplicant,启动和关闭WifiMonitor监视线程和把命令下方给wpa_supplicant,而WifiMonitor则负责从wpa_supplicant接受事件通知

b.代码分析

要想使用Wifi模块,必须首先使能Wifi,当你第一次按下Wifi使能按钮时,WirelessSettings会实例化一个WifiEnabler对象,实例化代码如下:

packages/apps/settings/src/com/android/settings/WirelessSettings.java

  1. protected void onCreate(Bundle savedInstanceState) {  
  2.   
  3.        super.onCreate(savedInstanceState);  
  4. ……  
  5.               CheckBoxPreferencewifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI);  
  6.   
  7.               mWifiEnabler= new WifiEnabler(this, wifi);  
  8. ……  
  9. }  
protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);
……
              CheckBoxPreferencewifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI);

              mWifiEnabler= new WifiEnabler(this, wifi);
……
}
WifiEnabler类的定义大致如下,它实现了一个监听接口,当WifiEnabler对象被初始化后,它监听到你按键的动作,会调用响应函数 onPreferenceChange(),这个函数会调用WifiManager的setWifiEnabled()函数。
  1. public class WifiEnabler implementsPreference.OnPreferenceChangeListener {  
  2.   
  3. ……  
  4.   
  5. public boolean onPreferenceChange(Preference preference,Object value) {  
  6.   
  7.         booleanenable = (Boolean) value;  
  8.   
  9. ……  
  10.   
  11. if (mWifiManager.setWifiEnabled(enable)) {  
  12.                 mCheckBox.setEnabled(false);  
  13. ……  
  14. }  
  15.   
  16. ……  
  17.   
  18. }  
public class WifiEnabler implementsPreference.OnPreferenceChangeListener {

……

public boolean onPreferenceChange(Preference preference,Object value) {

        booleanenable = (Boolean) value;

……

if (mWifiManager.setWifiEnabled(enable)) {
                mCheckBox.setEnabled(false);
……
}

……

}
我们都知道Wifimanager只是个服务代理,所以它会调用WifiService的setWifiEnabled()函数,而这个函数会调用 sendEnableMessage()函数,了解android消息处理机制的都知道,这个函数最终会给自己发送一个  MESSAGE_ENABLE_WIFI的消息,被WifiService里面定义的handlermessage()函数处理,会调用 setWifiEnabledBlocking()函数。下面是调用流程:

mWifiEnabler.onpreferencechange()===>mWifiManage.setWifienabled()===>mWifiService.setWifiEnabled()===>mWifiService.sendEnableMessage()

===>mWifiService.handleMessage()===>mWifiService.setWifiEnabledBlocking().

在setWifiEnabledBlocking()函数中主要做如下工作:加载Wifi驱动,启动wpa_supplicant,注册广播接收器,启动WifiThread监听线程。代码如下:
  1. ……  
  2.   
  3. if (enable) {  
  4.   
  5.            if (!mWifiStateTracker.loadDriver()) {  
  6.   
  7.                Slog.e(TAG, "Failed toload Wi-Fi driver.");  
  8.   
  9.                setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);  
  10.   
  11.                 return false;  
  12.   
  13.            }  
  14.   
  15.            if (!mWifiStateTracker.startSupplicant()) {  
  16.   
  17.                 mWifiStateTracker.unloadDriver();  
  18.   
  19.                 Slog.e(TAG, "Failed tostart supplicant daemon.");  
  20.   
  21.                setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);  
  22.   
  23.                 return false;  
  24.   
  25.            }  
  26.   
  27.    
  28.   
  29.            registerForBroadcasts();  
  30.   
  31.            mWifiStateTracker.startEventLoop();  
  32.   
  33. ……  
……

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();

……
至此,Wifi使能(开启)结束,自动进入扫描阶段。


(二)扫描AP

当驱动加载成功后,如果配置文件的AP_SCAN = 1,扫描会自动开始,WifiMonitor将会从supplicant收到一个消息EVENT_DRIVER_STATE_CHANGED,调用 handleDriverEvent(),然后调用mWifiStateTracker.notifyDriverStarted(),该函数向消息队列添加EVENT_DRIVER_STATE_CHANGED,handlermessage()函数处理消息时调用scan()函数,并通过 WifiNative将扫描命令发送到wpa_supplicant。

看代码Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

  1. private void handleDriverEvent(Stringstate) {  
  2.   
  3.            if (state == null) {  
  4.   
  5.                 return;  
  6.   
  7.            }  
  8.   
  9.            if (state.equals("STOPPED")) {  
  10.   
  11.                mWifiStateTracker.notifyDriverStopped();  
  12.   
  13.            } else if (state.equals("STARTED")) {  
  14.   
  15.                 mWifiStateTracker.notifyDriverStarted();  
  16.   
  17.            } else if (state.equals("HANGED")) {  
  18.   
  19.                 mWifiStateTracker.notifyDriverHung();  
  20.   
  21.            }  
  22.   
  23. }  
private void handleDriverEvent(Stringstate) {

           if (state == null) {

                return;

           }

           if (state.equals("STOPPED")) {

               mWifiStateTracker.notifyDriverStopped();

           } else if (state.equals("STARTED")) {

                mWifiStateTracker.notifyDriverStarted();

           } else if (state.equals("HANGED")) {

                mWifiStateTracker.notifyDriverHung();

           }

}
Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
  1. ...  
  2. case EVENT_DRIVER_STATE_CHANGED:  
  3.   
  4.                 switch(msg.arg1) {  
  5.   
  6.                 case DRIVER_STARTED:  
  7.   
  8.                     /** 
  9.  
  10.                      *Set the number of allowed radio channels according 
  11.  
  12.                      *to the system setting, since it gets reset by the 
  13.  
  14.                      *driver upon changing to the STARTED state. 
  15.  
  16.                      */  
  17.   
  18.                     setNumAllowedChannels();  
  19.   
  20.                    synchronized (this) {  
  21.   
  22.                        if (mRunState == RUN_STATE_STARTING) {  
  23.   
  24.                            mRunState = RUN_STATE_RUNNING;  
  25.   
  26.                            if (!mIsScanOnly) {  
  27.   
  28.                                 reconnectCommand();  
  29.   
  30.                            } else {  
  31.   
  32.                                 // In somesituations, supplicant needs to be kickstarted to  
  33.   
  34.                                 // start thebackground scanning  
  35.   
  36.                                 scan(true);  
  37.   
  38.                            }  
  39.   
  40.                        }  
  41.   
  42.                     }  
  43.   
  44.                    break;               
  45. ...  
...
case EVENT_DRIVER_STATE_CHANGED:

                switch(msg.arg1) {

                case DRIVER_STARTED:

                    /**

                     *Set the number of allowed radio channels according

                     *to the system setting, since it gets reset by the

                     *driver upon changing to the STARTED state.

                     */

                    setNumAllowedChannels();

                   synchronized (this) {

                       if (mRunState == RUN_STATE_STARTING) {

                           mRunState = RUN_STATE_RUNNING;

                           if (!mIsScanOnly) {

                                reconnectCommand();

                           } else {

                                // In somesituations, supplicant needs to be kickstarted to

                                // start thebackground scanning

                                scan(true);

                           }

                       }

                    }

                   break;             
...
上面是启动Wifi时,自动进行的AP的扫描,用户当然也可以手动扫描AP,这部分实现在WifiService里面,WifiService通过startScan()接口函数发送扫描命令到supplicant。

看代码:Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

  1. public boolean startScan(booleanforceActive) {  
  2.   
  3.        enforceChangePermission();  
  4.   
  5.    
  6.   
  7.        switch (mWifiStateTracker.getSupplicantState()) {  
  8.   
  9.            case DISCONNECTED:  
  10.   
  11.            case INACTIVE:  
  12.   
  13.            case SCANNING:  
  14.   
  15.            case DORMANT:  
  16.   
  17.                 break;  
  18.   
  19.            default:  
  20.   
  21.                mWifiStateTracker.setScanResultHandling(  
  22.   
  23.                        WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);  
  24.   
  25.                 break;  
  26.   
  27.        }  
  28.   
  29.        return mWifiStateTracker.scan(forceActive);  
  30.   
  31. }  
public boolean startScan(booleanforceActive) {

       enforceChangePermission();

 

       switch (mWifiStateTracker.getSupplicantState()) {

           case DISCONNECTED:

           case INACTIVE:

           case SCANNING:

           case DORMANT:

                break;

           default:

               mWifiStateTracker.setScanResultHandling(

                       WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);

                break;

       }

       return mWifiStateTracker.scan(forceActive);

}
然后下面的流程同上面的自动扫描,我们来分析一下手动扫描从哪里开始的。我们应该知道手动扫描是通过菜单键的扫描键来响应的,而响应该动作的应该是 WifiSettings类中Scanner类的handlerMessage()函数,它调用WifiManager的 startScanActive(),这才调用WifiService的startScan()。

如代码:packages/apps/Settings/src/com/android/settings/wifiwifisettings.java

  1. public boolean onCreateOptionsMenu(Menu menu) {  
  2.   
  3.        menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)  
  4.   
  5.                .setIcon(R.drawable.ic_menu_scan_network);  
  6.   
  7.        menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)  
  8.   
  9.                .setIcon(android.R.drawable.ic_menu_manage);  
  10.   
  11.        return super.onCreateOptionsMenu(menu);  
  12.   
  13. }  
public boolean onCreateOptionsMenu(Menu menu) {

       menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)

               .setIcon(R.drawable.ic_menu_scan_network);

       menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)

               .setIcon(android.R.drawable.ic_menu_manage);

       return super.onCreateOptionsMenu(menu);

}
当按下菜单键时,WifiSettings就会调用这个函数绘制菜单。如果选择扫描按钮,WifiSettings会调用onOptionsItemSelected()。

packages/apps/Settings/src/com/android/settings/wifiwifisettings.java

  1. public booleanonOptionsItemSelected(MenuItem item) {  
  2.   
  3.        switch (item.getItemId()) {  
  4.   
  5.            case MENU_ID_SCAN:  
  6.   
  7.                 if(mWifiManager.isWifiEnabled()) {  
  8.   
  9.                     mScanner.resume();  
  10.   
  11.                 }  
  12.   
  13.                 return true;  
  14.   
  15.            case MENU_ID_ADVANCED:  
  16.   
  17.                 startActivity(new Intent(this,AdvancedSettings.class));  
  18.   
  19.                 return true;  
  20.   
  21.        }  
  22.   
  23.        return super.onOptionsItemSelected(item);  
  24.   
  25. }  
public booleanonOptionsItemSelected(MenuItem item) {

       switch (item.getItemId()) {

           case MENU_ID_SCAN:

                if(mWifiManager.isWifiEnabled()) {

                    mScanner.resume();

                }

                return true;

           case MENU_ID_ADVANCED:

                startActivity(new Intent(this,AdvancedSettings.class));

                return true;

       }

       return super.onOptionsItemSelected(item);

}
Handler类:
  1. private class Scanner extends Handler {  
  2.   
  3.        private int mRetry = 0;  
  4.   
  5.        void resume() {  
  6.   
  7.            if (!hasMessages(0)) {  
  8.   
  9.                 sendEmptyMessage(0);  
  10.   
  11.            }  
  12.   
  13.        }  
  14.   
  15.        void pause() {  
  16.   
  17.            mRetry = 0;  
  18.   
  19.             mAccessPoints.setProgress(false);  
  20.   
  21.            removeMessages(0);  
  22.   
  23.        }  
  24.   
  25.    
  26.        @Override  
  27.   
  28.        public void handleMessage(Message message) {  
  29.   
  30.            if (mWifiManager.startScanActive()){  
  31.   
  32.                 mRetry = 0;  
  33.   
  34.            } else if (++mRetry >= 3) {  
  35.   
  36.                 mRetry = 0;  
  37.   
  38.                Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,  
  39.   
  40.                        Toast.LENGTH_LONG).show();  
  41.   
  42.                 return;  
  43.   
  44.            }  
  45.   
  46.            mAccessPoints.setProgress(mRetry != 0);  
  47.   
  48.            sendEmptyMessageDelayed(06000);  
  49.   
  50.        }  
  51.   
  52. }  
private class Scanner extends Handler {

       private int mRetry = 0;

       void resume() {

           if (!hasMessages(0)) {

                sendEmptyMessage(0);

           }

       }

       void pause() {

           mRetry = 0;

            mAccessPoints.setProgress(false);

           removeMessages(0);

       }

 
       @Override

       public void handleMessage(Message message) {

           if (mWifiManager.startScanActive()){

                mRetry = 0;

           } else if (++mRetry >= 3) {

                mRetry = 0;

               Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,

                       Toast.LENGTH_LONG).show();

                return;

           }

           mAccessPoints.setProgress(mRetry != 0);

           sendEmptyMessageDelayed(0, 6000);

       }

}
这里的mWifiManager.startScanActive()就会调用WifiService里的startScan()函数,下面的流程和上面的一样,这里不赘述。

当supplicant完成了这个扫描命令后,它会发送一个消息给上层,提醒他们扫描已经完成,WifiMonitor会接收到这消息,然后再发送给WifiStateTracker。

Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

  1. void handleEvent(int event, String remainder) {  
  2.   
  3.             switch (event) {  
  4.   
  5.                 caseDISCONNECTED:  
  6.   
  7.                    handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);  
  8.   
  9.                     break;  
  10.   
  11.                 case CONNECTED:  
  12.   
  13.                    handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);  
  14.   
  15.                     break;  
  16.   
  17.                 case SCAN_RESULTS:  
  18.   
  19.                     mWifiStateTracker.notifyScanResultsAvailable();  
  20.   
  21.                     break;  
  22.   
  23.                 case UNKNOWN:  
  24.   
  25.                     break;  
  26.   
  27.             }  
  28.   
  29. }  
void handleEvent(int event, String remainder) {

            switch (event) {

                caseDISCONNECTED:

                   handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);

                    break;

                case CONNECTED:

                   handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);

                    break;

                case SCAN_RESULTS:

                    mWifiStateTracker.notifyScanResultsAvailable();

                    break;

                case UNKNOWN:

                    break;

            }

}
WifiStateTracker将会广播SCAN_RESULTS_AVAILABLE_ACTION消息:

代码如:Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

  1. public voidhandleMessage(Message msg) {  
  2.   
  3.         Intent intent;  
  4.   
  5. ……  
  6.   
  7. case EVENT_SCAN_RESULTS_AVAILABLE:  
  8.   
  9.                 if(ActivityManagerNative.isSystemReady()) {  
  10.   
  11.                     mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));  
  12.   
  13.                 }  
  14.   
  15.                 sendScanResultsAvailable();  
  16.   
  17.                 /** 
  18.  
  19.                  * On receiving the first scanresults after connecting to 
  20.  
  21.                  * the supplicant, switch scanmode over to passive. 
  22.  
  23.                  */  
  24.   
  25.                 setScanMode(false);  
  26.   
  27.                 break;  
  28.   
  29. ……  
  30.   
  31. }  
public voidhandleMessage(Message msg) {

        Intent intent;

……

case EVENT_SCAN_RESULTS_AVAILABLE:

                if(ActivityManagerNative.isSystemReady()) {

                    mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

                }

                sendScanResultsAvailable();

                /**

                 * On receiving the first scanresults after connecting to

                 * the supplicant, switch scanmode over to passive.

                 */

                setScanMode(false);

                break;

……

}
由于WifiSettings类注册了intent,能够处理SCAN_RESULTS_AVAILABLE_ACTION消息,它会调用handleEvent(),调用流程如下所示。

WifiSettings.handleEvent() ====>WifiSettings.updateAccessPoints() ====> mWifiManager.getScanResults()====> mService.getScanResults()====> mWifiStateTracker.scanResults() ====> WifiNative.scanResultsCommand()……
将获取AP列表的命令发送到supplicant,然后supplicant通过Socket发送扫描结果,由上层接收并显示。这和前面的消息获取流程基本相同。


(3)配置,连接AP
当用户选择一个活跃的AP时,WifiSettings响应打开一个对话框来配置AP,比如加密方法和连接AP的验证模式。配置好AP后,WifiService添加或更新网络连接到特定的AP。
代码如:packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java

  1. public booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference) {  
  2.   
  3.        if (preference instanceof AccessPoint) {  
  4.   
  5.            mSelected = (AccessPoint) preference;  
  6.   
  7.            showDialog(mSelected, false);  
  8.   
  9.        } else if (preference == mAddNetwork) {  
  10.   
  11.            mSelected = null;  
  12.   
  13.            showDialog(nulltrue);  
  14.   
  15.        } else if (preference == mNotifyOpenNetworks) {  
  16.   
  17.            Secure.putInt(getContentResolver(),  
  18.   
  19.                    Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,  
  20.   
  21.                    mNotifyOpenNetworks.isChecked() ? 1 : 0);  
  22.   
  23.        } else {  
  24.   
  25.            return super.onPreferenceTreeClick(screen, preference);  
  26.   
  27.        }  
  28.   
  29.        return true;  
  30.   
  31. }  
public booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference) {

       if (preference instanceof AccessPoint) {

           mSelected = (AccessPoint) preference;

           showDialog(mSelected, false);

       } else if (preference == mAddNetwork) {

           mSelected = null;

           showDialog(null, true);

       } else if (preference == mNotifyOpenNetworks) {

           Secure.putInt(getContentResolver(),

                   Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,

                   mNotifyOpenNetworks.isChecked() ? 1 : 0);

       } else {

           return super.onPreferenceTreeClick(screen, preference);

       }

       return true;

}
配置好以后,当按下“Connect Press”时,WifiSettings通过发送LIST_NETWORK命令到supplicant来检查该网络是否配置。如果没有该网络或没有配置它,WifiService调用addorUpdateNetwork()函数来添加或更新网络,然后发送命令给supplicant,连接到这个网络。下面是从响应连接按钮到WifiService发送连接命令的代码:

packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java

  1. public void onClick(DialogInterfacedialogInterface, int button) {  
  2.   
  3.        if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {  
  4.   
  5.            forget(mSelected.networkId);  
  6.   
  7.        } else if (button == WifiDialog.BUTTON_SUBMIT && mDialog !=null) {  
  8.   
  9.            WifiConfiguration config = mDialog.getConfig();  
  10.   
  11.    
  12.   
  13.            if (config == null) {  
  14.   
  15.                 if (mSelected != null&& !requireKeyStore(mSelected.getConfig())) {  
  16.   
  17.                     connect(mSelected.networkId);  
  18.   
  19.                 }  
  20.   
  21.            } else if (config.networkId != -1) {  
  22.   
  23.                 if (mSelected != null) {  
  24.   
  25.                     mWifiManager.updateNetwork(config);  
  26.   
  27.                     saveNetworks();  
  28.   
  29.                 }  
  30.   
  31.            } else {  
  32.   
  33.                 int networkId =mWifiManager.addNetwork(config);  
  34.   
  35.                 if (networkId != -1) {  
  36.   
  37.                    mWifiManager.enableNetwork(networkId, false);  
  38.   
  39.                     config.networkId =networkId;  
  40.   
  41.                     if (mDialog.edit || requireKeyStore(config)){  
  42.   
  43.                         saveNetworks();  
  44.   
  45.                     } else {  
  46.   
  47.                         connect(networkId);  
  48.   
  49.                     }  
  50.   
  51.                 }  
  52.   
  53.            }  
  54.   
  55.        }  
  56. }  
public void onClick(DialogInterfacedialogInterface, int button) {

       if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {

           forget(mSelected.networkId);

       } else if (button == WifiDialog.BUTTON_SUBMIT && mDialog !=null) {

           WifiConfiguration config = mDialog.getConfig();

 

           if (config == null) {

                if (mSelected != null&& !requireKeyStore(mSelected.getConfig())) {

                    connect(mSelected.networkId);

                }

           } else if (config.networkId != -1) {

                if (mSelected != null) {

                    mWifiManager.updateNetwork(config);

                    saveNetworks();

                }

           } else {

                int networkId =mWifiManager.addNetwork(config);

                if (networkId != -1) {

                   mWifiManager.enableNetwork(networkId, false);

                    config.networkId =networkId;

                    if (mDialog.edit || requireKeyStore(config)){

                        saveNetworks();

                    } else {

                        connect(networkId);

                    }

                }

           }

       }
}
Frameworks\base\wifi\java\android\net\wifi\WifiManager.java
  1. public intupdateNetwork(WifiConfiguration config) {  
  2.   
  3.         if(config == null || config.networkId < 0) {  
  4.   
  5.            return -1;  
  6.   
  7.         }  
  8.   
  9.         return addOrUpdateNetwork(config);  
  10.   
  11. }  
  12.   
  13. private intaddOrUpdateNetwork(WifiConfiguration config) {  
  14.   
  15.        try {  
  16.   
  17.            return mService.addOrUpdateNetwork(config);  
  18.   
  19.        } catch (RemoteException e) {  
  20.   
  21.            return -1;  
  22.   
  23.        }  
  24.   
  25. }  
public intupdateNetwork(WifiConfiguration config) {

        if(config == null || config.networkId < 0) {

           return -1;

        }

        return addOrUpdateNetwork(config);

}

private intaddOrUpdateNetwork(WifiConfiguration config) {

       try {

           return mService.addOrUpdateNetwork(config);

       } catch (RemoteException e) {

           return -1;

       }

}
WifiService.addOrUpdateNetwork()通过调用mWifiStateTracker.setNetworkVariable()将连接命令发送到Wpa_supplicant。


(4)获取IP地址
当连接到supplicant后,WifiMonitor就会通知WifiStateTracker。

代码如:Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java

  1. Public void Run(){  
  2.   
  3. if (connectToSupplicant()) {  
  4.   
  5.                 // Send a message indicatingthat it is now possible to send commands  
  6.   
  7.                 // to the supplicant  
  8.   
  9.                 mWifiStateTracker.notifySupplicantConnection();  
  10.   
  11.            } else {  
  12.   
  13.                mWifiStateTracker.notifySupplicantLost();  
  14.   
  15.                 return;  
  16.   
  17.            }  
  18.   
  19. ……  
  20.   
  21. }  
Public void Run(){

if (connectToSupplicant()) {

                // Send a message indicatingthat it is now possible to send commands

                // to the supplicant

                mWifiStateTracker.notifySupplicantConnection();

           } else {

               mWifiStateTracker.notifySupplicantLost();

                return;

           }

……

}
WifiStateTracker发送EVENT_SUPPLICANT_CONNECTION消息到消息队列,这个消息有自己的handlermessage()函数处理,它会启动一个DHCP线程,而这个线程会一直等待一个消息事件,来启动DHCP协议分配IP地址。

frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java

  1. void notifySupplicantConnection() {  
  2.   
  3.        sendEmptyMessage(EVENT_SUPPLICANT_CONNECTION);  
  4.   
  5. }  
  6.   
  7.    
  8.   
  9. public void handleMessage(Message msg) {  
  10.   
  11.        Intent intent;  
  12.   
  13.     switch (msg.what) {  
  14.   
  15.            case EVENT_SUPPLICANT_CONNECTION:  
  16.   
  17.              ……  
  18.   
  19.              HandlerThread dhcpThread = newHandlerThread("DHCP Handler Thread");  
  20.   
  21.                 dhcpThread.start();  
  22.   
  23.                 mDhcpTarget = newDhcpHandler(dhcpThread.getLooper(), this);  
  24.        ……  
  25.   
  26.        ……  
  27.           <pre class="java" name="code">           case EVENT_NETWORK_STATE_CHANGED:  
  28.   
  29.              ……  
  30.   
  31.                configureInterface();  
  32.   
  33.              ……</pre><br>  
  34.        }}<br>  
  35. <pre class="java" name="code">private void configureInterface() {  
  36.   
  37.        checkPollTimer();  
  38.   
  39.         mLastSignalLevel = -1;  
  40.   
  41.         if(!mUseStaticIp) {          //使用DHCP线程动态IP  
  42.   
  43.             if(!mHaveIpAddress && !mObtainingIpAddress) {  
  44.   
  45.                mObtainingIpAddress = true;  
  46.   
  47.                 //发送启动DHCP线程获取IP  
  48.                 mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);  
  49.   
  50.             }  
  51.   
  52.         } else {        //使用静态IP,IP信息从mDhcpInfo中获取  
  53.   
  54.             intevent;  
  55.   
  56.             if(NetworkUtils.configureInterface(mInterfaceName, mDhcpInfo)) {  
  57.   
  58.                mHaveIpAddress = true;  
  59.   
  60.                event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;  
  61.   
  62.                if (LOCAL_LOGD) Log.v(TAG, "Static IP configurationsucceeded");  
  63.   
  64.             }else {  
  65.   
  66.                mHaveIpAddress = false;  
  67.   
  68.                event = EVENT_INTERFACE_CONFIGURATION_FAILED;  
  69.   
  70.                if (LOCAL_LOGD) Log.v(TAG, "Static IP configuration failed");  
  71.   
  72.             }  
  73.   
  74.            sendEmptyMessage(event);           //发送IP获得成功消息事件  
  75.   
  76.         }  
  77.   
  78. }</pre><br>  
  79. <pre></pre>  
  80. 当Wpa_supplicant连接到AP后,它会发送一个消息给上层来通知连接成功,WifiMonitor会接受到这个消息并上报给WifiStateTracker。  
  81. <p>Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java</p>  
  82. <pre class="java" name="code">void handleEvent(int event, String remainder) {  
  83.   
  84.            switch (event) {  
  85.   
  86.                case DISCONNECTED:  
  87.   
  88.                    handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);  
  89.   
  90.                    break;  
  91.   
  92.                case CONNECTED:  
  93.   
  94.                    handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);  
  95.   
  96.                    break;  
  97.                 ……  
  98.     }  
  99.   
  100.    
  101.   
  102. private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) {  
  103.   
  104.         StringBSSID = null;  
  105.   
  106.         intnetworkId = -1;  
  107.   
  108.         if(newState == NetworkInfo.DetailedState.CONNECTED) {  
  109.   
  110.            Matcher match = mConnectedEventPattern.matcher(data);  
  111.   
  112.             if(!match.find()) {  
  113.   
  114.                if (Config.LOGD) Log.d(TAG, "Could not find BSSID in CONNECTEDevent string");  
  115.   
  116.             }else {  
  117.   
  118.                BSSID = match.group(1);  
  119.   
  120.                try {  
  121.   
  122.                    networkId = Integer.parseInt(match.group(2));  
  123.   
  124.                } catch (NumberFormatException e) {  
  125.   
  126.                    networkId = -1;  
  127.   
  128.                 }  
  129.   
  130.             }  
  131.   
  132.         }  
  133.   
  134.         mWifiStateTracker.notifyStateChange(newState,BSSID, networkId);  
  135.   
  136. }  
  137.   
  138.         
  139.   
  140. void notifyStateChange(DetailedState newState, StringBSSID, int networkId) {  
  141.   
  142.         Messagemsg = Message.obtain(  
  143.   
  144.            this, EVENT_NETWORK_STATE_CHANGED,  
  145.   
  146.             newNetworkStateChangeResult(newState, BSSID, networkId));  
  147.   
  148.        msg.sendToTarget();  
  149.   
  150. }  
  151.   
  152.   
  153. </pre>DhcpThread获取EVENT_DHCP_START消息事件后,调用handleMessage()函数,启动DHCP获取IP地址的服务。  
  154. <p>frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java<br>  
  155. </p>  
  156. <pre class="java" name="code">public void handleMessage(Message msg) {  
  157.   
  158.             intevent;  
  159.   
  160.     switch (msg.what) {  
  161.   
  162.                case EVENT_DHCP_START:  
  163.   
  164.     ……  
  165.   
  166.     Log.d(TAG, "DhcpHandler: DHCP requeststarted");  
  167.   
  168.        
  169.   
  170.     //启动一个DHCPclient的精灵进程,为mInterfaceName请求分配一个IP地//址  
  171.   
  172.         if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {  
  173.   
  174.          event= EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;  
  175.   
  176.          if(LOCAL_LOGD) Log.v(TAG, "DhcpHandler: DHCP request succeeded");  
  177.   
  178.         } else {  
  179.   
  180.            event= EVENT_INTERFACE_CONFIGURATION_FAILED;  
  181.   
  182.            Log.i(TAG,"DhcpHandler: DHCP request failed: " +  
  183.   
  184.                             NetworkUtils.getDhcpError());  
  185.   
  186.         }  
  187.   
  188.     ……  
  189.   
  190.     }  
  191. }</pre>这里调用了一个NetworkUtils.runDhcp()函数,NetworkUtils类是一个网络服务的辅助类,它主要定义了一些本地接口,这些接口会通过他们的JNI层android_net_NetUtils.cpp文件和DHCP client通信,并获取IP地址。  
  192. <p>至此,IP地址获取完毕,Wifi启动流程结束。<br>  
  193. <br>  
  194. <br>  
  195. <br>  
  196. 待续</p>  
  197. <p>(b)    Wifi模块相关文件的解析<br>  
  198. </p>  
  199. <p>(c)    Wpa_supplicant解析</p>  
  200. <br>  
  201. <br>  
  202. <br>  
  203. <p><br>  
  204. </p>  
  205. <br>  
  206. <pre></pre>  
  207. <pre></pre>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值