首先來看WifiStateMachine的構造函數,其內容較多,我們分兩段來介紹。
**1、WifiStateMachine構造函數分析之一**
**WifiStateMachine.java::WifiStateMachine構造函數代碼段一**
~~~
public WifiStateMachine(Context context, String wlanInterface) {
super(TAG);
mContext = context;
mInterfaceName = wlanInterface;
// 創建一個NetworkInfo,它實際上代表一個網絡設備的狀態信息(status of a network interface)
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI,0, NETWORKTYPE, "");
// 和BatteryStatsService交互,BSS注冊的服務名叫“batteryinfo”
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
// 創建和NewtorkManagmentService交互的Binder客戶端
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);
/*
判斷系統是否支持Wi-Fi Display功能。本書不討論WFD,感興趣的讀者可閱讀筆者的一篇博文
http:// blog.csdn.net/innost/article/details/8474683
" Android Wi-Fi Display(Miracast)介紹"。
*/
mP2pSupported = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
/*
WifiNative:用于和wpa_supplicant交互。它和4.2.3節中控制API知識相關。
WifiMonitor:內部將創建一個線程,并借助WifiNative去接收并處理來自WPAS的信息。
WifiConfigStore:它對應一個配置文件,位置為/data/misc/wifi/ifconfig.txt。
該文件用于存儲每個無線網絡的配置項。例如代理地址、靜態IP地址等。讀者可在Settings
中選擇某個無線網絡,長按以彈出修改對話框,然后選擇“高級選項”即可設置這些信息。
*/
mWifiNative = new WifiNative(mInterfaceName);
mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
mWifiMonitor = new WifiMonitor(this, mWifiNative);
// 用于保存DHCP的一些信息
mDhcpInfoInternal = new DhcpInfoInternal();
// WifiInfo用于存儲手機當前連接上的無線網絡的一些信息,包括IP地址、ssid等內容
mWifiInfo = new WifiInfo();
// SupplicantStateTracker用于跟蹤WPAS的狀態,它也是一個StateMachine
mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,getHandler());
// LinkProperties用于描述網絡鏈接(network link)的一些屬性,如IP地址、DNS地址和路由設置
mLinkProperties = new LinkProperties();
// WifiApConfigStore和Soft AP模式有關,用于存儲Soft AP模式中使用到的一些配置信息
// WifiApConfigStore是一個StateMachine。配置信息存儲于/data// misc/wifi/softap.conf中
WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(context, getHandler());
wifiApConfigStore.loadApConfiguration();
// mWifiApConfigChannel的類型是AsyncChannel,它將和wifiApConfigStore中的某個Handler通信
mWifiApConfigChannel.connectSync(mContext, getHandler(),wifiApConfigStore.getMessenger());
mNetworkInfo.setIsAvailable(false);
mLinkProperties.clear();
......
// 設置掃描間隔時間:當驅動不支持Background掃描時,Framework將定時開展掃描工作
// 默認值為300秒
mDefaultFrameworkScanIntervalMs = mContext.getResources()
.getInteger(R.integer.config_wifi_framework_scan_interval);
/*
driver stop延遲,默認是120秒。該變量和emergency calls(緊急呼叫)有關。
處于這種模式下,即使用戶選擇關閉Wi-Fi,WifiStateMachine也不會立即執行它,而是要
等待一段時間才真正去關閉Wi-Fi。
*/
mDriverStopDelayMs = mContext.getResources().getInteger(R.integer.config_wifi_driver_stop_delay);
// 是否支持Background掃描
mBackgroundScanSupported = mContext.getResources()
.getBoolean(R.bool.config_wifi_background_scan_support);
// 和P2P有關。以后再介紹
mPrimaryDeviceType = mContext.getResources().getString(R.string.config_wifi_p2p_device_type);
// WIFI_SUSPEND_OPTIMIZATIONS_ENABLED變量用于控制手機睡眠期間是否保持Wi-Fi開啟
mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
......// 處理ACTION_START_SCAN廣播事件
......// 處理ACTION_SCREEN_ON/OFF廣播事件
......// 處理ACTION_DELAYED_DRIVER_STOP廣播事件
......// 監視ContentProvider中WIFI_SUSPEND_OPTIMIZATIONS_ENABLED設置的變化
// mScanResultCache用于保存掃描結果
mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
......// 申請WakeLock
}
~~~
重點介紹其中的三個對象,分別是WifiNative、WifiMonitor以及SupplicantStateTracker。
**①、WifiNative**
根據上文描述,WifiNative用于和WPAS通信,其內部定義了較多的native方法(對應的JNI模塊是android_net_wifi_Wifi)。本節介紹其中最重要的兩個方法。
第一個方法是startSupplicant,用于啟動WPAS。startSupplicant是一個native函數,其JNI[^①]函數是**android_net_wifi_startSupplicant**,代碼如下所示。
**android_net_wifi_Wifi.c::android_net_wifi_startSupplicant**
~~~
static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject,jboolean p2pSupported)
{
return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
}
~~~
wifi_start_supplicant代碼如下所示。
**wifi.c::wifi_start_supplicant**
~~~
int wifi_start_supplicant(int p2p_supported)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 200;
// 該宏在build/core/combo/include/arch/linux-arm/AndroidConfig.h中被定義為1
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
const prop_info *pi;
unsigned serial = 0, i;
#endif
// 和P2P有關
if (p2p_supported) {// P2P_SUPPLICANT_NAME值為“p2p_supplicant”
strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
// P2P _PROP_NAME值為“init.svc.p2p_supplicant”
strcpy(supplicant_prop_name, P2P_PROP_NAME);
/*
P2P_CONFIG_FILE的值為“/data/misc/wifi/p2p_supplicant.conf”。下面這個函數將把
/system/etc/wifi/wpa_supplicant.conf的內容復制到P2P_CONFIG_FILE中。
*/
if (ensure_config_file_exists(P2P_CONFIG_FILE) < 0)
return -1;
} else {
strcpy(supplicant_name, SUPPLICANT_NAME);// SUPPLICANT_NAME值為“wpa_supplicant”
// SUPP_PROP_NAME值為“init.svc.wpa_supplicant”
strcpy(supplicant_prop_name, SUPP_PROP_NAME);
}
// 如果WPAS已經啟動,則直接返回
if (property_get(supplicant_name, supp_status, NULL)
&& strcmp(supp_status, "running") == 0) return 0;
// SUPP_CONFIG_FILE的值為“/data/misc/wifi/wpa_supplicant.conf”
if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) return -1;
// entropy文件,用于增加隨機數生成的隨機性
if (ensure_entropy_file_exists() < 0)
ALOGE("Wi-Fi entropy file was not created");
// 關閉之前創建的wpa_ctrl對象
wifi_wpa_ctrl_cleanup();
for (i=0; i<MAX_CONNS; i++)
exit_sockets[i][0] = exit_sockets[i][1] = -1;
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
// supplicant_prop_name值為“init.svc.wpa_supplicant”
pi = __system_property_find(supplicant_prop_name);
......
#endif
property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
/*
通過設置“ctrl.start”屬性來啟動wpa_supplicant服務。該屬性將觸發init fork一個子
進程用于運行wpa_supplicant。同時,init還會添加一個新的屬性
“init.svc.wpa_supplicant”用于跟蹤wpa_supplicant的狀態。
*/
property_set("ctl.start", supplicant_name);
sched_yield();
// 下面這個循環用于查詢“init.svc.wpa_supplicant”的屬性值
// 如果其值變成“running”,表示wpa_supplicant成功運行
while (count-- > 0) {// count初值為200。while循環最多等待20秒
#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
if (pi == NULL) {
pi = __system_property_find(supplicant_prop_name);
}
if (pi != NULL) {
__system_property_read(pi, NULL, supp_status);
if (strcmp(supp_status, "running") == 0) return 0;
else if (pi->serial != serial &&// 如果WPAS已經停止,則直接返回-1
strcmp(supp_status, "stopped") == 0) return -1;
}
#else
......
#endif
usleep(100000);// 等待wpa_supplicant的狀態
}
return -1;
}
~~~
圖5-3顯示了wpa_supplicant運行過程中及退出后"init.svc.wpa_supplicant"屬性值的變化。
:-: 
圖5-3 init.svc.wpa_supplicant屬性
>[info] 提示 對Android屬性機制和init工作原理感興趣的讀者不妨閱讀《深入理解Android:卷Ⅰ》第3章。
第二個要介紹的函數是connectToSupplicant,它將通過WPAS控制API和WPAS建立交互關系。
**WifiNative.java::connectToSupplicant**
~~~
public boolean connectToSupplicant() {
// mInterface的值為”wlan0”,由屬性“wifi.interface”決定
return connectToSupplicant(mInterface);// 調用native函數
}
private native boolean connectToSupplicant(String iface);
~~~
與connectToSupplicant對應的JNI函數是android_net_wifi_connectToSupplicant,其代碼如下所示。
**android_net_wifi_Wifi.cpp::android_net_wifi_connectToSupplicant**
~~~
static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface)
{
ScopedUtfChars ifname(env, jIface);
return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0);
}
~~~
wifi_connect_to_supplicant的代碼如下所示。
**wifi.c::wifi_connect_to_supplicant**
~~~
int wifi_connect_to_supplicant(const char *ifname)
{
char path[256];
/*
Android 4.2支持STA和P2P設備并發(concurrent)工作,STA用PRIMARY(值為0)來標示,
而P2P設備用SECONDARY(值為1)代表。is_primary_interface用于判斷ifname是否代表STA。
*/
if (is_primary_interface(ifname)) {
// IFACE_DIR的值為“/data/system/wpa_supplicant”。筆者測試的幾個手機中都沒有該文件夾
if (access(IFACE_DIR, F_OK) == 0) {
snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
} else {
strlcpy(path, primary_iface, sizeof(path));
}
return wifi_connect_on_socket_path(PRIMARY, path);// PRIMARY值為0
} else {
sprintf(path, "%s/%s", CONTROL_IFACE_PATH, ifname);
return wifi_connect_on_socket_path(SECONDARY, path);// SECONDARY值為1
}
}
~~~
來看wifi_connect_on_socket_path,其代碼如下所示。
**wifi.c::wifi_connect_on_socket_path**
~~~
int wifi_connect_on_socket_path(int index, const char *path)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
// 判斷wpa_supplicant進程是否已經啟動
if (!property_get(supplicant_prop_name, supp_status, NULL)
|| strcmp(supp_status, "running") != 0) return -1;
// 創建第一個wpa_ctrl對象,用于發送命令
ctrl_conn[index] = wpa_ctrl_open(path);
......
// 創建第二個wpa_ctrl對象,用于接收unsolicited event
monitor_conn[index] = wpa_ctrl_open(path);
......
// 必須調用wpa_ctrl_attach函數以啟用unsolicited event接收功能
if (wpa_ctrl_attach(monitor_conn[index]) != 0) {......}
// 創建一個socketpair,它用于觸發WifiNative關閉和WPAS的連接
if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets[index]) == -1) {......}
return 0;
}
~~~
由于Android 4.2支持兩個并發設備,所以每個并發設備各有兩個wpa_ctrl對象。
* ctrl_conn[PRIMARY]、monitor_conn[PRIMARY]:用于STA設備。ctrl_conn用于向WPAS發送命令并接收對應命令的回復,而monitor_conn用于接收來自WPAS的unsolicited event。
* ctrl_conn[SECONDARY]、monitor_conn[SECONDARY]:這兩個wpa_ctrl對象用于P2P設備。
另外,exit_sockets保存了socketpair創建的socket句柄,這些句柄用于WifiService通知WifiNative去關閉它和WPAS的連接。
>[info] 提示 wifi.c中,wifi_send_command會使用ctrl_conn中的wpa_ctrl對象向WPAS發送命令并接收回復,而wifi_recv函數將使用monitor_conn中的wpa_ctrl對象接收來自WPAS的消息。這兩個函數比較簡單,請讀者可自行閱讀它。
下面來看WifiMonitor,它將使用monitor_conn中的wpa_ctrl對象。
**②、WifiMonitor**
WifiMonitor最重要的內容是其內部的WifiMonitor線程,該線程專門用于接收來自WPAS的消息。代碼如下所示。
**WifiMonitor.java::MonitorThread**
~~~
class MonitorThread extends Thread {
public MonitorThread() {
super("WifiMonitor");
}
public void run() {
if (connectToSupplicant()) {// 連接WPAS, mStateMachine指向WifiStateMachine
// 連接成功后,將向WifiStateMachine發送SUP_CONNECTION_EVENT消息
mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
} else {
mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
return;
}
for (;;) {
// waitForEvent內部會調用wifi.c中的wifi_wait_on_socket函數
String eventStr = mWifiNative.waitForEvent();
// 解析WPAS的消息格式。EVENT_PREFIX_STR的值為“CTRL-EVENT-”
if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
......// 非“CTRL-EVENT-”消息
continue;
}
// 處理“CTRL-EVENT-”消息
String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
int nameEnd = eventName.indexOf(' ');
if (nameEnd != -1)
eventName = eventName.substring(0, nameEnd);
......
int event;
if (eventName.equals(CONNECTED_STR))// 對應為“CONNECTED”消息
event = CONNECTED;
......
else if (eventName.equals(STATE_CHANGE_STR))// 對應為“STATE-CHANGED”
event = STATE_CHANGE;
else if (eventName.equals(SCAN_RESULTS_STR))// 對應為“SCAN-RESULTS”
event = SCAN_RESULTS;
......
else if (eventName.equals(DRIVER_STATE_STR))// 對應為“DRIVER-STATE”
event = DRIVER_STATE;
else if (eventName.equals(EAP_FAILURE_STR))// 對應為“EAP-FAILURE”
event = EAP_FAILURE;
else
event = UNKNOWN;
/*
提取消息中的其他信息,以CONNECTED消息為例,其消息全內容為:
CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:xx:xx completed
其中,xx:xx:xx:xx:xx:xx代表目標AP的BSSID。
*/
String eventData = eventStr;
if (event == DRIVER_STATE || event == LINK_SPEED)
eventData = eventData.split(" ")[1];
else if (event == STATE_CHANGE || event == EAP_FAILURE) {
......
} ......
if (event == STATE_CHANGE) {// WPAS狀態發生變化
handleSupplicantStateChange(eventData);
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
}......
else {// 其他事件處理
handleEvent(event, eventData);
}
mRecvErrors = 0;
}
}
......
}
~~~
上述代碼中:
* handleSupplicantStateChange用于處理WPAS的狀態變化(見下文解釋),它將先把這些變化信息交給WifiStateMachine去處理。而WifiStateMachine將根據處理情況再決定是否需要由下一節介紹的SupplicantStateTracker來處理。handleSupplicant StateChange代碼比較簡單,讀者可自行閱讀它。
* handleDriverEvent用于處理來Driver的信息[^②]。
* handleEvent用于處理其他消息事件。詳情見下文。
>[info] 注意 WPAS的狀態指的是wpa_sm狀態機中的狀態,包括WPA_DISCONNECTED、WPA_INTERFACE_DISABLED、WPA_INACTIVE、WPA_SCANNING、WPA_AUTHENTICATING、WPA_ASSOCIATING、WPA_ASSOCIATED、WPA_4WAY_HANDSHAKE、WPA_GROUP_HANDSHAKE、WPA_COMPLETED共10個狀態。WifiService定義了SupplicantState類來描述WPAS的狀態,包括DISCONNECTED、INTERFACE_DISABLED、INACTIVE、SCANNING、AUTHENTICATING、ASSOCIATING、ASSOCIATED、FOUR_WAY_HANDSHAKE、GROUP_HANDSHAKE、COMPLETED、DORMANT、UNINITIALIZED、INVALID共13個狀態。其中最后三個狀態是WifiService定義的,但筆者在代碼中沒有找到使用它們的地方。
下面簡單介紹handleEvent,其代碼如下所示。
**WifiMonitor.java::handleEvent**
~~~
void handleEvent(int event, String remainder) {
switch (event) {
case DISCONNECTED:
handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);
break;
case CONNECTED:// 該事件表示WPAS成功加入一個無線網絡
handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);
break;
case SCAN_RESULTS:// 該事件表示WPAS已經完成掃描,客戶端可以來查詢掃描結果
mStateMachine.sendMessage(SCAN_RESULTS_EVENT);// 處理掃描結果消息
break;
case UNKNOWN:
break;
}
}
~~~
先介紹SupplicantStateTracker。后文再分析CONNECTED和SCAN_RESULTS消息的處理流程。
**③、SupplicantStateTracker**
SupplicantStateTracker用于跟蹤和處理WPAS的狀態變化。根據前面對WPAS中的狀態以及WifiService中的狀態介紹可知。在WifiService中,WPAS的狀態由SupplicantState來表示,而和它相關的狀態管理模塊就是此處的SupplicantStateTracker。SupplicantStateTracker也從StateMachine派生,并且它還定義了8個狀態對象。相關代碼如下所示。
**SupplicantStateTracker.java::SupplicantStateTracker**
~~~
public SupplicantStateTracker(Context c, WifiStateMachine wsm,WifiConfigStore wcs, Handler t) {
super(TAG, t.getLooper());
mContext = c;
mWifiStateMachine = wsm;
mWifiConfigStore = wcs;
addState(mDefaultState);
addState(mUninitializedState, mDefaultState);
addState(mInactiveState, mDefaultState);
addState(mDisconnectState, mDefaultState);
addState(mScanState, mDefaultState);
addState(mHandshakeState, mDefaultState);
addState(mCompletedState, mDefaultState);
addState(mDormantState, mDefaultState);
setInitialState(mUninitializedState);// 初始狀態為mUninitializedState
start();// 啟動狀態機
}
~~~
* SupplicantState中的AUTHENTICATING、ASSOCIATING、ASSOCIATED、FOUR_WAY_HANDSHAKE和GROUP_HANDSHAKE均對應于此處的mHandshakeState。
* SupplicantState中的UNINITIALIZED和INVALID對應于此處的mUnitializedState。SupplicantStateTracker比較簡單,而且它也不影響本章的分析流程。讀者可在閱讀完本章的基礎上,自行對其開展研究。
下面來看WifiStateMachine構造函數的最后一部分。
**2、WifiStateMachine構造函數分析之二**
**WifiStateMachine.java::WifiStateMachine構造函數代碼段二**
~~~
......// WifiStateMachine中的狀態。說實話,筆者還沒見過如此復雜的狀態機
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mDriverUnloadingState, mDefaultState);
addState(mDriverUnloadedState, mDefaultState);
addState(mDriverFailedState, mDriverUnloadedState);
......// WifiStateMachine一共定義了30個狀態
addState(mSoftApStoppingState, mDefaultState);
setInitialState(mInitialState);// 設置初始狀態為mInitialState
......// 和StateMachine日志記錄相關設置
start();// 啟動狀態機
}
~~~
WifiStateMachine共定義30個狀態,其種類和層級關系如圖5-4所示。
:-: 
圖5-4 WifiStateMachine中的狀態及層級關系
圖5-4中,箭頭所指的狀態為父狀態。本節先介紹和初始狀態的相關代碼,其他狀態的功能等碰到它們時再來分析。
>[info] 提示 如果算上SupplicantStateTracker中的8個狀態以及后續章節將要介紹的P2pStateMachine中的15個狀態,Java層中Wi-Fi相關的狀態機竟然多達63個狀態(還沒有計算Wi-Fi模塊其他代碼中定義的好些個狀態機所包含的狀態)。筆者很難理解為什么WifiService相關模塊會定義如此多的狀態。這些狀態使得WifiService的分析難度陡增。而且,在整個Wi-Fi模塊中,wpa_supplicant作為核心已經完成了絕大部分的工作,為什么WifiService還會如此復雜呢?歡迎讀者對此問題和筆者展開討論。
WifiStateMachine的初始狀態是mInitialState,其類型是InitialState。根據前文對HSM的介紹,其enter函數將被調用(由于InitialState的父狀態DefaultState并未實現enter函數,故此處略去)。
**WifiStateMachine.java::InitialState:enter**
~~~
class InitialState extends State {
public void enter() {
// 判斷Wlan Driver是否已經加載,其內部實現通過"wlan.driver.status"屬性的值來判斷
if (mWifiNative.isDriverLoaded())
transitionTo(mDriverLoadedState);
else transitionTo(mDriverUnloadedState);// 假設此時驅動還沒有加載,故我們將轉入此狀態
// 獲取和WifiP2pService交互的對象
mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(
Context.WIFI_P2P_SERVICE);
// mWifiP2pChannel用于和WifiP2pService中的某個Handler交互
mWifiP2pChannel.connect(mContext, getHandler(),
mWifiP2pManager.getMessenger());
try {
mNwService.disableIpv6(mInterfaceName);
// 禁止Ipv6,NWService將和Netd交互
} ......
}
}
~~~
結合上述代碼,當WifiStateMachine開始運行后,其最終將進入DriverUnloadedState。由于DriverUnloadedState的enter函數沒有做什么有意義的工作,所以此處不再討論它。
至此,WifiService第一條分析路線就算結束。雖然WifiService創建工作涉及的流程并不長,但相信讀者也會感覺WifiService的代碼難度其實并不算小。從下一節開始,讀者還將進一步體會到這一點。
[^①]:可參考《深入理解Android:卷Ⅰ》第2章JNI相關的重要知識。
[^②]:筆者搜索了相關代碼,在wlan芯片廠商提供的一些供WPAS使用的動態庫中會發送DRIVER-EVENT。相關代碼可參考
hardware/broadcom/wlan/bcmdhd/wpa_supplicant_8_lib/driver_cmd_nl80211.c
- 前言
- 第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 參考資料說明
- 附錄