【Android源码 栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了Android源码 -qianxk源码分析-Android移植_wifi设计原理 - 企业软件开发的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
post by 雨天等晴 / 2010-2-6 17:30 Saturday
ANDROID移植: WIFI设计原理
源码分析
ANDROID 初始化 在 SystemServer 启动的时候会生成一个 ConnectivityService 的实例 try Log.iTAG Starting Connectivity Service. ServiceManager.addServiceContext.CONNECTIVITY_SERVICE new ConnectivityServicecontext catch Throwable e Log.eTAG Failure starting Connectivity Service e ConnectivityService 的构造函数会创建 WifiService if DBG Log.vTAG Starting Wifi Service. mWifiStateTracker new WifiStateTrackercontext handler WifiService wifiService new WifiServicecontext mWifiStateTracker ServiceManager.addServiceContext.WIFI_SERVICE wifiService WifiStateTracker 会创建 WifiMonitor 接收来自底层的事件WifiService 和 WifiMonitor 是整 个模块的核心。
WifiService 负责启动关闭 wpa_supplicant、启动关闭 WifiMonitor 监视线程 和把命令下发给 wpa_supplicant而 WifiMonitor 则负责从 wpa_supplicant 接收事件通知。
连接 AP 1. 使能 WIFI WirelessSettings 在初始化的时候配置了由 WifiEnabler 来处理 Wifi 按钮 private void initToggles mWifiEnabler new WifiEnabler this WifiManager getSystemServiceWIFI_SERVICE CheckBoxPreference findPreferenceKEY_TOGGLE_WIFI 当用户按下 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 中的监视 线程。
private boolean setWifiEnabledBlockingboolean enable final int eventualWifiState enable WIFI_STATE_ENABLED : WIFI_STATE_DISABLED updateWifiStateenable WIFI_STATE_ENABLING : WIFI_STATE_DISABLING if enable if WifiNative.loadDriver Log.eTAG Failed to load Wi-Fi driver. updateWifiStateWIFI_STATE_UNKNOWN return false if WifiNative.startSupplicant WifiNative.unloadDriver Log.eTAG Failed to start supplicant daemon. updateWifiStateWIFI_STATE_UNKNOWN return false mWifiStateTracker.startEventLoop // Success persistWifiEnabledenable updateWifiStateeventualWifiState return true 当使能成功后会广播发送 WIFI_STATE_CHANGED_ACTION 这个 Intent 通知外界 WIFI 已 经 成 功 使 能 了 。
WifiEnabler 创 建 的 时 候 就 会 向
Android 注 册 接 收 WIFI_STATE_CHANGED_ACTION因此它会收到该 Intent从而开始扫描。
private void handleWifiStateChangedint wifiState if wifiState WIFI_STATE_ENABLED loadConfiguredAccessPoints attemptScan 2. 查找 AP 扫描的入口函数是 WifiService 的 startScan它其实也就是往 wpa_supplicant 发送 SCAN 命 令。
static jboolean
android_net_wifi_scanCommandJNIEnv env jobject clazz jboolean result // Ignore any error from setting the scan mode. // The scan will still work. voiddoBooleanCommandDRIVER SCAN-ACTIVE OK result doBooleanCommandSCAN OK voiddoBooleanCommandDRIVER SCAN-PASSIVE OK return result 当 wpa_supplicant 处理完 SCAN 命令后它会向控制通道发送事件通知扫描完成从而 wifi_wait_for_event 函数会接收到该事件由此 WifiMonitor 中的 MonitorThread 会被执行来 出来这个事件 void handleEventint event String remainder case SCAN_RESULTS: mWifiStateTracker.notifyScanResultsAvailable break WifiStateTracker 则接着广播发送 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent case EVENT_SCAN_RESULTS_AVAILABLE: mContext.sendBroadcastnew IntentWifiManager.SCAN_RESULTS_AVAILABLE_ACTION WifiLayer 注册了接收 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent所以它的相关 处理函数 handleScanResultsAvailable 会被调用在该函数中先会去拿到 SCAN 的结果最 终是往 wpa_supplicant 发送 SCAN_RESULT 命令并读取返回值来实现的 List list mWifiManager.getScanResults 对每一个扫描返回的 APWifiLayer 会调用 WifiSettings 的 onAccessPointSetChanged 函数 从而最终把该 AP 加到 GUI 显示列表中。
public void onAccessPointSetChangedAccessPointState ap boolean added AccessPointPreference pref mAps.getap if added if pref null pref new AccessPointPreferencethis ap mAps.putap pref else pref.setEnabledtrue mApCategory.addPreferencepref 3. 配置 AP 参数 当用户在 WifiSettings 界面上选择了一个 AP 后会显示配置 AP 参数的一个对话框 public boolean onPreferenceTreeClickPreferenceScreen preferenceScreen Preference preference if preference instanceof AccessPointPreference AccessPointState state AccessPointPreference preference.getAccessPointState showAccessPointDialogstate AccessPointDialog.MODE_INFO 4. 连接 当用户在 AcessPointDialog 中选择好加密方式和输入密钥之后再点击连接按钮
Android 就会去连接这个 AP。
private void handleConnect String password getEnteredPassword if TextUtils.isEmptypassword mState.setPasswordpassword mWifiLayer.connectToNetworkmState WifiLayer 会先检测这个 AP 是不是之前被配置过这个是通过向 wpa_supplicant 发送 LIST_NETWORK 命令并且比较返回值来实现的 // Need WifiConfiguration for the AP WifiConfiguration config findConfiguredNetworkstate 如果 wpa_supplicant 没有这个 AP 的配置信息 则会向 wpa_supplicant 发送 ADD_NETWORK 命令来添加该 AP if config null // Connecting for the first time need to create it config addConfigurationstate ADD_CONFIGURATION_ENABLEADD_CONFIGURATION_SAVE ADD_NETWORK 命 令 会 返 回 一 个 ID WifiLayer 再 用 这 个 返 回 的 ID 作 为 参 数 向 wpa_supplicant 发送 ENABLE_NETWORK 命令从而让 wpa_supplicant 去连接该 AP。
// Make sure that network is enabled and disable others mReenableApsOnNetworkStateChange true if mWifiManager.enableNetworkstate.networkId true Log.eTAG Could not enable network ID state.networkId errorR.string.error_connecting return false 5. 配置 IP 地址 当 wpa_supplicant 成功连接上 AP 之后它会向控制通道发送事件通知连接上 AP 了从而 wifi_wait_for_event 函数会接收到该事件由此 WifiMonitor 中的 MonitorThread 会被执行来 出来这个事件 void handleEventint event String remainder case CONNECTED: handleNetworkStateChangeNetworkInfo.DetailedState.CONNECTED remainder break WifiMonitor 再调用 WifiStateTracker 的 notifyStateChangeWifiStateTracker 则接着会往自身 发送 EVENT_DHCP_START 消息来启动 DHCP 去获取 IP 地址 private void handleConnectedState setPollTimer mLastSignalLevel -1 if mHaveIPAddress mObtainingIPAddress mObtainingIPAddress true mDhcpTarget.obtainMessageEVENT_DHCP_START.sendToTarget 然后再广播发送 NETWORK_STATE_CHANGED_ACTION 这个 Intent case EVENT_NETWORK_STATE_CHANGED: if result.state DetailedState.DISCONNECTED mDisconnectPending intent new IntentWifiManager.NETWORK_STATE_CHANGED_ACTION intent.putExtraWifiManager.EXTRA_NETWORK_INFO mNetworkInfo if result.BSSID null intent.putExtraWifiManager.EXTRA_BSSID result.BSSID mContext.sendStickyBroadcastintent break WifiLayer 注册了接收 NETWORK_STATE_CHANGED_ACTION 这个 Intent所以它的相关 处理函数 handleNetworkStateChanged 会被调用 当 DHCP 拿到 IP 地址之后会再发送 EVENT_DHCP_SUCCEEDED 消息 private class DhcpHandler extends Handler public void handleMessageMessage msg switch msg.what case EVENT_DHCP_START: if NetworkUtils.runDhcpmInterfaceName mDhcpInfo event EVENT_DHCP_SUCCEEDED WifiLayer 处 理 EVENT_DHCP_SUCCEEDED 消 息 会 再 次 广 播 发 送 NETWORK_STATE_CHANGED_ACTION 这个 Intent这次带上完整的 IP 地址信息。
case EVENT_DHCP_SUCCEEDED: mWifiInfo.setIpAddressmDhcpInfo.ipAddress setDetailedStateDetailedState.CONNECTED intent new IntentWifiManager.NETWORK_STATE_CHANGED_ACTION intent.putExtraWifiManager.EXTRA_NETWORK_INFO mNetworkInfo mContext.sendStickyBroadcastintent break 至此为止整个连接过程完成。
问题: 目前的实现不支持 Ad-hoc 方式。
上一篇:
如何编写高效的Android代码_安卓条码扫描器
下一篇:
大学生汉语写作水平与英语水平相关性研究