首先来看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"属性值的变化。
:-: ![](https://box.kancloud.cn/bd1c4c272f9627aad27f765d2b7f5605_653x198.jpg)
图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所示。
:-: ![](https://box.kancloud.cn/f6aecfa81a54392f17c67917eba6ce38_1186x524.jpg)
图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 参考资料说明
- 附录