Android WIFI 分析(一)

时间:2023-03-08 23:15:14
Android WIFI 分析(一)
本文基于《深入理解Android WiFi NFC和GPS 卷》和 Android N 代码结合分析
WifiService 是 Frameworks中负责wifi功能的核心服务,它主要借助wpa_supplicant(简称WPAS)来管理和控制Android 平台中的wifi 功能。
将通过两条线路来分析WifiService 服务:
1、WifiService 的创建及初始化;
2、在Setting中打开WiFi功能、扫描网络以及连接网络的流程;
最后介绍WifiWatchdogStateMachine 和 Captive Portal Check 这两个知识点。
WIFIService 的创建及初始化

WifiService 在SystemService 进程中被创建,Wifi 相关对象定义:

/frameworks/base/services/java/com/android/server/SystemServer.java

    private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
private static final String WIFI_NAN_SERVICE_CLASS =
"com.android.server.wifi.nan.WifiNanService";
private static final String WIFI_P2P_SERVICE_CLASS =
"com.android.server.wifi.p2p.WifiP2pService";

SystemService 类进程启动方法run() 调用startOtherService() 方法创建WifiService 进程:

                if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_NAN)) {
mSystemServiceManager.startService(WIFI_NAN_SERVICE_CLASS);//mSystemServiceManager 进程管理对象在run()方法中创建
} else {
Slog.i(TAG, "No Wi-Fi NAN Service (NAN support Not Present)");
}
mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
mSystemServiceManager.startService(
"com.android.server.wifi.scanner.WifiScanningService"); if (!disableRtt) {
mSystemServiceManager.startService("com.android.server.wifi.RttService");
}

对SystemService的研究可参考《深入理解Android:卷II》第3章

WifiService 继承SystemService,包名com.android.service.wifi,其构造函数初始化一个WifiServiceImpl 对象:

public final class WifiService extends SystemService {

    private static final String TAG = "WifiService";
final WifiServiceImpl mImpl; public WifiService(Context context) {
super(context);
mImpl = new WifiServiceImpl(context);
}
}

在此,先介绍两个知识点,分别是HSM(Hierarchical State Machine,结构化状态机)和AsyncChannel。

HSM 和AsyncChannel 介绍

HSM(对应的类是StateMachine) 和AsyncChannel 是Android Framework 中两个重要的类。

HSM 中的状态层级关系与Java中父子类的派生和继承关系类似,即在父状态中实现generic 的功能,而在子状态中实现一些特定的处理;不过与Java 中类派生不同的是,HSM 中父子状态对应的是毫无派生关系的两个类,使用时需要创建两个对象。

AsyncChannel 用于两个Handler 之间的通信,具体的通信方式为源Handler 通过sendMessage 向目标Handler 发送消息,而目标Handler 通过replyToMessage 回复源Handler 处理结果;这两个Handler 可位于同一个进程,也可分属于两个不同的进程。

1、HSM 的使用

addState():添加一个状态。同时还可指定父状态

transitionTo():将状态机切换到某个状态

obtainMessage():HSM内部是围绕一个Handler来工作的,外界只能调用HSM的obtainMessage()以获取一个Message

sendMessage():发送消息给HSM。HSM 中的Handler 会处理它

deferMessage():保留某个消息,该消息将留待下一个新状态中去处理

start():启动状态机

quit()、quitNow():停止状态机

HSM 中状态和状态直接的层级关系体现在:

1) SM启动后,初始状态的EA将按派生顺序执行,即其祖先状态先执行,子状态后执行

2) 当State发送切换时,旧State的exit 先执行,新State 的enter 后执行,并且新旧State 派生树上对应的State 也需要执行exit 或 enter 函数。类似C++ 类构造/析构函数执行顺序

3) State 处理Message 时,如子状态不能处理(返回NOT_HANDLED),则交给父状态去处理

2、AsyncChannel 的使用

1) 简单的request/response 模式下,Server 端无须维护Client 的信息,它只要处理来自Client 的请求即可。

Client 调用connectSync(同步连接)或connect(异步连接,连接成功后Client 会收到CMD_CHANNEL_HALF_CONNECTED 消息)即可连接到Server。

2) 与request/response 模式相反,即Server 端维护Client 的信息。

Server 可以向Client 发送自己的状态或者其他一些有意义的信息。wpa_cli 和wpa_supplicant 就是此模式的应用,wpa_cli 可以发送命令给WPAS 去执行;同时,WPAS 也会将自己的状态及其他一些信息通知给 wpa_cli。

以异步方式为例介绍第2种应用模式中AsyncChannel 的使用步骤:

1) Client 调用AsyncChannel 的connect() 函数,Client 的Handler 会收到一个名为CMD_CHANNEL_HALF_CONNECTED 消息;

2) Client 在处理CMD_CHANNEL_HALF_CONNECTED 消息时,需通过sendMessage() 函数向Server 端发送一个名为 CMD_CHANNEL_FULL_CONNECTION 的消息;

3) Server 端的Handler 将收到此CMD_CHANNEL_FULL_CONNECTION 消息,成功处理它后,Server 端先调用AsyncChannel 的connected() 函数,然后通过sendMessage() 函数向Client 端发送CMD_CHANNEL_FULLY_CONNECTED 消息;

4) Client 端收到CMD_CHANNEL_FULLY_CONNECTED 消息。至此,Client 和Server 端成功建立连接。

5) Clinet 和Server 端的两个Handler 可借助sendMessage() 和replyToMessage() 来完成请求消息及回复消息的传递。注意,只有针对那些需要回复的情况,Server 端才需调用replyToMessage()。

6) Client 和Server 的任意一端都可以调用disconnect() 函数以结束连接。该函数将导致Client 和Server 端都会收到CMD_CHANNEL_DISCONNECTED 消息。

注此部分流程描述来自AsyncChannel.java 文件中的注释,但实际第3步,AsyncChannel 一般由客户端创建,Server无法获取到。接下来通过代码展示正确的做法。

WifiManager 类的getChannel() 函数会创建一个AsyncChannel 以和WifiService 中的ServiceHandler 建立连接关系,并返回AsyncChannel 对象:

    private synchronized AsyncChannel getChannel() {
if (mAsyncChannel == null) {
Messenger messenger = getWifiServiceMessenger(); //是Server 端的Handler 在Client 端的代表
if (messenger == null) {
throw new IllegalStateException(
"getWifiServiceMessenger() returned null! This is invalid.");
} mAsyncChannel = new AsyncChannel(); //AsyncChannel 一般在Client 端创建
mConnected = new CountDownLatch(1);
//ServiceHandler 是WifiManager 定义的内部类Handler
Handler handler = new ServiceHandler(mLooper); //Client 端的Handler
mAsyncChannel.connect(mContext, handler, messenger); //mContext 是Client 端的Context 对象
try {
mConnected.await();
} catch (InterruptedException e) {
Log.e(TAG, "interrupted wait at init");
}
}
return mAsyncChannel;
}

getWifiServiceMessager() 函数,获取WifiService 端的Handler 引用,用于Client 与WifiService 建立AsyncChannel 通信:

    public Messenger getWifiServiceMessenger() {
try {
return mService.getWifiServiceMessenger(); //返回的Messenger 对象包含WifiService 的Handler
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

mService 是IWifiManager 类对象,其实质是一个AIDL 接口,WifiServiceImpl 类继承自IWifiManager.Stub,所以getWifiServiceMessenger() 函数的实现在WifiServiceImpl.java 中:

    /**
* Get a reference to handler. This is used by a client to establish
* an AsyncChannel communication with WifiService
*/
public Messenger getWifiServiceMessenger() {
enforceAccessPermission(); //权限检查
enforceChangePermission();
return new Messenger(mClientHandler); //通过Messenger 封装了目标Handler
}

connect() 函数将触发Client 端Handler(即ServiceHandler) 收到一个CMD_CHANNEL_HALF_CONNECTED 消息,由WifiManager 的ServiceHandler 处理:

        private void dispatchMessageToListeners(Message message) {
Object listener = removeListener(message.arg2);
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { //半连接成功
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); //向Server 端发送CMD_CHANNEL_FULL_CONNECTION
} else {
Log.e(TAG, "Failed to set up channel connection");
// This will cause all further async API calls on the WifiManager
// to fail and throw an exception
mAsyncChannel = null;
}
mConnected.countDown();
break;
                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: //连接成功
// Ignore
break;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: //连接关闭
Log.e(TAG, "Channel connection lost");
// This will cause all further async API calls on the WifiManager
// to fail and throw an exception
mAsyncChannel = null;
getLooper().quit(); //连接关闭,退出线程
break;

WifiServiceImpl.java 中定义ClientHandler,处理Client 端发送过来的消息:

    /**
* Handles client connections 处理Client 连接
*/
private class ClientHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
//处理因ac.connect调用而收到的CMD_CHANNEL_HALF_CONNECTED消息
//该消息携带了一个AsyncChannel 对象,即ac
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
// We track the clients by the Messenger
// since it is expected to be always available
mTrafficPoller.addClient(msg.replyTo); //WifiTrafficPoller 类
Android WIFI 分析(一)
                    } break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
if (DBG) Slog.d(TAG, "Send failed, client connection lost");
} else {
if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
}
mTrafficPoller.removeClient(msg.replyTo);
break;
}
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { //Server 端先收到此消息
AsyncChannel ac = new AsyncChannel(); //新建一个AsyncChannel对象,调用它的connect()函数
ac.connect(mContext, this, msg.replyTo); //msg.replyTo 代表Client 端的Handler,即WifiManager 中ServiceHandler
//connect()函数将触发CMD_CHANNEL_HALF_CONNECTED消息被发送,而且该消息会携带对应的AsyncChannel 对象,即此次的ac
break;
}

WifiTrafficPoller 类的addClient() 方法:

    void addClient(Messenger client) {
Message.obtain(mTrafficHandler, ADD_CLIENT, client).sendToTarget();
}

ADD_CLIENT 消息由该类的内部类TrafficHandler 处理:

                case ADD_CLIENT:
mClients.add((Messenger) msg.obj); //保存上面的AsyncChannel 对象,用于向Client发送消息
break;

由于Server 端无法得到Client 端的AsyncChannel 对象,所以就新创建了一个AsyncChannel,并connect 到Client 端。

WifiService 构造函数分析

在上文看到WifiService 的构造函数主要创建一个WifiServiceImpl 对象,所以重点查看WifiServiceImpl 的构造函数:

    public WifiServiceImpl(Context context) {
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
HandlerThread wifiStateMachineThread = new HandlerThread("WifiStateMachine");
wifiStateMachineThread.start(); mWifiStateMachine = new WifiStateMachine(mContext, mFacade,
wifiStateMachineThread.getLooper(), mUserManager, mWifiInjector,
new BackupManagerProxy(), mCountryCode); //创建一个WifiStateMachine对象
mWifiStateMachine.enableRssiPolling(true); //RSSI(信号接收强度)轮询机制
     //WPAS支持的RSSI信息包括:接收信号强度、连接速度(link speed)、噪声强度(noise)和频率 mClientHandler = new ClientHandler(wifiThread.getLooper()); //用于AsyncChannel,其交互对象来自WifiManager
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper()); //用于AsyncChannel,其交互对象来自WifiStateMachine
}

接下来重点分析WifiStateMachine 类。

WifiStateMachine 构造函数分析之一

WifiStateMachine 类继承自StateMachine,其构造函数:

    public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper,
UserManager userManager, WifiInjector wifiInjector,
BackupManagerProxy backupManagerProxy,
WifiCountryCode countryCode) {
super("WifiStateMachine", looper);
//WifiNative 用于和wpa_supplicant 交互
mWifiNative = WifiNative.getWlanNativeInterface();
//创建一个NetworkInfo,实际上代表一个网络设备的状态信息
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
//和BatteryStateService 交互,BSS 注册的服务名叫“batteryinfo”
mBatteryStats = IBatteryStats.Stub.asInterface(mFacade.getService(
BatteryStats.SERVICE_NAME));
//创建和NetworkManagmentService 交互的Binder 客户端
IBinder b = mFacade.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);
//判断系统是否支持Wifi Display功能(WFD)
mP2pSupported = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_DIRECT);
//内部将创建一个线程,并借助WifiNative 去接收处理来自WPAS的信息
mWifiMonitor = WifiMonitor.getInstance();
//WifiInfo 用于存储手机当前连接上的无线网络信息,包括IP地址、ssid 等内容
mWifiInfo = new WifiInfo();
//SupplicantStateTracker 用于跟踪WPAS 的状态,它是一个StateMachine
mSupplicantStateTracker = mFacade.makeSupplicantStateTracker(
context, mWifiConfigManager, getHandler());
//LinkProperties 用于描述网络连接(network link)的一些属性,如IP地址、DNS地址和路由设置
mLinkProperties = new LinkProperties();
}

将重点介绍WifiNative、WifiMonitor 以及SupplicantStateTracker

1) WifiNative 用于和WPAS 通信,其内部定义了较多的native 方法(对应的JNI 模块是com_android_server_wifi_WifiNative.cpp),本文将介绍最重要的两个方法:

第一个方法是startSupplicant(),用于启动WPAS。startSupplicant() 方法:

    private native static boolean startSupplicantNative(boolean p2pSupported);
public boolean startSupplicant(boolean p2pSupported) {
synchronized (sLock) {
return startSupplicantNative(p2pSupported);
}
}

其JNI 模块中的定义:

/frameworks/opt/net/wifi/service/jni/com_android_server_wifi_WifiNative.cpp

static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jclass, jboolean p2pSupported)
{
return (::wifi_start_supplicant(p2pSupported) == 0);
}

底层wifi_start_supplicant() native方法的定义:

/hardware/libhardware_legacy/wifi/wifi.c

int wifi_start_supplicant(int p2p_supported)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = ; /* wait at most 20 seconds for completion */
//和 P2P有关
if (p2p_supported) {
strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
strcpy(supplicant_prop_name, P2P_PROP_NAME);//"init.svc.p2p_supplicant"赋值 /* Ensure p2p config file is created */
if (ensure_config_file_exists(P2P_CONFIG_FILE) < ) {
ALOGE("Failed to create a p2p config file");
return -;
} } else {
strcpy(supplicant_name, SUPPLICANT_NAME);
strcpy(supplicant_prop_name, SUPP_PROP_NAME);//"init.svc.wpa_suppplicant"赋值
} /* Check whether already running */
if (property_get(supplicant_prop_name, supp_status, NULL)
&& strcmp(supp_status, "running") == ) {
return ; //如果WPAS已经启动,则直接返回
}
//配置文件对应“/data/misc/wifi/wpa_supplicant.conf”
/* Before starting the daemon, make sure its config file exists */
if (ensure_config_file_exists(SUPP_CONFIG_FILE) < ) {
ALOGE("Wi-Fi will not be enabled");
return -;
}
//entropy 文件,用于增加随机数生成的随机性
if (ensure_entropy_file_exists() < ) {
ALOGE("Wi-Fi entropy file was not created");
} /* Clear out any stale socket files that might be left over. */
wpa_ctrl_cleanup(); //关闭之前创建的wpa_ctrl 对象 /*
* Get a reference to the status property, so we can distinguish
* the case where it goes stopped => running => stopped (i.e.,
* it start up, but fails right away) from the case in which
* it starts in the stopped state and never manages to start
* running at all.
*/
pi = __system_property_find(supplicant_prop_name);
if (pi != NULL) {
serial = __system_property_serial(pi);
}
property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
//通过设置"ctl_start”属性来启动wpa_supplicant 服务,该属性将触发init fork 一个子进程用于运行wpa_supplicant。同时,init 还会添加一个新的属性“init.svc.wpa_supplicant”用于跟踪wpa_supplicant 的状态
property_set("ctl.start", supplicant_name);
sched_yield();
//此循环用于查询supplicant_prop_name 的属性值,如果其值变为“running”,表示wpa_supplicant 成功运行
while (count-- > ) { //最多等待20s
if (pi == NULL) {
pi = __system_property_find(supplicant_prop_name);
}
if (pi != NULL) {
/*
* property serial updated means that init process is scheduled
* after we sched_yield, further property status checking is based on this */
if (__system_property_serial(pi) != serial) {
__system_property_read(pi, NULL, supp_status);
if (strcmp(supp_status, "running") == ) {
return ;
} else if (strcmp(supp_status, "stopped") == ) {
return -; //如果WPAS 停止运行,则直接返回 -1
}
}
}
usleep();
}
return -;
}

第二个方法是connectToSupplicant(),它将通过WPAS 控制API 和 WPAS 建立交互关系:

    private native static boolean connectToSupplicantNative();
public boolean connectToSupplicant() {
synchronized (sLock) {
localLog(mInterfacePrefix + "connectToSupplicant");
return connectToSupplicantNative();
}
}

其对应JNI 模块方法:

static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jclass)
{
return (::wifi_connect_to_supplicant() == );
}

其native 方法:

/* Establishes the control and monitor socket connections on the interface */
int wifi_connect_to_supplicant()
{
static char path[PATH_MAX];
   //IFACE_DIR="/data/system/wpa_supplicant"
if (access(IFACE_DIR, F_OK) == ) {
snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);//primary_iface 为0表示STA,为1表示P2P
} else {
snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
}
return wifi_connect_on_socket_path(path);
}

查看wifi_connect_on_socket_path() :

int wifi_connect_on_socket_path(const char *path)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
//判断wpa_supplicant 进程是否已经启动
/* Make sure supplicant is running */
if (!property_get(supplicant_prop_name, supp_status, NULL)
|| strcmp(supp_status, "running") != ) {
ALOGE("Supplicant not running, cannot connect");
return -;
}
//创建第一个wpa_ctrl 对象,用于发送命令
ctrl_conn = wpa_ctrl_open(path);
..........
//创建第二个wpa_ctrl 对象,用于接收unsolicited event
monitor_conn = wpa_ctrl_open(path);
..........
//必须调用wpa_ctrl_attach 函数以启用unsolicited event 接收功能
if (wpa_ctrl_attach(monitor_conn) != ) {
.........
}
//创建一个socketpair,用于触发wifiNative 关闭和WPAS 的连接
if (socketpair(AF_UNIX, SOCK_STREAM, , exit_sockets) == -) {
wpa_ctrl_close(monitor_conn);
wpa_ctrl_close(ctrl_conn);
ctrl_conn = monitor_conn = NULL;
return -;
} return ;
}

由于支持两个并发设备,所以每个并发设置各有两个wpa_ctrl 对象。

ctrl_conn[PRIMARY]、monitor_conn[PRIMARY]:用于STA 设备;

ctrl_conn 用于向WPAS 发送命令并接收对应命令的回复,而monitor_conn 用于接收来自WPAS 的unsolicited event。

ctrl_conn[SECONDARY]、monitor_conn[SECONDARY]:用于P2P 设备;

另外,exit_sockets 保存了socketpair 创建的socket 句柄,这些句柄用于WifiService 通知WifiNative 去关闭它和WPAS 的连接。

wifi_send_command() 使用ctrl_conn 中的wpa_ctrl 对象向WPAS 发送命令并接收回复:

int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
{
int ret;
ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
if (ret == -) {
.........
} else if (ret < || strncmp(reply, "FAIL", ) == ) {
return -;
}
if (strncmp(cmd, "PING", ) == ) {
reply[*reply_len] = '\0';
}
return ;
}

wifi_ctrl_recv() 使用monitor_conn 中的wpa_ctrl 对象接收来自WPAS 的消息:

int wifi_ctrl_recv(char *reply, size_t *reply_len)
{
int res;
int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
struct pollfd rfds[]; memset(rfds, , * sizeof(struct pollfd));
rfds[].fd = ctrlfd;
rfds[].events |= POLLIN;
rfds[].fd = exit_sockets[];
rfds[].events |= POLLIN;
do {
res = TEMP_FAILURE_RETRY(poll(rfds, , ));
if (res < ) {
ALOGE("Error poll = %d", res);
return res;
} else if (res == ) {
/* timed out, check if supplicant is active
* or not ..
*/
res = wifi_supplicant_connection_active();
if (res < )
return -;
}
} while (res == ); if (rfds[].revents & POLLIN) {
return wpa_ctrl_recv(monitor_conn, reply, reply_len);
} /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
* or we timed out. In either case, this call has failed ..
*/
return -;
}

2) WifiMonitor 最重要的内容是其内部的WifiMonitor 线程,该线程专门用于接收来自WPAS 的消息

    private class MonitorThread extends Thread {
........
public void run() {
//noinspection InfiniteLoopStatement
for (;;) {
if (!mConnected) { //判断与WPAS 是否连接成功
if (DBG) Log.d(TAG, "MonitorThread exit because mConnected is false");
break;
}
//waitForEvent() 内部调用WifiNative 的waitForEventNative()
String eventStr = mWifiNative.waitForEvent(); // Skip logging the common but mostly uninteresting events
if (!eventStr.contains(BSS_ADDED_STR) && !eventStr.contains(BSS_REMOVED_STR)) {
if (DBG) Log.d(TAG, "Event [" + eventStr + "]");
mLocalLog.log("Event [" + eventStr + "]");
}
//解析WPAS 消息
if (dispatchEvent(eventStr)) {
if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
break;
}
}
}
}

dispatchEvent() 方法解析以及处理WPAS 的状态,重点分析其中的方法:

handleSupplicantStateChange() 用于处理WPAS 的状态变化,它把这些信息交给WifiStateMachine 去处理;而WifiStateMachine 将根据处理情况是否需要由SupplicantStateTracker 来处理。

handleDirverEvent() 用于处理来自Driver 的信息。

handleEvent() 用于处理其他消息事件,此函数定义如下:

WPAS 的状态指的是wpa_sm 状态机中的状态,包括WPA_DISCONNECTED、WPA_SCANNING等;WifiService 定义了SupplicantState 类来描述WPAS 的状态,包括DISCONNECTED、SCANNING等。

    private void handleEvent(int event, String remainder, String iface) {
switch (event) {
case DISCONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder, iface);
break;
case CONNECTED: //该事件表示WPAS 成功加入一个无线网络 handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder, iface);
break;
case SCAN_RESULTS: //表示WPAS 已经完成扫描,客户端可以来查询扫描结果
sendMessage(iface, SCAN_RESULTS_EVENT); //处理扫描结果消息
break;
case UNKNOWN:
...........
default:
break;
}
}

3) SupplicantStateTracker 用于跟踪和处理WPAS 的状态变化。

在WifiService 中,WPAS 的状态有SupplicantState 来表示,而管理状态模块就是SupplicantStateTracker。

SupplicantStateTracker 继承StateMachine,还定义了8个状态对象,其构造方法:

    public SupplicantStateTracker(Context c, WifiConfigManager wcs, Handler t) {
super(TAG, t.getLooper()); mContext = c;
mWifiConfigManager = wcs;
mBatteryStats = (IBatteryStats)ServiceManager.getService(BatteryStats.SERVICE_NAME);
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);//设置初始状态
//start the state machine
start(); //启动状态机
}

SupplicantState 中的AUTHENTICATING、ASSOCIATING、ASSOCIATED、FOUR_WAY_HANDSHAKE 和GROUP_HANDSHAKE 均对应此处的mHandshakeState;

SupplicantState 中的UNINITIALZED 和NVALID 对应此处的mUninitializedState;

WifiStateMachine 构造函数分析之二

        // CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState); //wifi 状态很多
addState(mInitialState, mDefaultState);
.........
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApState, mDefaultState);
// CHECKSTYLE:ON IndentationCheck setInitialState(mInitialState); //设置初始化状态

WifiStateMachine 的初始状态是mInitialState,其类型是InitialState。对HSN的介绍,其enter() 方法将被调用(由于InitialState 的父状态DefaultState 并未实现enter() 方法,故此处略去)。