TetherCmd和SoftapCmd命令都和手機中一項名為綁定(Tether)的功能相關。簡單來說,綁定功能即把手機當成Modem用。智能手機一般都有多種連接網絡的方式,例如使用Wi-Fi或3G。在某些環境下如高鐵列車上,差旅人士只要把手機接到筆記本上,然后開啟3G和Tether,筆記本就可以利用手機上網了(在智能機普及前,類似的場景中就需要使用3G上網卡)。
另外,如果手機中的無線網絡設備支持Soft AP(Soft Access Point,軟件實現的接入點)功能,還可以通過Softap命令將手機變成一個AP(可以把它看成是一個無線路由器)。
目前Android 4.2系統支持以下三種方式的綁定。
* Soft AP:利用Wi-Fi無線網絡的特性,開啟手機Soft AP功能。主機和手機間通過Wi-Fi通信。
* Bluetooth:主機(PC或筆記本電腦)和手機通過藍牙協議通信。
* USB:主機和手機通過USB協議通信。手機相當于一個USB上網卡。
本節主要介紹TetherCmd中的USB綁定和Softap命令。其余內容我們將留給讀者自行研究。
* * * * *
**提示** TetherCmd還支持所謂的逆綁定(reverse tethering),即手機借助主機上網。這部分內容請讀者自行研究。
* * * * *
**1.TetherCmd命令**
本節僅介紹利用USB實現Tether的功能,其中涉及RNDIS以及DHCP相關的背景知識,我們先來介紹它們。
(1)背景知識介紹[26][27][28][29][30]
RNDIS(Remote Network Driver Interface Specification)是微軟公司的,主要用于Windows平臺中USB網絡設備的驅動開發。RNDIS的協議棧如圖2-24所示。
:-: 
圖2-24 RNDIS協議棧
RNDIS的作用是簡化Windows平臺上USB網絡設備驅動開發的流程。此處不討論相關內容,感興趣的讀者可閱讀本章最后列出的參考資料。
RNDIS和Android有什么關系呢?當手機通過USB連接到主機(主機一般運行Windows系統)后,如果要啟用USB綁定,必須要把手機的USB設置成RNDIS(絕大部分廠商的手機都是這么實現的)。這樣,主機上的OS就能識別到一個新的網卡。然后用戶就可以選擇使用它來開展網絡操作了。
* * * * *
**提示** 本書后續章節將討論Android平臺上USB的相關功能。
* * * * *
假設用戶選擇使用這個通過USB綁定的網卡,下一步要做的就是給主機分配IP地址了。此處涉及DHCP協議。
DHCP(Dynamic Host Configuration Protocol,動態主機配置協議)的前身是BOOTP。BOOTP原本是用于無磁盤主機連接的網絡上的,網絡主機使用BOOT ROM而不是磁盤啟動并連接上網絡,BOOTP則可以自動地為那些主機設定TCP/IP環境DHCP是BOOTP的增強版本,它分為兩個部分。
* 服務器端:所有的IP網絡設定數據都由DHCP服務器集中管理,并負責處理客戶端的DHCP要求。
* 客戶端:客戶端會使用從服務器分配下來的IP地址等配置信息。
根據上述介紹,相信讀者很容易想到,在USB綁定中,主機將是DHCP的客戶端,而手機是DHCP的服務器端。那么在Android系統中,DHCP服務器端是誰呢?同Pppd類似,Android也使用了另外一個開源軟件DNSmasq來充當DHCP服務器。
DNSmasq是一個用于配置DNS和DHCP的工具,小巧且方便,適用于小型網絡,它提供了DNS功能和可選擇的DHCP功能。它服務只在本地適用的域名,這些域名是不會在全球的DNS服務器中出現的。DHCP服務器和DNS服務器結合,并且允許DHCP分配的地址能在DNS中正常解析,而這些DHCP分配的地址和相關命令可以配置到每臺主機中,也可以配置到一臺核心設備中(如路由器)。
DNSmasq適用于擁有NAT的家庭網絡、用Modem、ADSL設備連接到互聯網等環境。對于需求低資源消耗且配置方便簡單的小型網絡(最多可支持1000臺主機)是一個很好的選擇。
(2)TetherCmd命令使用
Android中啟動USB Tether功能將涉及Framework層多個模塊,其詳細過程留待后續章節介紹。此處讀者僅需從TetherCmd角度考慮其中的兩個主要步驟。
- 1、**添加需要Tether的接口**。對USB綁定來說,接口名為rndis0。對應的處理函數是TetherController的tetherInterface,代碼如下所示。
**TetherController.cpp::tetherInterface**
~~~
int TetherController::tetherInterface(const char *interface) {
mInterfaces->push_back(strdup(interface));
// 把需要interface名字保存到一個鏈表即可
return 0;
}
~~~
tetherInterface的功能很簡單,就是保存需要Tether的設備名。這一步其實沒有太多實質性的內容。
- 2、**通過"start"選項啟動Tether**。這個步驟將觸發TetherController的startTethering函數被調用。該函數的主要功能就是配置dnsmasq的啟動參數并啟動它。這部分代碼比較簡單,dnsmasq的啟動參數如下所示。
~~~
dnsmasq\
--keep-in-foreground\#前臺運行
--no-resolv\#不解析/etc/resolv.conf,該文件記錄域名和dns服務器的一些信息
--no-poll\#不關注/etc/resolv.conf文件的變化
--dhcp-option-force=43,ANDROID_METERED\#強制的dhcp選項。客戶端和dnsmasq交互時,首先
#會獲取dhcp服務器的一些配置信息。43是DHCP協議中定義的option的一種,代表vendor specific
#infomation該選項說明vendor specifi information就是ANDROID_METERED
--pid-file\#指定dnsmasq記錄自己進程id(pid)到某個文件。默認是/var/run/dnsmasq.pid
--dhcp-range=192.168.1.2 192.168.1.100 1h\#該選項開啟dnsmasq的dhcp服務功能。分配的IP地址
#位于192.168.1.2和192.168.1.100之間。1h代表租約時間為1小時。租約時間即某IP地址可以被DHCP
#客戶端使用的時間。如果超過租約時間,dnsmasq必須為該客戶端重新分配IP
~~~
這兩步完成后,USB綁定功能中和TetherCmd相關的任務就完成了。從整個綁定過程來看,涉及應用(例如Settings提供的設置功能)、網絡模塊、USB模塊、驅動等,是一個非常復雜的過程。
* * * * *
**提示** 這個過程對軟件開發者來說也是一個挑戰,只有對USB Tether涉及的各個模塊都有相應了解,碰到問題時候才能快速定位和解決它。
* * * * *
**2.SoftapCmd命令**
Softap命令和Wi-Fi有緊密關系。本節先簡單介紹Soft AP相關的背景知識,后續章節將對Wi-Fi開展深入討論。
(1)背景知識介紹[31][32][33]
Soft AP代表通過軟件實現Access Point的功能。那么AP是什么?AP和Soft AP有什么不同?
在Wi-Fi無線技術規范中,AP和Station是其中的兩個基本概念。
- 從功能角度來看,AP作為基站設備,起著連接其他無線設備到有線網的作用,相當于有線網絡中的HUB與交換機。在日常工作和家庭中經常使用的無線路由器就是一個AP。一般情況下,它一端接著有線網絡,另一端連接其他無線設備。
- Station代表配備無線網絡接口的設備,如手機、筆記本等。
雖然AP和Station是兩個不同的設備,但實際上在Station中用軟件也能實現AP擁有的功能,如橋接、路由等。在基本功能上,Soft AP與AP并沒有太大的差別,只是Soft AP設備的接入能力和覆蓋范圍不如AP。
以前面提到的高鐵列車上的應用場景為例,除了用USB綁定外,還可以打開筆記本和手機的Wi-Fi,并啟動手機的Soft AP功能。這樣,手機一方面用3G接入互聯網,另一方面又利用SoftAP向筆記本提供Wi-Fi接入功能。
在Android系統中使用Soft AP功能還得借助另一個開源軟件"hostapd",這是一個運行在用戶空間的用于AP和認證服務器的守護進程。它實現了IEEE 802.11相關的接入管理、IEEE802.1X/WPA/WPA2/EAP認證、RADIUS客戶端、EAP服務器和RADIUS認證服務器。
(2)SoftapCmd命令使用
和TetherCmd類似,開啟Android中手機的Soft AP功能將涉及大量Framework層中的操作,本節僅關注和Netd相關的三個步驟。
1)首先為Wi-Fi加載不同的固件(Firmware),這是通過SoftapController的fwReloadSoftap函數完成的,代碼如下所示。
**SoftapController.cpp::fwReloadSoftap**
~~~
int SoftapController::fwReloadSoftap(int argc, char *argv[])
{
int ret, i = 0;
char *iface;
char *fwpath;
......// 參數檢測
iface = argv[2];
if (strcmp(argv[3], "AP") == 0) {
fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
} else if (strcmp(argv[3], "P2P") == 0) {
fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
} else {
fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
}
// 通過往/sys/module/wlan/parameters/fwpath文件中寫入固件名
// 觸發驅動去加載對應的固件
ret = wifi_change_fw_path((const char *)fwpath);
......
return ret;
}
~~~
上面這段代碼表示在Android中,如果要讓Wi-Fi無線設備扮演不同的角色,得為它們加載不同的固件(Firmware),具體說明如下。
* **WIFI_GET_FW_PATH_AP**:代表Soft AP功能的固件,其對應的文件位置由WIFI_DRIVER_FW_PATH_AP宏表達。三星Tuna平臺中,該文件位置為/vendor/firmware/fw_bcmdhd_apsta.bin。
* **WIFI_GET_FW_PATH_P2P**:代表P2P功能的固件,其對應的文件位置由WIFI_DRIVER_FW_PATH_P2P宏表達。三星Tuna平臺中,該文件位置為/vendor/firmware/fw_bcmdp2p.bin。
* **WIFI_GET_FW_PATH_STA**:代表Station功能的固件,其對應的文件位置由WIFI_DRIVER_FW_PATH_STA宏表達。三星Tuna平臺中,該文件位置為/vendor/firmware/fw_bcmdhd.bin。
* * * * *
**提示** 三星Tuna平臺對應的配置文件在Android 4.2源碼根目錄/device/samsung/tuna目錄中。從上面的固件文件名來看,它用的Wi-Fi無線芯片是博通(Broadcom)公司生產的。通過加載不同固件的方式來啟用無線芯片硬件的不同功能可能和Wi-Fi驅動及芯片的設計有關。
另外,根據審稿專家的反饋,在Android 4.2中,STA和P2P可同時運行(即所謂的共存模式),這樣STA和P2P實際對應的固件相同,但可能文件名不同。而SoftAP的固件與STA/P2P就不一樣了。
* * * * *
2)加載完指定的Wi-Fi固件后,下一步將對Soft AP功能進行一些配置,配置信息最終將寫到一個配置文件。這部分功能由SoftapController的setSoftap函數完成,代碼如下所示。
**SoftapController.cpp::setSoftap**
~~~
int SoftapController::setSoftap(int argc, char *argv[]) {
char psk_str[2*SHA256_DIGEST_LENGTH+1];
int ret = 0, i = 0, fd;
char *ssid, *iface;
......// 參數檢查
iface = argv[2];
char *wbuf = NULL;
char *fbuf = NULL;
if (argc > 3) {
ssid = argv[3];
} else {
ssid = (char *)"AndroidAP"; // SSID即接入點的名稱
}
asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
"/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n",
iface, ssid);
if (argc > 4) { // 判斷AP的加密類型
if (!strcmp(argv[4], "wpa-psk")) {
generatePsk(ssid, argv[5], psk_str);
asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n",
wbuf, psk_str);
} else if (!strcmp(argv[4], "wpa2-psk")) {
generatePsk(ssid, argv[5], psk_str);
asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n",
wbuf, psk_str);
} else if (!strcmp(argv[4], "open")) {
asprintf(&fbuf, "%s", wbuf);
}
} ......
// HOSTAPD_CONF_FILE指向/data/misc/wifi/hostapd.conf文件
fd = open(HOSTAPD_CONF_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0660);
......
if (write(fd, fbuf, strlen(fbuf)) < 0) {
ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
ret = -1;
}
......// 修改該文件的讀寫權限等
return ret;
}
~~~
上面代碼中涉及Wi-Fi技術的很多概念,將在后續章節統一介紹。從功能上來說,setSoftap函數無非就是把一些配置信息寫到一個hostapd.conf文件中。可以通過一個例子文件來了解此文件的內容。
Android4.2/hardware/ti/wlan/mac80211/config目錄中有一個hostapd.conf文件,其內容如下所示。
**hostapd.conf**
~~~
driver=nl80211 #指定Wi-Fi驅動的名稱
......#略去部分內容
ssid=AndroidAP #設置接入點名稱為AndroidAP
country_code=US
wep_rekey_period=0
eap_server=0
own_ip_addr=127.0.0.1
wpa_group_rekey=0
wpa_gmk_rekey=0 #加密方式等設置
wpa_ptk_rekey=0
interface=wlan1 #網絡設備接口
......#略去部分內容
~~~
由上邊示例的hostapd.conf可知,當使用該配置文件后,其他Station搜索到由這臺手機設置的Soft AP的名稱將會是"AndroidAP"。
3)最后,SoftapController的startap函數被調用,它將啟動hostapd進程。重點關注hostapd啟動的參數信息,如下所示。
~~~
hostapd\
-e/data/misc/wifi/entropy.bin \和Wi-Fi協議中的信息加密有關
/data/misc/wifi/hostapd.conf \hostapd的配置文件
~~~
- 前言
- 第1章 準備工作
- 1.1 Android系統架構
- 1.2 工具使用
- 1.2.1 Source Insight的使用
- 1.2.2 Eclipse的使用
- 1.2.3 BusyBox的使用
- 1.3 本書資源下載說明
- 第2章 深入理解Netd
- 2.1 概述
- 2.2 Netd工作流程
- 2.2.1 main函數分析
- 2.2.2 NetlinkManager分析
- 2.2.3 CommandListener分析
- 2.2.4 DnsProxyListener分析
- 2.2.5 MDnsSdListener分析
- 2.3 CommandListener中的命令
- 2.3.1 iptables、tc和ip命令
- 2.3.2 CommandListener構造函數和測試工具ndc
- 2.3.3 InterfaceCmd命令
- 2.3.4 IpFwd和FirewallCmd命令
- 2.3.5 ListTtysCmd和PppdCmd命令
- 2.3.6 BandwidthControlCmd和IdletimerControlCmd命令
- 2.3.7 NatCmd命令
- 2.3.8 TetherCmd和SoftapCmd命令
- 2.3.9 ResolverCmd命令
- 2.4 NetworkManagementService介紹
- 2.4.1 create函數詳解
- 2.4.2 systemReady函數詳解
- 2.5 本章總結和參考資料說明
- 2.5.1 本章總結
- 2.5.2 參考資料說明
- 第3章 Wi-Fi基礎知識
- 3.1 概述
- 3.2 無線電頻譜和802.11協議的發展歷程
- 3.2.1 無線電頻譜知識
- 3.2.2 IEEE 802.11發展歷程
- 3.3 802.11無線網絡技術
- 3.3.1 OSI基本參考模型及相關基本概念
- 3.3.2 802.11知識點導讀
- 3.3.3 802.11組件
- 3.3.4 802.11 Service介紹
- 3.3.5 802.11 MAC服務和幀
- 3.3.6 802.11 MAC管理實體
- 3.3.7 無線網絡安全技術知識點
- 3.4 Linux Wi-Fi編程API介紹
- 3.4.1 Linux Wireless Extensions介紹
- 3.4.2 nl80211介紹
- 3.5 本章總結和參考資料說明
- 3.5.1 本章總結
- 3.5.2 參考資料說明
- 第4章 深入理解wpa_supplicant
- 4.1 概述
- 4.2 初識wpa_supplicant
- 4.2.1 wpa_supplicant架構
- 4.2.2 wpa_supplicant編譯配置
- 4.2.3 wpa_supplicant命令和控制API
- 4.2.4 git的使用
- 4.3 wpa_supplicant初始化流程
- 4.3.1 main函數分析
- 4.3.2 wpa_supplicant_init函數分析
- 4.3.3 wpa_supplicant_add_iface函數分析
- 4.3.4 wpa_supplicant_init_iface函數分析
- 4.4 EAP和EAPOL模塊
- 4.4.1 EAP模塊分析
- 4.4.2 EAPOL模塊分析
- 4.5 wpa_supplicant連接無線網絡分析
- 4.5.1 ADD_NETWORK命令處理
- 4.5.2 SET_NETWORK命令處理
- 4.5.3 ENABLE_NETWORK命令處理
- 4.6 本章總結和參考資料說明
- 4.6.1 本章總結
- 4.6.2 參考資料說明
- 第5章 深入理解WifiService
- 5.1 概述
- 5.2 WifiService的創建及初始化
- 5.2.1 HSM和AsyncChannel介紹
- 5.2.2 WifiService構造函數分析
- 5.2.3 WifiStateMachine介紹
- 5.3 加入無線網絡分析
- 5.3.1 Settings操作Wi-Fi分析
- 5.3.2 WifiService操作Wi-Fi分析
- 5.4 WifiWatchdogStateMachine介紹
- 5.5 Captive Portal Check介紹
- 5.6 本章總結和參考資料說明
- 5.6.1 本章總結
- 5.6.2 參考資料說明
- 第6章 深入理解Wi-Fi Simple Configuration
- 6.1 概述
- 6.2 WSC基礎知識
- 6.2.1 WSC應用場景
- 6.2.2 WSC核心組件及接口
- 6.3 Registration Protocol詳解
- 6.3.1 WSC IE和Attribute介紹
- 6.3.2 802.11管理幀WSC IE設置
- 6.3.3 EAP-WSC介紹
- 6.4 WSC代碼分析
- 6.4.1 Settings中的WSC處理
- 6.4.2 WifiStateMachine的處理
- 6.4.3 wpa_supplicant中的WSC處理
- 6.4.4 EAP-WSC處理流程分析
- 6.5 本章總結和參考資料說明
- 6.5.1 本章總結
- 6.5.2 參考資料說明
- 第7章 深入理解Wi-Fi P2P
- 7.1 概述
- 7.2 P2P基礎知識
- 7.2.1 P2P架構
- 7.2.2 P2P Discovery技術
- 7.2.3 P2P工作流程
- 7.3 WifiP2pSettings和WifiP2pService介紹
- 7.3.1 WifiP2pSettings工作流程
- 7.3.2 WifiP2pService工作流程
- 7.4 wpa_supplicant中的P2P
- 7.4.1 P2P模塊初始化
- 7.4.2 P2P Device Discovery流程分析
- 7.4.3 Provision Discovery流程分析
- 7.4.4 GO Negotiation流程分析
- 7.5 本章總結和參考資料說明
- 7.5.1 本章總結
- 7.5.2 參考資料說明
- 第8章 深入理解NFC
- 8.1 概述
- 8.2 NFC基礎知識
- 8.2.1 NFC概述
- 8.2.2 NFC R/W運行模式
- 8.2.3 NFC P2P運行模式
- 8.2.4 NFC CE運行模式
- 8.2.5 NCI原理
- 8.2.6 NFC相關規范
- 8.3 Android中的NFC
- 8.3.1 NFC應用示例
- 8.3.2 NFC系統模塊
- 8.4 NFC HAL層討論
- 8.5 本章總結和參考資料說明
- 8.5.1 本章總結
- 8.5.2 參考資料說明
- 第9章 深入理解GPS
- 9.1 概述
- 9.2 GPS基礎知識
- 9.2.1 衛星導航基本原理
- 9.2.2 GPS系統組成及原理
- 9.2.3 OMA-SUPL協議
- 9.3 Android中的位置管理
- 9.3.1 LocationManager架構
- 9.3.2 LocationManager應用示例
- 9.3.3 LocationManager系統模塊
- 9.4 本章總結和參考資料說明
- 9.4.1 本章總結
- 9.4.2 參考資料說明
- 附錄