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 類
} 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 = 200; /* 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) < 0) { ALOGE("Failed to create a p2p config file"); return -1; } } 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") == 0) { return 0; //如果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) < 0) { ALOGE("Wi-Fi will not be enabled"); return -1; } //entropy 文件,用於增加隨機數生成的隨機性 if (ensure_entropy_file_exists() < 0) { 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-- > 0) { //最多等待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") == 0) { return 0; } else if (strcmp(supp_status, "stopped") == 0) { return -1; //如果WPAS 停止運行,則直接返回 -1 } } } usleep(100000); } return -1; }
第二個方法是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() == 0); }
其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) == 0) { 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") != 0) { ALOGE("Supplicant not running, cannot connect"); return -1; } //創建第一個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) != 0) { ......... } //創建一個socketpair,用於觸發wifiNative 關閉和WPAS 的連接 if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) { wpa_ctrl_close(monitor_conn); wpa_ctrl_close(ctrl_conn); ctrl_conn = monitor_conn = NULL; return -1; } return 0; }
由於支持兩個並發設備,所以每個並發設置各有兩個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 == -2) { ......... } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) { return -1; } if (strncmp(cmd, "PING", 4) == 0) { reply[*reply_len] = '\0'; } return 0; }
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[2]; memset(rfds, 0, 2 * sizeof(struct pollfd)); rfds[0].fd = ctrlfd; rfds[0].events |= POLLIN; rfds[1].fd = exit_sockets[1]; rfds[1].events |= POLLIN; do { res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000)); if (res < 0) { ALOGE("Error poll = %d", res); return res; } else if (res == 0) { /* timed out, check if supplicant is active * or not .. */ res = wifi_supplicant_connection_active(); if (res < 0) return -2; } } while (res == 0); if (rfds[0].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; }
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() 方法,故此處略去)。