WifiP2pService和第5章介紹的WifiService一樣,都屬于Android系統中負責處理Wi-Fi相關工作的核心模塊。其中,WifiService處理和WLAN網絡連接相關的工作,而WifiP2pService則專門負責處理和Wi-Fi P2P相關的工作。圖7-24所示為WifiP2pService家族類圖。
:-: 
圖7-24 WifiP2pService類圖
圖7-24所示的WifiP2pService家族類圖和圖5-1所示的WifiService家族類圖類似,此處就不詳細討論了。直接來看WifiP2pService的代碼,首先是它的構造函數,如下所示。
**WifiP2pService.java::WifiP2pService**
~~~
public WifiP2pService(Context context) {
mContext = context;
mInterface = "p2p0";// P2P使用的虛擬網絡接口設備名為“p2p0”
mActivityMgr = (ActivityManager)context.getSystemService(Activity.ACTIVITY_SERVICE);
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
// 判斷系統是否支持WiFi-Direct功能
mP2pSupported = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
// 獲取PrimaryDeviceType,默認值是“10-0050F204-5”。結合圖6-15可知
// “10”是Category ID,代表Telephone
// “0050F204”是WFA的OUI,最后一個“5”是Sub Category ID,在Telephone大類里邊,它代表
// 支持Dual Mode的Smartphone(規范中定義為Smart phone-Dual mode)
mThisDevice.primaryDeviceType = mContext.getResources().getString(com.android.internal.R.string.config_wifi_p2p_device_type);
// WifiP2pService主要工作也是由狀態機來完成的,即下面的這個P2pStateMachine
mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
mP2pStateMachine.start();// 啟動P2P狀態機
}
~~~
P2pStateMachine是WifiP2pService定義的內部類,它比第5章介紹的WifiStateMachine簡單,其構造函數如下所示。
**WifiP2pService.java::P2pStateMachine構造函數**
~~~
P2pStateMachine(String name, boolean p2pSupported) {
super(name);
addState(mDefaultState);// 為狀態機添加狀態,一共15個狀態
addState(mP2pNotSupportedState, mDefaultState);
......
if (p2pSupported)
setInitialState(mP2pDisabledState);// 初始狀態為P2pDisabledState
else
setInitialState(mP2pNotSupportedState);
}
~~~
圖7-25描述了P2pStateMachine中定義的各個狀態及層級關系。
:-: 
圖7-25 P2pStateMachine狀態機
P2pStateMachine的初始狀態是P2pDisabledState,它和父狀態DefaultState的Entry Action都沒有執行什么有意義的事情,故此處略去對二者EA的介紹。
P2pStateMachine是WifiP2pService的核心,我們馬上來介紹它的工作流程。
**1、CMD_ENABLE_P2P處理流程**
P2pStateMachine雖然屬于WifiP2pService,但它也受WifiStateMachine的影響。通過5.2.3節“WifiStateMachine構造函數分析之二”中對WifiStateMachine InitialState EA的介紹,會發現WifiStateMachine將創建一個名為mWifiP2pChannel的AsyncChannel對象用于向P2pStateMachine發送消息。
在Android平臺中,如果用戶打開Wi-Fi功能,P2pStateMachine就會收到第一個消息CMD_ENABLE_P2P。該消息是WifiStateMachine進入DriverStartedState后,在其EA中借助mWifiP2pChannel向P2pStateMachine發送的(可參考5.3.2節SUP_CONNECTION_EVENT處理流程分析)[^①]。
P2pStateMachine此時處于P2pDisabledState,它對CMD_ENABLE_P2P消息的處理邏輯如下所示。
**WifiP2pService.java::P2pDisabledState:enter**
~~~
class P2pDisabledState extends State {
public boolean processMessage(Message message) {
switch (message.what) {
case WifiStateMachine.CMD_ENABLE_P2P:
try {
mNwService.setInterfaceUp(mInterface);
} ......
// 啟動WifiMonitor,它將通過wpa_ctl連接上wpa_supplicant。關于wpa_supplicant的啟動
// 讀者可參考5.2.3節“WifiNative介紹”
mWifiMonitor.startMonitoring();
// 轉入P2pEnablingState,其EA未作有意義的事情,讀者可自行閱讀它
transitionTo(mP2pEnablingState);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
~~~
處理完CMD_ENABLE_P2P消息后,P2pStateMachine將創建一個WifiMonitor用于接收來自wpa_supplicant的消息,同時狀態機將轉入P2pEnablingState。
WifiMonitor連接wpa_supplicant之后,WifiMonitor會發送一個SUP_CONNECTION_EVENT給P2pStateMachine。該消息將由P2pEnablingState處理,馬上來看相關的處理流程。
**2、SUP_CONNECTION_EVENT處理流程**
代碼如下。
**WifiP2pService.java::P2pEnablingState:processMessage**
~~~
class P2pEnablingState extends State {
......
public boolean processMessage(Message message) {
switch (message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
transitionTo(mInactiveState);// 轉入InactiveState
break;
......
}
return NOT_HANDLED
}
}
~~~
根據5.2.1節HSM的知識,當狀態機轉入InactiveState后,首先執行的是其父狀態P2pEnabledState的EA,然后才是InactiveState自己的EA。由于InactiveState的EA僅打印了一句日志輸出,故此處僅介紹P2pEnabledState的EA,相關代碼如下所示。
**WifiP2pService.java::P2pEnabledState:enter**
~~~
class P2pEnabledState extends State {
public void enter() {
// 發送WIFI_P2P_STATE_CHANGED_ACTION廣播,并設置EXTRA_WIFI_STATE狀態為
// WIFI_P2P_STATE_ENABLED
sendP2pStateChangedBroadcast(true);
mNetworkInfo.setIsAvailable(true);
/*
發送WIFI_P2P_CONNECTION_CHANGED_ACTION廣播,它將攜帶WifiP2pInfo和NetworkInfo信息。
注意,下面這個函數還會向WifiStateMachine發送P2P_CONNECTION_CHANGED消息。讀者不妨
自行研究WifiStateMachine對P2P_CONNECTION_CHANGED消息的處理流程。
*/
sendP2pConnectionChangedBroadcast();
initializeP2pSettings();// 初始化P2P的一些設置,詳情見下文
}
}
~~~
我們重點關注上面代碼中的initializeP2pSettings函數,其代碼如下所示。
**WifiP2pSettings.java::initializeP2pSettings**
~~~
private void initializeP2pSettings() {
/*
發送“SET persistent_reconnect 1”給WPAS,該命令對應如下一種應用場景。
當發現一個Persistent Group時,如果 persistent_reconnect為1,則可利用之前保存的配置信息自動重連,
重新連接時無需用戶參與。如果persistent_reconnect為0,則需要提醒用戶,讓用戶來決定是否加入此
persistent group。
*/
mWifiNative.setPersistentReconnect(true);
/*
獲取P2P Device Name,先從數據庫中查詢“wifi_p2p_device_name”字段的值,如果數據庫中沒有設置
該字段,則取數據庫中“android_id”字段值的前4個字符并在其前面加上“Android_”字符串以
組成P2P Device Name。以Galaxy Note 2為例,數據庫文件是/data/data/com.android.providers.
settings/database/settings.db,所查詢的表名為secure,wifi_p2p_device_name字段取值為
“Android_4aa9”,android_id字段取值為“4aa9213016889423”。
*/
mThisDevice.deviceName = getPersistedDeviceName();// mThisDevice指向一個WifiP2pDevice對象
// 將P2P DeviceName保存到WPAS中
mWifiNative.setDeviceName(mThisDevice.deviceName);
// 設置P2P網絡SSID的后綴。如果本設備能扮演GO,則它構建的Group對應的SSID后綴就是此處設置的后綴名
mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
// 設置Primary DeviceType
mWifiNative.setDeviceType(mThisDevice.primaryDeviceType);
// 設置支持的WSC配置方法
mWifiNative.setConfigMethods("virtual_push_button physical_display keypad");
// 設置STA連接的優先級高于P2P連接
mWifiNative.setConcurrencyPriority("sta");
// 從WPAS中獲取P2P Device Address
mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
// 更新自己的狀態,并發送WIFI_P2P_THIS_DEVICE_CHANGED_ACTION消息
updateThisDevice(WifiP2pDevice.AVAILABLE);
mClientInfoList.clear();
// 清空WPAS中保存peer P2P Device和Service信息
mWifiNative.p2pFlush(); mWifiNative.p2pServiceFlush();
mServiceTransactionId = 0; mServiceDiscReqId = null;
/*
WPAS中會保存persistent Group信息,而P2pStateMachine也會保存一些信息,下面這個函數將根據
WPAS中的信息來更新P2pStateMachine中保存的Group信息。P2pStateMachine通過一個名為mGroups
的成員變量(類型為WifiP2pGroupList)來保存所有的Group信息。
*/
updatePersistentNetworks(RELOAD);
}
~~~
至此,P2pStateMachine就算初始化完畢,接下來的工作就是處理用戶發起的操作。
首先來看WifiP2pSettings中WifiP2pManager的discoverPeers函數,它將發送DISCOVER_PEERS消息給P2pStateMachine。
**3、DISCOVER_PEERS處理流程**
P2pStateMachine當前處于InactiveState,不過DISCOVER_PEERS消息卻是由其父狀態P2pEnabledState來處理的,相關代碼如下所示。
**WifiP2pService.java::P2pEnabledState:processMessage**
~~~
class P2pEnabledState extends State{
public boolean processMessage(Message message) {
switch (message.what) {
case WifiP2pManager.DISCOVER_PEERS:
clearSupplicantServiceRequest();// 先取消Service Discovery請求
// 發送“P2P_FIND 超時時間”給WPAS,DISCOVER_TIMEOUT_S值為120秒
if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
// 發送WIFI_P2P_DISCOVERY_CHANGED_ACTION廣播以通知P2P Device Discovery已啟動
sendP2pDiscoveryChangedBroadcast(true);
}.......
break;
}
}
}
~~~
當WPAS搜索到周圍的P2P Device后,將發送以下格式的消息給WifiMonitor。
~~~
P2P-DEVICE-FOUND fa : 7b : 7a : 42 : 02 : 13
p2p_dev_addr=fa:7b : 7a:42:02 : 13
pri_dev_type = 1 - 0050F204-1
name = 'p2p-TEST1'
config_methods=0x188
dev_capab=0x27
group_capab=0x0
~~~
WifiMonitor將根據這些信息構建一個WifiP2pDevice對象,然后發送P2P_DEVICE_FOUND_EVENT給P2pStateMachine。
**4、P2P_DEVICE_FOUND_EVENT處理流程**
同樣,P2P_DEVICE_FOUND_EVENT也由InactiveState的父狀態P2pEnabledState來處理,相關代碼如下所示。
**WifiP2pService.java::P2pEnabledState:processMessage**
~~~
class P2pEnabledState extends State{
public boolean processMessage(Message message) {
switch (message.what) {
......
case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
// WifiMonitor根據WPAS反饋的信息構建一個WifiP2pDevice對象
WifiP2pDevice device = (WifiP2pDevice) message.obj;
// 如果搜索到的這個P2P Device是自己(根據Device Address來判斷),則不處理它
if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
/*
mPeers指向一個WifiP2pDeviceList對象。如果之前已存儲了此Device的信息,
更新這些信息,否則將添加一個新的WifiP2pDevice對象。
*/
mPeers.update(device);
sendP2pPeersChangedBroadcast();// 發送WIFI_P2P_PEERS_CHANGED_ACTION廣播
break;
}......
}
}
~~~
WifiP2pSettings收到WIFI_P2P_PEERS_CHANGED_ACTION廣播后,將通過WifiP2pManager的requestPeers來獲得當前搜索到的P2P Device信息(即mPeers的內容)。這部分處理邏輯非常簡單,請讀者自行閱讀相關代碼。
現在,用戶將選擇一個P2P Device然后通過WifiP2pManager的connect函數向其發起連接。來看相關代碼。
**5、CONNECT處理流程**
WifiP2pManager的connect函數將發送CONNECT消息給P2pStateMachine,該消息由InactiveState狀態自己來處理,代碼如下所示。
**WifiP2pSettings.java::InactiveState:processMessage**
~~~
class InactiveState extends State {
......
public boolean processMessage(Message message) {
switch (message.what) {
case WifiP2pManager.CONNECT:
/*
WifiP2pSettings將設置一個WifiP2pConfig對象以告訴P2pStateMachine該連接
哪一個P2P Device(參考7.3.1節onPreferenceTreeClick介紹)
*/
WifiP2pConfig config = (WifiP2pConfig) message.obj;
mAutonomousGroup = false;
// 獲取該P2P Device的Group Capability信息
int gc = mWifiNative.getGroupCapability(config.deviceAddress);
mPeers.updateGroupCapability(config.deviceAddress, gc);
// 關鍵函數connect,見下文介紹
int connectRet = connect(config, TRY_REINVOCATION);
// TRY_REINVOCATION值為true
......
mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
sendP2pPeersChangedBroadcast();
replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
// 根據connectRet的值進行狀態切換選擇
if (connectRet == NEEDS_PROVISION_REQ) {
transitionTo(mProvisionDiscoveryState);// 轉入ProvisionDiscoveryState
break;
}
transitionTo(mGroupNegotiationState);// 或者轉入GroupNegotiationState
break;
......
}
return HANDLED
}
}
~~~
上述代碼中有一個關鍵函數,即connect,其代碼如下所示。
**WifiP2pService.java::connect**
~~~
private int connect(WifiP2pConfig config, boolean tryInvocation) {
......
// 當前還沒有保存的對端P2P Device配置信息(對應的數據類型為WifiP2pConfig)
// 所以isResp為false
boolean isResp = (mSavedPeerConfig != null &&
config.deviceAddress.equals(mSavedPeerConfig.deviceAddress));
mSavedPeerConfig = config;// 保存傳入的WifiP2pConfig信息
WifiP2pDevice dev = mPeers.get(config.deviceAddress);
......
// 判斷對端設備是否為GO。由于還沒有開展GON,所以join為false
boolean join = dev.isGroupOwner();
String ssid = mWifiNative.p2pGetSsid(dev.deviceAddress);
// 如果join為true,但對端設備不能再添加新的P2P Device,則join被設置為false
if (join && dev.isGroupLimit()) join = false;
else if (join) {// mGroups保存搜索到的GO信息,當前還沒有GO,所以netId為-1
int netId = mGroups.getNetworkId(dev.deviceAddress, ssid);
if (netId >= 0) {// 這種情況對應于加入一個當前已經存在的P2P Group
if (!mWifiNative.p2pGroupAdd(netId))
return CONNECT_FAILURE;
return CONNECT_SUCCESS;
}
}
if (!join && dev.isDeviceLimit()) return CONNECT_FAILURE;
// tryInvocation為true。P2P Device一般都支持Invitation
// 下面這個if代碼段處理Persistent Group的情況
if (!join && tryInvocation && dev.isInvitationCapable()) {
int netId = WifiP2pGroup.PERSISTENT_NET_ID;// PERSISTENT_NET_ID值為-2
if (config.netId >= 0) {
if (config.deviceAddress.equals(mGroups.getOwnerAddr(config.netId)))
netId = config.netId;
} else netId = mGroups.getNetworkId(dev.deviceAddress);
if (netId < 0) netId = getNetworkIdFromClientList(dev.deviceAddress);
if (netId >= 0) {// 通過Invitation Request重新啟動一個Persistent Group
if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) {
mSavedPeerConfig.netId = netId;
return CONNECT_SUCCESS;
} else updatePersistentNetworks(RELOAD);
}
}
mWifiNative.p2pStopFind();
if (!isResp) return NEEDS_PROVISION_REQ;// 就本例而言,connect返回NEEDS_PROVISION_REQ
p2pConnectWithPinDisplay(config);// 發起P2P連接,即啟動Group Formation流程
return CONNECT_SUCCESS;
}
~~~
就本例而言,connect將返回NEEDS_PROVISON_REQ,所以P2pStateMachine將轉入ProvisionDiscoveryState,馬上來看它的EA。
**WifiP2pService.java::ProvisionDiscoveryState:enter**
~~~
class ProvisionDiscoveryState extends State {
public void enter() {
// 觸發本機設備向對端設備發送Provision Discovery Request幀
mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig);
}
}
~~~
注意,由于WSC配置方法為PBC,所以對端設備的P2pStateMachine將收到一個P2P_PROV_DISC_PBC_REQ_EVENT消息。當對端設備處理完畢后,將收到一個P2P_PROV_DISC_PBC_RSP_EVENT消息。馬上來看P2P_PROV_DISC_PBC_RSP_EVENT消息
的處理流程。
**6、P2P_PROV_DISC_PBC_RSP_EVENT處理流程**
P2pStateMachine當前處于ProvisionDiscoveryState,相關處理邏輯如下所示。
**WifiP2pService.java::ProvisionDiscoveryState:processMessage**
~~~
public boolean processMessage(Message message) {
WifiP2pProvDiscEvent provDisc;
WifiP2pDevice device;
switch (message.what) {
case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:
provDisc = (WifiP2pProvDiscEvent) message.obj;
device = provDisc.device;
if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
/*
下面這個函數將調用WifiNative的p2pConnect函數,此函數將觸發WPAS發送
GON Request幀。接收端設備收到該幀后,將彈出圖7-16所示的提示框以提醒用戶。
*/
p2pConnectWithPinDisplay(mSavedPeerConfig);
// 轉入GroupNegotiationState,其EA比較簡單,請讀者自行閱讀
transitionTo(mGroupNegotiationState);
}
break;
......
}
}
~~~
上述代碼中,P2pStateMachine通過p2pConnectWithPinDisplay向對端發起Group Negotiation Request請求。接下來的工作就由WPAS來處理。當Group Formation結束后,P2pStateMachine將收到一個P2P_GROUP_STARTED_EVENT消息以通知Group建立完畢,該消息的處理流程如下節所述。
**7、P2P_GROUP_STARTED_EVENT處理流程**
P2P_GROUP_STARTED_EVENT消息由GroupNegotiationState處理,相關代碼如下所示。
**WifiP2pService.java::GroupNegotiationState:processMessage**
~~~
class GroupNegotiationState extends State {
......
public boolean processMessage(Message message) {
switch (message.what) {
case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
break;// 不處理Group Negotiation成功的消息
case WifiMonitor.P2P_GROUP_STARTED_EVENT:// 只處理Group Started消息
mGroup = (WifiP2pGroup) message.obj;
if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) {
updatePersistentNetworks(NO_RELOAD);
String devAddr = mGroup.getOwner().deviceAddress;
mGroup.setNetworkId(mGroups.getNetworkId(devAddr,
mGroup.getNetworkName()));
}
if (mGroup.isGroupOwner()) {// 如果本機P2P設備是GO,則啟動DhcpServer
// 假設本機P2P設備扮演GO,請讀者自行閱讀startDhcpServer函數
startDhcpServer(mGroup.getInterface());
} else {
/*
如果對端設備是GO,則啟動DhcpStateMachine用于獲取一個IP地址,這部分流程和
5.3.2節NETWORK_CONNECTION_EVENT消息處理流程分析的
ObtainingIpState工作流程類似。
*/
mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
P2pStateMachine.this, mGroup.getInterface());
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
WifiP2pDevice groupOwner = mGroup.getOwner();
groupOwner.update(mPeers.get(groupOwner.deviceAddress));
mPeers.updateStatus(groupOwner.deviceAddress,WifiP2pDevice.CONNECTED);
sendP2pPeersChangedBroadcast();
}
mSavedPeerConfig = null;
transitionTo(mGroupCreatedState);// 轉入GroupCreatedState
break;
......
}
}
~~~
P2pStateMachine將轉入GroupCreatedState,其EA代碼如下所示。
**WifiP2pService.java::GroupCreatedState:enter**
~~~
class GroupCreatedState extends State {
public void enter() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
updateThisDevice(WifiP2pDevice.CONNECTED);// 連接成功
if (mGroup.isGroupOwner()) {
/*
SERVER_ADDRESS為“192.168.49.1”,該地址也被設置到Dhcp Server中。
另外,P2pStateMachine有一個名為mWifiP2pInfo的成員變量,其類型為WifiP2pInfo,
下面這個函數也將GO的IP地址保存到mWifiP2pInfo中。
*/
setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
sendP2pConnectionChangedBroadcast();// 發送WIFI_P2P_CONNECTION_CHANGED_ACTION廣播
}
}
......
}
~~~
**8、AP_STA_CONNECTED_EVENT處理流程**
當對端P2P設備成功關聯到本機后,WifiMonitor又將發送一個名為AP_STA_CONNECTED_EVENT的消息,該消息的處理邏輯如下所示。
**WifiP2pService.java::GroupCreatedState:enter**
~~~
public boolean processMessage(Message message) {
switch (message.what) {
case WifiMonitor.AP_STA_CONNECTED_EVENT:// 該消息表示一個P2P Client關聯上本機GO
WifiP2pDevice device = (WifiP2pDevice) message.obj;
String deviceAddress = device.deviceAddress;
if (deviceAddress != null) {
......
mGroup.addClient(deviceAddress);// 添加一個P2P Client
mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
sendP2pPeersChangedBroadcast();
}
......
break;
......
}
}
~~~
至此,一個P2P Device(扮演Client)就成功關聯上本機的P2P Device(扮演GO)。
**9、WifiP2pService總結**
回顧上文介紹的WifiP2pService工作流程,可知P2pStateMachine初始狀態為P2pDisabledState,然后:
1. P2pStateMachine將接收到的第一條消息,它是來自WifiStateMachine的CMD_ENABLE_P2P。在該消息的處理邏輯中,P2pStateMachine將創建一個WifiMonitor對象以和wpa_supplicant進程交互。最后,P2pStateMachine轉入P2pEnablingState。
2. 在P2pEnablingState中,P2pStateMachine將處理SUP_CONNECT_EVENT消息,它代表WifiMonitor成功連接上了wpa_supplicant。該消息處理完畢后,P2pStateMachine將轉入InactiveState。
3. InactiveState的父狀態是P2pEnabledState,P2pEnabledState的EA將初始化P2P設置,這部分代碼邏輯在initializeP2pSettings函數中。另外,WifiP2pSettings將收到一些P2P廣播,此時P2P功能正常啟動。
4. 用戶在界面中進行操作以搜索周圍的設備,這使得P2pStateMachine將收到DISCVOER_PEERS消息。它在P2pEnabledState中被處理,wpas_supplicant將發起P2P Device Discovery流程以搜索周圍的P2P設備。
5. 一旦有P2P設備被搜索到,P2pStateMachine將接收到一條P2P_DEVICE_FOUND_EVENT消息。該消息依然由P2pEnabledState來處理。同時,WifiP2pSettings也會相應收到信息以更新UI。
6. 當用戶在WifiP2pSettings界面中選擇連接某個P2P Device后,WifiP2pSettings將發送CONNECT消息給P2pStateMachine。該消息由InactiveState來處理。大部分情況下(除了Persistent Group或者對端設備是GO的情況下),P2pStateMachine將轉入ProvisionDiscoveryState。
7. ProvisionDiscoveryState中,P2pStateMachine將通知WPAS以開展Provisioning Discovery流程。一切順利的話,P2pStateMachine將接收到P2P_PROV_DISC_PBC_RSP_EVENT消息。在該消息的處理過程中,P2pStateMachine將通過p2pConnectWithPinDisplay函數通知WPAS和對端設備啟動Group Formation流程。此后,P2pStateMachine轉入GroupNegotiationState。
8. Group Formation完成,一個Group也就創建成功,P2pStateMachine將收到P2P_GROUP_STARTED_EVENT消息。該消息由GroupNegotiationState處理。如果本機扮演GO的話,它將啟動一個Dhcp服務器,也就是第2章提到的dnsmasq(詳情請參考2.3.8節“背景知識介紹”)。
9. 當對端P2P Client(Group建立后,角色也就確定了)關聯上本機的GO后,AP_STA_CONNECTED_EVENT消息將被發送給P2pStateMachine處理。
如果仔細閱讀WifiP2pService代碼,會發現本節介紹的工作流程是WifiP2pService中最簡單的一條了。經過筆者實際測試,WifiP2pService有一個工作場景的處理流程比較復雜,即如果用戶在對端設備發起connect操作,則本機的處理相對要復雜一些。這部分流程和wpa_suppliant的處理也有關系,所以請讀者在學完本章的基礎上再自行研究它。現在,讓我們抖擻精神來分析P2P真正的主角wpa_supplicant。
[^①]: 注意,Android原生代碼中,P2P和STA功能是能同時啟用的,但有一些手機不支持concurrent operation,所以這些手機需要修改Wi-Fi相關的代碼。
- 前言
- 第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 參考資料說明
- 附錄