根據7.3.2節中對DISCOVER_PEERS命令的代碼分析可知,P2pStateMachine將發
送"P2P_FIND 120"命令給WPAS以觸發P2P Device Discovery流程。處理該命令的代碼如下所
示。
**ctrl_iface.c::wpa_supplicant_ctrl_iface_process**
~~~
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len)
{
char *reply; const int reply_size = 4096;
int ctrl_rsp = 0; int reply_len;
......
#ifdef CONFIG_P2P
// 處理帶參數的P2P_FIND命令
} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
// 注意“P2P_FIND ”多了一個空格
if (p2p_ctrl_find(wpa_s, buf + 9)) reply_len = -1;
} else if (os_strcmp(buf, "P2P_FIND") == 0) {
// 處理不帶參數的P2P_FIND命令
if (p2p_ctrl_find(wpa_s, "")) reply_len = -1;
} ......// 其他P2P命令處理
#endif
......
}
~~~
不論P2P_FIND命令是否攜帶參數,其最終的處理函數都將對應為p2p_ctrl_find,如下所示。
**ctrl_iface.c::p2p_ctrl_find**
~~~
static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
{
unsigned int timeout = atoi(cmd);
enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
// 搜索方式,見下文解釋
u8 dev_id[ETH_ALEN], *_dev_id = NULL;
char *pos;
// 設置搜索方式,見下文解釋
if (os_strstr(cmd, "type=social")) type = P2P_FIND_ONLY_SOCIAL;
else if (os_strstr(cmd, "type=progressive")) type = P2P_FIND_PROGRESSIVE;
pos = os_strstr(cmd, "dev_id=");// dev_id代表peer端device的MAC地址
if (pos) {......}
// wpas_p2p_find內部將調用p2p_find,下文將直接分析p2p_find
return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id);
}
~~~
P2P_FIND支持三種不同的Discovery Type,分別如下。
* P2P_FIND_START_WITH_FULL:默認設置。表示先掃描所有頻段,然后再掃描socialchannels。這種搜索方式如圖7-3所示。
* P2P_FIND_ONLY_SOCIAL:只掃描social channels。它將跳過“掃描所有頻段”這一過程。這種搜索方式能加快搜索的速度。
* P2P_FIND_PROGRESSIVE:它和P2P_FIND_START_WITH_FULL類似,只不過在SearchState階段將逐個掃描所有頻段。為什么在search state階段會掃描所有頻段呢?請讀者參考圖7-22中的狀態切換路線14。當周圍已經存在Group的時候,如果在最初的“掃描所有頻段”這一過程中沒有發現Group,則在后續的search state逐個掃描頻段過程中就有可能發現之前那些沒有找到的Group。
>[info] 注意 GO將工作在Operation Channel,而Listen Channel只在最初的P2P Device Discovery階段使用。
**1、P2P設備掃描流程**
P2P設備掃描流程從wpas_p2p_find開始,其代碼如下所示。
**p2p_supplicant.c::wpas_p2p_find**
~~~
int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
enum p2p_discovery_type type,unsigned int num_req_dev_types,
const u8 *req_dev_types, const u8 *dev_id)
{
/*
取消還未發送的Action幀數據。WPAS中,待發送的Action幀數據保存在wpa_supplicant對象的
pending_action_tx變量中,它指向一塊數據緩沖區。
*/
wpas_p2p_clear_pending_action_tx(wpa_s);
wpa_s->p2p_long_listen = 0;
/*
如果wifi driver能直接處理P2P管理,則主要工作將由wifi driver來完成。Galaxy Note 2
不支持WPA_DRIVER_FLAGS_P2P_MGMT。
*/
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
return wpa_drv_p2p_find(wpa_s, timeout, type);
......
// 取消計劃掃描任務
wpa_supplicant_cancel_sched_scan(wpa_s);
// 調用p2p_find函數
return p2p_find(wpa_s->global->p2p, timeout, type,
num_req_dev_types, req_dev_types, dev_id);
}
~~~
來看p2p_find函數,其代碼如下所示。
**p2p.c::p2p_find**
~~~
int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id)
{
int res;
p2p_free_req_dev_types(p2p);
if (req_dev_types && num_req_dev_types) {......// 本例沒有設置request dev type屬性}
if (dev_id) {
os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN);
p2p->find_dev_id = p2p->find_dev_id_buf;
} else p2p->find_dev_id = NULL;
// 注意下面這個P2P_AFTER_SCAN_NOTHING標志,它表示P2P設備完成scan動作后,無須做其他動作
p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
p2p_clear_timeout(p2p);
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);// 停止監聽
p2p->find_type = type;
p2p_device_clear_reported(p2p);
p2p_set_state(p2p, P2P_SEARCH); // 設置P2P模塊的狀態為P2P_SEARCH
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
p2p->last_p2p_find_timeout = timeout;
// 注冊一個掃描超時處理任務
if (timeout) eloop_register_timeout(timeout, 0, p2p_find_timeout,p2p, NULL);
switch (type) {
case P2P_FIND_START_WITH_FULL:
case P2P_FIND_PROGRESSIVE: // p2p_scan函數指針指向wpas_p2p_scan
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
p2p->num_req_dev_types,p2p->req_dev_types, dev_id);
break;
case P2P_FIND_ONLY_SOCIAL:
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
p2p->num_req_dev_types,p2p->req_dev_types, dev_id);
break;
default:
return -1;
}
if (res == 0) {
// 設置p2p_scan_running值為1,該變量后面用到的地方比較多,請讀者注意
p2p->p2p_scan_running = 1;
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,p2p, NULL);
} ...... // 略去res為其他值的處理情況
return res;
}
~~~
上述代碼中p2p_config對象的p2p_scan函數指針變量將指向p2p_supplicant.c中的wpas_p2p_scan,馬上來看它,代碼如下所示。
**p2p_supplicant.c::wpas_p2p_scan**
~~~
static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id)
{
struct wpa_supplicant *wpa_s = ctx;
// 掃描參數
struct wpa_driver_scan_params params;
int ret; struct wpabuf *wps_ie, *ies;
int social_channels[] = { 2412, 2437, 2462, 0, 0 };
size_t ielen; int was_in_p2p_scan;
os_memset(¶ms, 0, sizeof(params));
params.num_ssids = 1; // 設置SSID參數,P2P_WILDCARD_SSID的值為“DIRECT-”
params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
wpa_s->wps->dev.p2p = 1;
// 構造Probe Request幀中WSC IE信息
wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
WPS_REQ_ENROLLEE,num_req_dev_types, req_dev_types);
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
......
// 構造P2P IE信息,感興趣的讀者不妨自行閱讀p2p_scan_ie函數
p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
params.p2p_probe = 1;
params.extra_ies = wpabuf_head(ies); params.extra_ies_len = wpabuf_len(ies);
switch (type) {
case P2P_SCAN_SOCIAL: // 只掃描social channels的話,將設置params.freqs變量
params.freqs = social_channels;
break;
case P2P_SCAN_FULL:
break;
......// 其他掃描頻段控制
}
was_in_p2p_scan = wpa_s->scan_res_handler == wpas_p2p_scan_res_handler;
// 設置P2P掃描結果處理函數
wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
// 發起P2P設備掃描,該函數內部將調用driver_nl80211.c的wpa_driver_nl80211_scan函數
ret = wpa_drv_scan(wpa_s, ¶ms);
wpabuf_free(ies);
......
return ret;
}
~~~
讀者可比較本節和4.5.3節無線網絡掃描流程分析的內容。總體而言,P2P設備掃描的代碼邏輯比無線網絡掃描的代碼邏輯要簡單得多。圖7-31為WPAS中P2P設備掃描所涉及的幾個重要函數調用。
:-: 
圖7-31 P2P Device掃描流程
下面來看P2P設備掃描結果的處理流程。
**2、P2P設備掃描結果處理流程**
由4.5.3節“_wpa_supplicant_event_scan_results分析之二”中的代碼可知,當scan_res_handler不為空的時候,掃描結果將交給scan_res_handler來處理。由圖7-31可知,對P2P設備掃描時將設置scan_res_handler為wpas_p2p_scan_res_handler,其代碼如下所示。
**p2p_supplicant.c::wpas_p2p_scan_res_handler**
~~~
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
size_t i;
......
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
// ①對每一個掃描結果調用p2p_scan_res_handler函數
if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid,// 處理掃描結果
bss->freq, bss->level,(const u8 *) (bss + 1), bss->ie_len) > 0)
break;
}
p2p_scan_res_handled(wpa_s->global->p2p);// ②處理完畢后調用p2p_scan_res_handled
}
~~~
wpas_p2p_scan_res_handler中有兩個關鍵函數,先來看第一個。
**①、p2p_scan_res_handler函數**
p2p_scan_res_handler的代碼如下所示。
**p2p.c::p2p_scan_res_handler**
~~~
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
int level, const u8 *ies, size_t ies_len)
{
// 添加一個P2P Device,詳情見下文代碼分析
p2p_add_device(p2p, bssid, freq, level, ies, ies_len);
/*
go_neg_peer代表GON的對端設備,如果go_neg_peer不為空而且設備掃描時由發現了它,則直接通過
p2p_connect_send向其發送GON Request幀以開展GON流程。
*/
if (p2p->go_neg_peer && p2p->state == P2P_SEARCH &&
os_memcmp(p2p->go_neg_peer->info.p2p_device_addr, bssid, ETH_ALEN) == 0) {
p2p_connect_send(p2p, p2p->go_neg_peer);
return 1;
}
return 0;
}
~~~
上述代碼中最重要的是p2p_add_device函數,其代碼如下所示。
**p2p.c::p2p_add_device**
~~~
int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
const u8 *ies, size_t ies_len)
{
struct p2p_device *dev; struct p2p_message msg;
const u8 *p2p_dev_addr; int i;
os_memset(&msg, 0, sizeof(msg));
// 解析掃描結果中的IE信息,解析完的結果保存在一個p2p_message對象中
if (p2p_parse_ies(ies, ies_len, &msg)) {......// 解析掃描結果}
// p2p device info中的屬性
if (msg.p2p_device_addr) p2p_dev_addr = msg.p2p_device_addr;
else if (msg.device_id) p2p_dev_addr = msg.device_id;
......
// 過濾那些被阻止的P2P Device
if (!is_zero_ether_addr(p2p->peer_filter) &&
os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) {......}
// 構造一個p2p_device對象,并將其加入p2p_data結構體的devices鏈表中
dev = p2p_create_device(p2p, p2p_dev_addr);// 創建一個P2P Device對象
......
os_get_time(&dev->last_seen);// 設置發現該P2P Device的時間
// p2p_device的flags變量代表該p2p_device的一些信息
dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0)
os_memcpy(dev->interface_addr, addr, ETH_ALEN);
......// 處理ssid、listen channel等內容
dev->listen_freq = freq;
// 如果對端P2P Device是GO,它回復的Probe Response幀P2P IE信息中將包含Group Info屬性
if (msg.group_info) dev->oper_freq = freq;
dev->info.level = level;
p2p_copy_wps_info(dev, 0, &msg);// 復制WSC IE
......// 處理Vendor相關的IE信息
// 根據Group Info信息添加Client。就本例而言,周圍還不存在GO
p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq, msg.group_info,msg.group_info_len);
p2p_parse_free(&msg);
// 判斷是否有Service Discovery Request,如果有,需要為flags設置P2P_DEV_SD_SCHEDULE標志位
if (p2p_pending_sd_req(p2p, dev)) dev->flags |= P2P_DEV_SD_SCHEDULE;
// P2P_DEV_REPORTED表示WPAS已經向客戶端匯報過該P2P Device信息了
if (dev->flags & P2P_DEV_REPORTED) return 0;
// P2P_DEV_USER_REJECTED表示用戶拒絕該P2P Device信息
if (dev->flags & P2P_DEV_USER_REJECTED) {return 0;}
/*
dev_found函數指針指向wpas_dev_found,該函數將向WifiMonitor發送消息以告知我們找到了一個
P2P Device,該消息也稱為P2P Device Found消息。
*/
p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
!(dev->flags & P2P_DEV_REPORTED_ONCE));
// 下面這兩個標志表示該P2P Device已經向客戶端匯報過并且匯報過一次了
dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
return 0;
}
~~~
圖7-32為WPAS向其客戶端匯報的P2P Device Found消息的格式示例。
:-: 
圖7-32 P2P Device Found消息
**②、p2p_scan_res_handled函數**
接著來看第二個關鍵函數p2p_scan_res_handled。
**p2p.c::p2p_scan_res_handled**
~~~
void p2p_scan_res_handled(struct p2p_data *p2p)
{
......
p2p->p2p_scan_running = 0; // 設置p2p_scan_running值為0
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);// 取消掃描超時處理任務
/*
還記得p2p_find函數中介紹的P2P_AFTER_SCAN_NOTHING標志嗎(參考7.4.2節)?它將用在
下面這個p2p_run_after_scan函數中。由于指定了P2P_AFTER_SCAN_NOTHING標志,所以下面這個
函數返回0。感興趣的讀者可自行研究p2p_run_after_scan函數。
*/
if (p2p_run_after_scan(p2p)) return;
if (p2p->state == P2P_SEARCH) // 就本例而言,將滿足此if條件
p2p_continue_find(p2p);
}
~~~
p2p_continue_find的代碼如下所示。
**p2p.c::p2p_continue_find**
~~~
void p2p_continue_find(struct p2p_data *p2p)
{
struct p2p_device *dev;
#ifdef ANDROID_P2P
int skip=1;
#endif
p2p_set_state(p2p, P2P_SEARCH);
......// Service Discovery和Provision Discovery處理。就本例而言,這部分代碼邏輯意義不大
p2p_listen_in_find(p2p); // 進入listen state。來看此函數的代碼
}
~~~
**p2p.c::p2p_listen_in_find**
~~~
static void p2p_listen_in_find(struct p2p_data *p2p)
{
unsigned int r, tu;
int freq;
struct wpabuf *ies;
// 根據p2p_supplicant.conf中listen_channel等配置參數獲取對應的頻段
freq = p2p_channel_to_freq(p2p->cfg->country,
p2p->cfg->reg_class,p2p->cfg->channel);
......
// 計算需要在listen state等待的時間
os_get_random((u8 *) &r, sizeof(r));
tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
p2p->min_disc_int) * 100;
p2p->pending_listen_freq = freq;
p2p->pending_listen_sec = 0;
p2p->pending_listen_usec = 1024 * tu;
/*
構造P2P Probe Response幀,當我們在Listen state收到其他設備發來的Probe Request幀后,wifi
驅動將直接回復此處設置的P2P Probe Response幀。
*/
ies = p2p_build_probe_resp_ies(p2p);
// start_listen指向wpas_start_listen函數
if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 *tu/1000,ies)<0){...... }
wpabuf_free(ies);
}
~~~
由上述代碼可知,p2p_listen_in_find的內部實現完全遵循了7.2.2節介紹的和listen state相關的理論知識。
下面來看wpas_start_listen函數。
**p2p_supplicant.c::wpas_start_listen**
~~~
static int wpas_start_listen(void *ctx, unsigned int freq,
unsigned int duration, const struct wpabuf *probe_resp_ie)
{
struct wpa_supplicant *wpa_s = ctx;
/*
調用driver_nl80211.c的wpa_driver_set_ap_wps_p2p_ie函數,它用于將Probe Response幀信息和
Association Response幀信息。此函數為Android新增的功能,由廠商實現。
*/
wpa_drv_set_ap_wps_ie(wpa_s, NULL, probe_resp_ie, NULL);
/*
調用driver_nl80211.c的wpa_driver_nl80211_probe_req_report函數,其目的是讓wifi driver
收到Probe Request幀后,返回一個EVENT_RX_PROBE_REQ netlink消息給WPAS。
*/
if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {......}
wpa_s->pending_listen_freq = freq;
wpa_s->pending_listen_duration = duration;
/*
調用driver_nl80211.c的wpa_driver_nl80211_remain_on_channel函數,其目的是讓
wlan設備在指定頻段(第二個參數freq)上停留duration毫秒。注意,這個函數的返回值只是表示
wifi driver是否成功處理了這個請求,它不能用于判斷wifi driver是否已經切換到了指定頻段。
如果一切正常,當wifi driver切換到指定頻段后,它將發送一個名為EVENT_REMAIN_ON_CHANNEL的
netlink消息給WPAS。
*/
if (wpa_drv_remain_on_channel(wpa_s, freq, duration) < 0) {......}
wpa_s->off_channel_freq = 0;
wpa_s->roc_waiting_drv_freq = freq;
return 0;
}
~~~
wpas_start_listen比較簡單,不過有一些知識點請讀者注意。
* wpa_drv_set_ap_wps_ie為wifi driver設置了P2P IE信息。如果wifi driver自己處理Probe Resquest幀(即不發送EVENT_RX_PROBE_REQ消息給WPAS),則wifi driver將把此處設置的P2P IE信息填寫到Probe Response幀中。
* wpa_drv_probe_req_report要求wifi driver收到Probe Request幀后,發送EVENT_RX_PROBE_REQ消息給WPAS。WPAS內部將處理此消息,最終會回復一個Probe Response幀。這部分代碼請讀者自行閱讀。
* wpa_drv_remain_on_channel要求wifi driver在指定頻段工作一段時間。當wifi driver切換到指定頻段后,會發送EVENT_REMAIN_ON_CHANNEL消息給WPAS,WPAS內部將處理一些事情。這部分代碼也請讀者自行閱讀。
>[info] 提醒 筆者感覺wpa_drv_set_ap_wps_ie和wpa_drv_probe_req_report功能重復。不過由于driver.h對set_ap_wps_ie的功能描述不是特別清晰,請了解細節的讀者和我們分享相關的知識。另外,請讀者認真閱讀EVENT_RX_PROBE_REQ和EVENT_REMAIN_ON_CHANNEL消息的處理代碼。
**③、P2P設備掃描結果處理流程總結**
圖7-33展示了P2P設備掃描結果處理的流程。
:-: 
圖7-33 P2P設備掃描結果處理流程
>[info] 注意 圖7-33中,只有滿足一定條件,第6個及以后的函數才能執行。請讀者結合p2p_scan_res_handled的代碼來加深對圖7-32的體會。另外,由于Android平臺中wpa_driver_set_ap_wps_p2p_ie由廠商實現,故圖7-33沒有列出該函數。設備找到以后,下一步工作就是發起Provision Discovery流程,馬上來看它。
- 前言
- 第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 參考資料說明
- 附錄