Android Wifi工作流程_第1页
Android Wifi工作流程_第2页
Android Wifi工作流程_第3页
Android Wifi工作流程_第4页
Android Wifi工作流程_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Android Wifi的工作流程一、WIFI工作相关部分Wifi 网卡状态1.    WIFI_STATE_DISABLED: WIFI网卡不可用2.    WIFI_STATE_DISABLING: WIFI正在关闭3.    WIFI_STATE_ENABLED:WIFI网卡可用4.    WIFI_STATE_ENABLING:WIFI网卡正在打开5.    WIFI_STATE

2、_UNKNOWN:未知网卡状态 WIFI 访问网络需要的权限"android.permission.CHANGE_NETWORK_STATE">修改网络状态的权限 android:name="android.permission.CHANGE_WIFI_STATE">修改WIFI状态的权限"android.permission.ACCESS_NETWORK_STATE">访问网络权限"android.permission.ACCESS_WIFI_STATE">访问WIFI

3、权限 WIFI 核心模块n  WifiService由SystemServer启动的时候生成的ConnecttivityService创建,负责启动关闭wpa_supplicant,启动和关闭WifiMonitor线程,把命令下发给wpa_supplicant以及跟新WIFI的状态n  WifiMonitor  负责从wpa_supplicant接收事件通知n  Wpa_supplicant1、读取配置文件2、初始化配置参数,驱动函数3、让驱动scan当前所有的bssid4、检查扫描的参数是否和用户设置的

4、想否5、如果相符,通知驱动进行权限 认证操作6、连上APn  Wifi驱动模块厂商提供的source,主要进行load firmware和kernel的wireless进行通信n  Wifi电源管理模块主要控制硬件的GPIO和上下电,让CPU和Wifi模组之间通过sdio接口通信 二、Wifi工作步骤1  Wifi模块初期化2  Wifi启动3  查找热点(AP)4  配置AP5   配置AP参数6   Wifi连接7  &#

5、160;IP地址配置三、WIFI的架构和流程1、WIFI的基本架构   1、wifi用户空间的程序和库:         external/wpa_supplicant/       生成库libwpaclient.so和守护进程wpa_supplicant   2、hardware/libhardware_legary/wifi/是wifi管理库  

6、60;3、JNI部分:         frameworks/base/core/jni/android_net_wifi_Wifi.cpp   4、JAVA部分:         frameworks/base/services/java/com/android/server/         f

7、rameworks/base/wifi/java/android/net/wifi/   5、WIFI Settings应用程序位于:       packages/apps/Settings/src/com/android/settings/wifi/   6、WIFI 驱动模块  wlan.ko        wpa_supplicant通过wireless_ext 接口和

8、驱动通信   7、WIFI 硬件模块 2、WIFI在Android中如何工作       Android使用一个修改版wpa_supplicant作为daemon来控制WIFI,代码位于external/wpa_supplicant。wpa_supplicant是通过socket与hardware/libhardware_legacy/wifi/wifi.c通信。UI通过.wifi package(frameworks/base/wifi/java/android/net/wifi/)

9、发送命令给wifi.c。相应的JNI实现位于frameworks/base/core/jni/android_net_wifi_Wifi.cpp。更高一级的网络管理位于frameworks/base/core/java/android/net。3、配置Android支持WIFI   在BoardConfig.mk中添加:      BOARD_HAVE_WIFI := true      BOARD_WPA_SUPPLICANT_DRIVER :

10、= WEXT   这将在external/wpa_supplicant/Android.mk设置WPA_BUILD_SUPPLICANT为true,默认使用驱动driver_wext.c。   如果使用定制的wpa_supplicant驱动(例如 wlan0),可以设置:       BOARD_WPA_SUPPLICANT_DRIVER := wlan04、使能wpa_supplicant调试信息   默认wpa_supplicant

11、设置为MSG_INFO,为了输出更多信息,可修改:   1、在common.c中设置wpa_debug_level = MSG_DEBUG;   2、在common.c中把#define wpa_printf宏中的      if (level) >= MSG_INFO)      改为      if (level) >= MSG_DEBUG)

12、5、配置wpa_supplicant.conf   wpa_supplicant是通过wpa_supplicant.conf中的ctrl_interface=来指定控制socket的,应该在 AndroidBoard.mk中配置好复制到$(TARGET_OUT_ETC)/wifi(也就是/system/etc/wifi/wpa_supplicant.conf)这个位置会在init.rc中再次检测的。   一般的wpa_supplicant.conf配置为:      ctrl

13、_interface=DIR=/data/system/wpa_supplicant GROUP=wifi      update_config=1      fast_reauth=1     有时,驱动需要增加:      ap_scan=1   如果遇到AP连接问题,需要修改ap_scan=0来让驱动连接,代替wpa_supplicant。&

14、#160;  如果要连接到non-WPA or open wireless networks,要增加:      network=              key_mgmt=NONE      6、配置路径和权限   Google修改的wpa_supplicant要运行在wifi用户和组

15、下的。代码可见wpa_supplicant/os_unix.c   中的os_program_init()函数。     如果配置不对,会出现下面错误:      E/WifiHW  (  ): Unable to open connection to supplicant on      "/data/system/wpa_supplicant/wlan0"

16、;: No such file or directory will appear.   确认init.rc中有如下配置:       mkdir /system/etc/wifi 0770 wifi wifi       chmod 0770 /system/etc/wifi       chmod 0660 /system/etc/wifi/wpa_sup

17、plicant.conf       chown wifi wifi /system/etc/wifi/wpa_supplicant.conf       # wpa_supplicant socket       mkdir /data/system/wpa_supplicant 0771 wifi wifi      

18、60;chmod 0771 /data/system/wpa_supplicant       #wpa_supplicant control socket for android wifi.c       mkdir /data/misc/wifi 0770 wifi wifi       mkdir /data/misc/wifi/sockets 0770 wifi wifi

19、0;      chmod 0770 /data/misc/wifi       chmod 0660 /data/misc/wifi/wpa_supplicant.conf   如果系统的/system目录为只读,那应该使用路径/data/misc/wifi/wpa_supplicant.conf。7、运行wpa_supplicant和dhcpcd   在init.rc中确保有如下语句: 

20、60;    service wpa_supplicant /system/bin/logwrapper /system/bin/wpa_supplicant -dd                   -Dwext -iwlan0 -c /data/misc/wifi/wpa_supplicant.conf     

21、    user root         group wifi inet      socket wpa_wlan0 dgram 660 wifi wifi         oneshot      service dhcpcd /system/bin/lo

22、gwrapper /system/bin/dhcpcd -d -B wlan0         disabled         oneshot   根据所用的WIFI驱动名字,修改wlan0为自己驱动的名字。8、编译WIFI驱动为module或kernel built in   1、编译为module    

23、0; 在BoardConfig.mk中添加:         WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/xxxx.ko"         WIFI_DRIVER_MODULE_ARG := ""  #for example nohwcrypt     &#

24、160;   WIFI_DRIVER_MODULE_NAME := "xxxx"  #for example wlan0          WIFI_FIRMWARE_LOADER := ""            2、编译为kernel built in     &#

25、160; 1)在hardware/libhardware_legacy/wifi/wifi.c要修改interface名字,     2)在init.rc中添加:        setprop erface "wlan0"     3)在hardware/libhardware_legacy/wifi/wifi.c中当insmod/rmmod时,  &

26、#160;     直接return 0。9、WIFI需要的firmware   Android不使用标准的hotplug binary,WIFI需要的firmware要复制到/etc/firmware。   或者复制到WIFI驱动指定的位置,然后WIFI驱动会自动加载。10、修改WIFI驱动适合Android   Google修改的wpa_supplicant要求SIOCSIWPRIV ioctl发送命令到驱动,及接收信息,例如signal streng

27、th, mac address of the AP, link speed等。所以要正确实现WIFI驱动,需要从SIOCSIWPRIV ioctl返回RSSI (signal strength)和MACADDR信息。    如果没实现这个ioctl,会出现如下错误:     E/wpa_supplicant(  ): wpa_driver_priv_driver_cmd failed         

28、60;                     wpa_driver_priv_driver_cmd RSSI len = 4096      E/wpa_supplicant(  ): wpa_driver_priv_driver_cmd failed     

29、60;D/wpa_supplicant(  ): wpa_driver_priv_driver_cmd LINKSPEED len = 4096     E/wpa_supplicant(  ): wpa_driver_priv_driver_cmd failed      I/wpa_supplicant(  ): CTRL-EVENT-DRIVER-STATE HANGED10、设置dhcpcd.conf   一般/sys

30、tem/etc/dhcpcd/dhcpcd.conf的配置为:      interface wlan0      option subnet_mask, routers, domain_name_server四、WIFI模块分析Wifi模块学习流程最近研究Wifi模块,查了不少的相关资料,但发现基本上是基于android2.0版本的的分析,而现在研发的android移动平台基本上都是2.3的版本,跟2.0版本的差别,在Wifi模块上也是显而易见的。2.3版本Wifi模块没有

31、了WifiLayer,之前的WifiLayer主要负责一些复杂的Wifi功能,如AP选择等以提供给用户自定义,而新的版本里面的这块内容基本上被WifiSettings所代替本文就是基于android2.3版本的Wifi分析,主要分为两部分来分别说明:(a)    Wifi的启动流程(有代码供参考分析)(b)    Wifi模块相关文件的解析(c)    Wpa_supplicant解析Awifi的基本运行流程(针对代码而言)首先给一张我网上down下来的图,针对2.3版本之前

32、的,由于不怎么擅长画这些,大家也就将就点,只要能助理解就可以了(一)初始化a.流程1.在SystemServer启动的时候会生成一个ConnectivityService的实例2.ConnectivityService的构造函数会创建WifiService3.WifiStateTracker会创建WifiMonitor接受来自底层的事件,WifiService和WifiMonitor是整个wifi模块的核心,WifiService负责启动和关闭wpa_supplicant,启动和关闭WifiMonitor监视线程和把命令下方给wpa_supplicant,而WifiMonitor则负责从wpa

33、_supplicant接受事件通知b.代码分析要想使用Wifi模块,必须首先使能Wifi,当你第一次按下Wifi使能按钮时,WirelessSettings会实例化一个WifiEnabler对象,实例化代码如下:packages/apps/settings/src/com/android/settings/WirelessSettings.javajava view plaincopy1. protected void onCreate(Bundle savedInstanceState)   2.   

34、3.        super.onCreate(savedInstanceState);  4.   5.               CheckBoxPreferencewifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI);  6

35、.   7.               mWifiEnabler= new WifiEnabler(this, wifi);  8.   9.   WifiEnabler类的定义大致如下,它实现了一个监听接口,当WifiEnabler对象被初始化后,它监听到你按键的动作,会调用响应函数 onPreferenceChange(),这个函数会调用Wi

36、fiManager的setWifiEnabled()函数。java view plaincopy1. public class WifiEnabler implementsPreference.OnPreferenceChangeListener    2.  3. public boolean onPreferenceChange(Preference preference,Object value)   4.    

37、60;    booleanenable = (Boolean) value;    5.  6. if (mWifiManager.setWifiEnabled(enable)   7.                 mCheckBox.setEnabled(false); 

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

39、eferencechange()=>mWifiManage.setWifienabled()=>mWifiService.setWifiEnabled()=>mWifiService.sendEnableMessage()=>mWifiService.handleMessage()=>mWifiService.setWifiEnabledBlocking().在setWifiEnabledBlocking()函数中主要做如下工作:加载Wifi驱动,启动wpa_supplicant,注册广播接收器,启动WifiThread监听线程。代码如下:1.  2.

40、if (enable)  3.            if (!mWifiStateTracker.loadDriver()   4.                Slog.e(TAG, "Failed toload Wi-Fi 

41、;driver.");  5.                setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);   6.                 return false; 

42、60;7.              8.            if (!mWifiStateTracker.startSupplicant()   9.                &

43、#160;mWifiStateTracker.unloadDriver();  10.                 Slog.e(TAG, "Failed tostart supplicant daemon.");   11.          

44、      setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);   12.                 return false;  13.              

45、;14.            registerForBroadcasts();  15.            mWifiStateTracker.startEventLoop();  16.   至此,Wifi使能(开启)结束,自动进入扫描阶段。(二)扫描AP当驱动加载成功后,如果配置文件的AP_SCAN = 1,扫描会自动开始,Wi

46、fiMonitor将会从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.javajava

47、0;view plaincopy1. private void handleDriverEvent(Stringstate)   2.            if (state = null)   3.                 re

48、turn;  4.              5.            if (state.equals("STOPPED")   6.               &

49、#160;mWifiStateTracker.notifyDriverStopped();  7.             else if (state.equals("STARTED")   8.                 mWifiStat

50、eTracker.notifyDriverStarted();  9.             else if (state.equals("HANGED")   10.                 mWifiStateTracker.notif

51、yDriverHung();  11.              12.   Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.javajava view plaincopy1. .  2. case EVENT_DRIVER_STATE_CHANGED:  3.      &#

52、160;          switch(msg.arg1)   4.                 case DRIVER_STARTED:  5.             &

53、#160;         6.                     setNumAllowedChannels();  7.               

54、     synchronized (this)   8.                        if (mRunState = RUN_STATE_STARTING)   9.     &#

55、160;                      mRunState = RUN_STATE_RUNNING;  10.                    

56、;        if (!mIsScanOnly)   11.                                 reconnectCommand();

57、 12.                             else   13.                  

58、;               / In somesituations, supplicant needs to be kickstarted to  14.                 

59、;                / start thebackground scanning  15.                        

60、0;        scan(true);  16.                              17.          &

61、#160;               18.                       19.             

62、60;      break;               20. .  上面是启动Wifi时,自动进行的AP的扫描,用户当然也可以手动扫描AP,这部分实现在WifiService里面,WifiService通过startScan()接口函数发送扫描命令到supplicant。看代码:Frameworks/base/wifi/java/android/net/wifi

63、/WifiStateTracker.javajava view plaincopy1. public boolean startScan(booleanforceActive)   2.        enforceChangePermission();  3.        switch (mWifiStateTracker.getSupplicantState()  

64、60;4.            case DISCONNECTED:  5.            case INACTIVE:   6.            case SCANNING:  7.

65、            case DORMANT: 8.                 break;  9.            default:  10.  

66、60;             mWifiStateTracker.setScanResultHandling(  11.                        WifiStateTracker.SUPPL_SCAN_HA

67、NDLING_LIST_ONLY);  12.                 break;  13.          14.        return mWifiStateTracker.scan(forceActive);  15. 

68、0; 然后下面的流程同上面的自动扫描,我们来分析一下手动扫描从哪里开始的。我们应该知道手动扫描是通过菜单键的扫描键来响应的,而响应该动作的应该是 WifiSettings类中Scanner类的handlerMessage()函数,它调用WifiManager的 startScanActive(),这才调用WifiService的startScan()。如代码:packages/apps/Settings/src/com/android/settings/wifiwifisettings.javajava view plaincopy1. public boolea

69、n onCreateOptionsMenu(Menu menu)   2.        menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)  3.                .setIcon(R.drawable.ic_m

70、enu_scan_network);  4.        menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)  5.                .setIcon(android.R.drawable.ic_menu_manage); &

71、#160;6.        return super.onCreateOptionsMenu(menu);  7.   当按下菜单键时,WifiSettings就会调用这个函数绘制菜单。如果选择扫描按钮,WifiSettings会调用onOptionsItemSelected()。packages/apps/Settings/src/com/android/settings/wifiwifisettings.java1. public booleanonOptionsIte

72、mSelected(MenuItem item)   2.        switch (item.getItemId()   3.            case MENU_ID_SCAN:  4.            

73、60;    if(mWifiManager.isWifiEnabled()   5.                     mScanner.resume();  6.              

74、     7.                 return true;  8.            case MENU_ID_ADVANCED:  9.        

75、0;        startActivity(new Intent(this,AdvancedSettings.class);  10.                 return true;  11.          12. 

76、60;      return super.onOptionsItemSelected(item);  13.   Handler类:1. private class Scanner extends Handler    2.        private int mRetry = 0;   3.

77、       void resume()   4.            if (!hasMessages(0)     5.                 sendEmptyM

78、essage(0);  6.               7.          8.        void pause()   9.            mRetr

79、y = 0;  10.             mAccessPoints.setProgress(false);  11.            removeMessages(0);  12.          13.  

80、60;     Override  14.        public void handleMessage(Message message)   15.            if (mWifiManager.startScanActive()  16.   

81、;              mRetry = 0;  17.             else if (+mRetry >= 3)   18.         &

82、#160;       mRetry = 0;  19.                Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,  20.          

83、              Toast.LENGTH_LONG).show();  21.                 return;  22.            

84、;  23.            mAccessPoints.setProgress(mRetry != 0);  24.            sendEmptyMessageDelayed(0, 6000);  25.         

85、0;26.   这里的mWifiManager.startScanActive()就会调用WifiService里的startScan()函数,下面的流程和上面的一样,这里不赘述。当supplicant完成了这个扫描命令后,它会发送一个消息给上层,提醒他们扫描已经完成,WifiMonitor会接收到这消息,然后再发送给WifiStateTracker。Frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java1. void handleEvent(int event, String&#

86、160;remainder)    2.             switch (event)   3.                 caseDISCONNECTED:  4.      

87、0;             handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);  5.                     break;  6.

88、                 case CONNECTED:  7.                    handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTE

89、D,remainder);  8.                     break;  9.                 case SCAN_RESULTS:  10.   

90、;                  mWifiStateTracker.notifyScanResultsAvailable();  11.                     break;  

91、12.                 case UNKNOWN:  13.                     break;  14.      

92、0;        15.   WifiStateTracker将会广播SCAN_RESULTS_AVAILABLE_ACTION消息:代码如:Frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java1. public voidhandleMessage(Message msg)   2.         Inten

93、t intent;  3.  4. case EVENT_SCAN_RESULTS_AVAILABLE:  5.                 if(ActivityManagerNative.isSystemReady()   6.           &

94、#160;         mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);  7.                    8.       &

95、#160;         sendScanResultsAvailable();   9.                   10.               &#

96、160; setScanMode(false); 11.                 break;  12.  13.   由于WifiSettings类注册了intent,能够处理SCAN_RESULTS_AVAILABLE_ACTION消息,它会调用handleEvent(),调用流程如下所示。WifiSettings.handleEvent() =>W

97、ifiSettings.updateAccessPoints() => mWifiManager.getScanResults()=> mService.getScanResults()=>mWifiStateTracker.scanResults() => WifiNative.scanResultsCommand()将获取AP列表的命令发送到supplicant,然后supplicant通过Socket发送扫描结果,由上层接收并显示。这和前面的消息获取流程基本相同。(三)配置,连接AP当用户选择一个活跃的AP时,Wi

98、fiSettings响应打开一个对话框来配置AP,比如加密方法和连接AP的验证模式。配置好AP后,WifiService添加或更新网络连接到特定的AP。代码如:packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.java1. public booleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference)    2.   

99、0;    if (preference instanceof AccessPoint)   3.            mSelected = (AccessPoint) preference;  4.            showDialog(

100、mSelected, false);  5.         else if (preference = mAddNetwork)   6.            mSelected = null;  7.        

101、;    showDialog(null, true);  8.         else if (preference = mNotifyOpenNetworks)   9.            Secure.putInt(getContentResolver(), 

102、0; 10.                    Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,  11.                    mN

103、otifyOpenNetworks.isChecked() ? 1 : 0);  12.         else   13.            return super.onPreferenceTreeClick(screen, preference);  14.    &

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

105、发送连接命令的代码:packages/apps/settings/src/com/android/settings/wifi/WifiSetttings.javajava view plaincopy1. public void onClick(DialogInterfacedialogInterface, int button)   2.        if (button = WifiDialog.BUTTON_FORGE

106、T && mSelected != null)   3.            forget(mSworkId);  4.         else if (button = WifiDialog.BUTTON_SUBMIT && mDialog&

107、#160;!=null)   5.            WifiConfiguration config = mDialog.getConfig();  6.            if (config = null)   7.    &

108、#160;            if (mSelected != null&& !requireKeyStore(mSelected.getConfig()   8.                    

109、60;connect(mSworkId);  9.                   10.             else if (workId != -1)   11.      &

110、#160;          if (mSelected != null)   12.                     mWifiManager.updateNetwork(config);  13.  

111、0;14.                     saveNetworks();  15.                   16.        

112、;     else   17.                 int networkId =mWifiManager.addNetwork(config);  18.               

113、  if (networkId != -1)   19.                    mWifiManager.enableNetwork(networkId, false);    20.         &

114、#160;           workId =networkId;   21.                     if (mDialog.edit | requireKeyStore(config)  22.              

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论