WifiP2pService工作流程
2015-04-07 17:27
447 查看
本文为《深入理解Android Wi-Fi、NFC和GPS卷》读书笔记,Android源码为Android 5.1
主要特点就是无底线的粘贴源码
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pService.java
P2pStateMachine此时处于 P2pDisabledState ,它对 CMD_ENABLE_P2P 消息的处理逻辑如下:
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
WiFiMonitor连接wpa_supplicant之后,WiFiMonitor会发送一个 SUP_CONNECTION_EVENT 给 P2pStateMachine。该消息将由 P2pEnablingState 处理:
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
首先来看WifiP2pSettings中WifiP2pManager的discoveryPeers函数,它将发送DISCOVERY_PEERS消息给P2pStateMachine。
P2pStateMachine当前处于InactiveState,不过 DISCOVER_PEERS 消息确实由其父状态P2pEnabledState来处理的,相关代码见上面"case WifiP2pManager.DISCOVER_PEERS:"
当WPAS搜索到周围的P2P Device后,将发送消息给WiFiMonitor,WiFiMonitor将根据这些信息构建一个WifiP2pDevice对象,然后发送 P2P_DEVICE_FOUND_EVENT 给 P2pStateMachine,P2P_DEVICE_FOUND_EVENT 也由InactiveState的父状态 P2pEnabledState来处理,相关代码见"case WifiMonitor.P2P_DEVICE_FOUND_EVENT:"
WifiP2pSettings收到 WIFI_P2P_PEERS_CHANGED_ACTION 广播后,将通过WifiP2pManager的requestPeers来获得当前搜索到的P2P Device信息(即mPeers的内容)。
现在用户将选择一个P2P Device然后通过 WifiP2pManager的connect函数向其发起连接,见下面的"case WifiP2pManager.CONNECT:":
P2pStateMachine通过 p2pConnectWithPinDisplay 向对端发起 Group Negotiation Request请求。接下来的工作就由WPAS来处理。当Group Formation结束后, P2pStateMachine将收到一个 P2P_GROUP_STARTED_EVENT 消息以通知 Group 建立完毕,详细代码见"case WifiMonitor.P2P_GROUP_STARTED_EVENT:"
P2pStateMachine将转入GroupCreatedState:
至此,一个P2P Device(扮演Client)就成功关联上本机的P2P Device(扮演GO)
主要特点就是无底线的粘贴源码
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pService.java
public WifiP2pService(Context context) { super(context); mImpl = new WifiP2pServiceImpl(context); }android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
public WifiP2pServiceImpl(Context context) { mContext = context; //STOPSHIP: get this from native side mInterface = "p2p0";//P2P使用的虚拟网络接口设备名为p2p0 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, ""); //判断系统是否支持WiFi-Direct功能 mP2pSupported = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_DIRECT); //获取PrimaryDeviceType,默认值是 10-0050F204-5 //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); HandlerThread wifiP2pThread = new HandlerThread("WifiP2pService"); wifiP2pThread.start(); mClientHandler = new ClientHandler(wifiP2pThread.getLooper()); //WifiP2pService主要工作也是由状态机来完成的,即下面的这个P2pStateMachine mP2pStateMachine = new P2pStateMachine(TAG, wifiP2pThread.getLooper(), mP2pSupported); mP2pStateMachine.start(); }P2pStateMachine 是 WifiP2pServiceImpl 定义的内部类,构造函数如下:
P2pStateMachine(String name, Looper looper, boolean p2pSupported) { super(name, looper); addState(mDefaultState);//为状态机添加状态,一共15个状态 addState(mP2pNotSupportedState, mDefaultState); addState(mP2pDisablingState, mDefaultState); addState(mP2pDisabledState, mDefaultState); addState(mP2pEnablingState, mDefaultState); addState(mP2pEnabledState, mDefaultState); addState(mInactiveState, mP2pEnabledState); addState(mGroupCreatingState, mP2pEnabledState); addState(mUserAuthorizingInviteRequestState, mGroupCreatingState); addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState); addState(mProvisionDiscoveryState, mGroupCreatingState); addState(mGroupNegotiationState, mGroupCreatingState); addState(mFrequencyConflictState, mGroupCreatingState); addState(mGroupCreatedState, mP2pEnabledState); addState(mUserAuthorizingJoinState, mGroupCreatedState); addState(mOngoingGroupRemovalState, mGroupCreatedState); if (p2pSupported) { setInitialState(mP2pDisabledState);//初始状态为P2pDisableState } else { setInitialState(mP2pNotSupportedState); } setLogRecSize(50); setLogOnlyTransitions(true); }在Android平台中,如果用户打开Wi-Fi功能,P2pStateMachine就会收到第一个消息 CMD_ENABLE_P2P。该消息是WiFiStateMachine进入DriverStartedState 后, 在其EA中借助 mWifiP2pChannel向P2pStateMachine发送的。
P2pStateMachine此时处于 P2pDisabledState ,它对 CMD_ENABLE_P2P 消息的处理逻辑如下:
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
class P2pDisabledState extends State { @Override public void enter() { if (DBG) logd(getName()); } @Override public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiStateMachine.CMD_ENABLE_P2P: try { mNwService.setInterfaceUp(mInterface); } catch (RemoteException re) { loge("Unable to change interface settings: " + re); } catch (IllegalStateException ie) { loge("Unable to change interface settings: " + ie); } //启动WifiMonitor,它将通过wpa_ctl连接上wpa_supplicant 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 处理:
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
class P2pEnablingState extends State { @Override public void enter() { if (DBG) logd(getName()); } @Override public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiMonitor.SUP_CONNECTION_EVENT: if (DBG) logd("P2p socket connection successful"); transitionTo(mInactiveState);//转入InactiveState break; case WifiMonitor.SUP_DISCONNECTION_EVENT: loge("P2p socket connection failed"); transitionTo(mP2pDisabledState); break; case WifiStateMachine.CMD_ENABLE_P2P: case WifiStateMachine.CMD_DISABLE_P2P_REQ: deferMessage(message); break; default: return NOT_HANDLED; } return HANDLED; } }当状态机转入InactiveState后,首先执行的是其负状态 P2pEnabledState 的EA,然后才是InactiveState自己的EA。由于 InactiveState的EA仅打印了一句日志输出,故此处仅介绍 P2pEnabledState 的EA:
android-5.1/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
class P2pEnabledState extends State { @Override public void enter() { if (DBG) logd(getName()); //发送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消息。 sendP2pConnectionChangedBroadcast(); initializeP2pSettings();//初始化P2P的一些设置 } @Override public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiMonitor.SUP_DISCONNECTION_EVENT: loge("Unexpected loss of p2p socket connection"); transitionTo(mP2pDisabledState); break; case WifiStateMachine.CMD_ENABLE_P2P: //Nothing to do break; case WifiStateMachine.CMD_DISABLE_P2P_REQ: if (mPeers.clear()) { sendPeersChangedBroadcast(); } if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast(); mWifiMonitor.stopMonitoring(); transitionTo(mP2pDisablingState); break; case WifiP2pManager.SET_DEVICE_NAME: { WifiP2pDevice d = (WifiP2pDevice) message.obj; if (d != null && setAndPersistDeviceName(d.deviceName)) { if (DBG) logd("set device name " + d.deviceName); replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED, WifiP2pManager.ERROR); } break; } case WifiP2pManager.SET_WFD_INFO: { WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj; if (d != null && setWfdInfo(d)) { replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, WifiP2pManager.ERROR); } break; } case BLOCK_DISCOVERY: boolean blocked = (message.arg1 == ENABLED ? true : false); if (mDiscoveryBlocked == blocked) break; mDiscoveryBlocked = blocked; if (blocked && mDiscoveryStarted) { mWifiNative.p2pStopFind(); mDiscoveryPostponed = true; } if (!blocked && mDiscoveryPostponed) { mDiscoveryPostponed = false; mWifiNative.p2pFind(DISCOVER_TIMEOUT_S); } if (blocked) { try { StateMachine m = (StateMachine)message.obj; m.sendMessage(message.arg2); } catch (Exception e) { loge("unable to send BLOCK_DISCOVERY response: " + e); } } break; case WifiP2pManager.DISCOVER_PEERS: if (mDiscoveryBlocked) { replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, WifiP2pManager.BUSY); break; } // do not send service discovery request while normal find operation. 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); } else { replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, WifiP2pManager.ERROR); } break; case WifiMonitor.P2P_FIND_STOPPED_EVENT: sendP2pDiscoveryChangedBroadcast(false); break; case WifiP2pManager.STOP_DISCOVERY: if (mWifiNative.p2pStopFind()) { replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, WifiP2pManager.ERROR); } break; case WifiP2pManager.DISCOVER_SERVICES: if (mDiscoveryBlocked) { replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, WifiP2pManager.BUSY); break; } if (DBG) logd(getName() + " discover services"); if (!updateSupplicantServiceRequest()) { replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, WifiP2pManager.NO_SERVICE_REQUESTS); break; } if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) { replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED, WifiP2pManager.ERROR); } break; 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.updateSupplicantDetails(device); sendPeersChangedBroadcast();//发送 WIFI_P2P_PEERS_CHANGED_ACTION 广播 break; case WifiMonitor.P2P_DEVICE_LOST_EVENT: device = (WifiP2pDevice) message.obj; // Gets current details for the one removed device = mPeers.remove(device.deviceAddress); if (device != null) { sendPeersChangedBroadcast(); } break; case WifiP2pManager.ADD_LOCAL_SERVICE: if (DBG) logd(getName() + " add service"); WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo)message.obj; if (addLocalService(message.replyTo, servInfo)) { replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED); } break; case WifiP2pManager.REMOVE_LOCAL_SERVICE: if (DBG) logd(getName() + " remove service"); servInfo = (WifiP2pServiceInfo)message.obj; removeLocalService(message.replyTo, servInfo); replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED); break; case WifiP2pManager.CLEAR_LOCAL_SERVICES: if (DBG) logd(getName() + " clear service"); clearLocalServices(message.replyTo); replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED); break; case WifiP2pManager.ADD_SERVICE_REQUEST: if (DBG) logd(getName() + " add service request"); if (!addServiceRequest(message.replyTo, (WifiP2pServiceRequest)message.obj)) { replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED); break; } replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED); break; case WifiP2pManager.REMOVE_SERVICE_REQUEST: if (DBG) logd(getName() + " remove service request"); removeServiceRequest(message.replyTo, (WifiP2pServiceRequest)message.obj); replyToMessage(message, WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED); break; case WifiP2pManager.CLEAR_SERVICE_REQUESTS: if (DBG) logd(getName() + " clear service request"); clearServiceRequests(message.replyTo); replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED); break; case WifiMonitor.P2P_SERV_DISC_RESP_EVENT: if (DBG) logd(getName() + " receive service response"); List<WifiP2pServiceResponse> sdRespList = (List<WifiP2pServiceResponse>) message.obj; for (WifiP2pServiceResponse resp : sdRespList) { WifiP2pDevice dev = mPeers.get(resp.getSrcDevice().deviceAddress); resp.setSrcDevice(dev); sendServiceResponse(resp); } break; case WifiP2pManager.DELETE_PERSISTENT_GROUP: if (DBG) logd(getName() + " delete persistent group"); mGroups.remove(message.arg1); replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED); break; case SET_MIRACAST_MODE: mWifiNative.setMiracastMode(message.arg1); break; case WifiP2pManager.START_LISTEN: if (DBG) logd(getName() + " start listen mode"); mWifiNative.p2pFlush(); if (mWifiNative.p2pExtListen(true, 500, 500)) { replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); } break; case WifiP2pManager.STOP_LISTEN: if (DBG) logd(getName() + " stop listen mode"); if (mWifiNative.p2pExtListen(false, 0, 0)) { replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); } mWifiNative.p2pFlush(); break; case WifiP2pManager.SET_CHANNEL: Bundle p2pChannels = (Bundle) message.obj; int lc = p2pChannels.getInt("lc", 0); int oc = p2pChannels.getInt("oc", 0); if (DBG) logd(getName() + " set listen and operating channel"); if (mWifiNative.p2pSetChannel(lc, oc)) { replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); } break; case SET_COUNTRY_CODE: String countryCode = (String) message.obj; countryCode = countryCode.toUpperCase(Locale.ROOT); if (mLastSetCountryCode == null || countryCode.equals(mLastSetCountryCode) == false) { if (mWifiNative.setCountryCode(countryCode)) { mLastSetCountryCode = countryCode; } } break; case WifiP2pManager.GET_HANDOVER_REQUEST: Bundle requestBundle = new Bundle(); requestBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, mWifiNative.getNfcHandoverRequest()); replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, requestBundle); break; case WifiP2pManager.GET_HANDOVER_SELECT: Bundle selectBundle = new Bundle(); selectBundle.putString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE, mWifiNative.getNfcHandoverSelect()); replyToMessage(message, WifiP2pManager.RESPONSE_GET_HANDOVER_MESSAGE, selectBundle); break; default: return NOT_HANDLED; } return HANDLED; } @Override public void exit() { sendP2pDiscoveryChangedBroadcast(false); sendP2pStateChangedBroadcast(false); mNetworkInfo.setIsAvailable(false); mLastSetCountryCode = null; } }
private void initializeP2pSettings() { //发送SET persistent_reconnect 1给WPAS,该命令对应如下一种应用场景 //当发现一个Persistent Group时,如果 persistent_reconnect 为1,则可利用之前保存的配置信息自动重连,重新连接时无需用户参与。如果 persistent_reconnect 为0,则需要提醒用户,让用户来决定是否加入此persistent group。 mWifiNative.setPersistentReconnect(true); //获取P2P设备名称,先从数据库中查询 wifi_p2p_device_name 字段的值,如果数据库中没有设置该字段,则取数据库中 android_id 字段值的前4个字符并在其前面加上 Android_ 字符串以组成P2P设备名。以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设备名保存到WPAS中 mWifiNative.setDeviceName(mThisDevice.deviceName); //设置P2P网络SSID的后缀。如果本设备能扮演GO,则它创建的Group对应的SSID后缀就是此处设置的后缀名 mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); //设置Primary DeviceType mWifiNative.setDeviceType(mThisDevice.primaryDeviceType); // Supplicant defaults to using virtual display with display // which refers to a remote display. Use physical_display //设置支持的WSC设置方法 mWifiNative.setConfigMethods("virtual_push_button physical_display keypad"); // STA has higher priority over P2P //设置STA连接的优先级高于P2P连接 mWifiNative.setConcurrencyPriority("sta"); //从WPAS获取P2P Device Address mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress(); //更新自己的状态,并发送 WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 消息 updateThisDevice(WifiP2pDevice.***AILABLE); if (DBG) logd("DeviceAddress: " + mThisDevice.deviceAddress); mClientInfoList.clear(); //清空WPAS中保存peer P2P Device和Service信息 mWifiNative.p2pFlush(); mWifiNative.p2pServiceFlush(); mServiceTransactionId = 0; mServiceDiscReqId = null; String countryCode = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.WIFI_COUNTRY_CODE); if (countryCode != null && !countryCode.isEmpty()) { mP2pStateMachine.sendMessage(SET_COUNTRY_CODE, countryCode); } //WPAS会保存 persistent Group 消息,而 P2pStateMachine 也会保存一些信息,下面这个函数将根据WPAS中的信息来更新P2pStateMachine 中保存的 Group 信息。 P2pStateMachine 通过一个名为 mGroups的成员变量(类型为WifiP2PGroupList)来保存所有的Group信息 updatePersistentNetworks(RELOAD); }至此P2pStateMachine就算初始化完毕,接下来的工作就是处理用户发起的操作。
首先来看WifiP2pSettings中WifiP2pManager的discoveryPeers函数,它将发送DISCOVERY_PEERS消息给P2pStateMachine。
P2pStateMachine当前处于InactiveState,不过 DISCOVER_PEERS 消息确实由其父状态P2pEnabledState来处理的,相关代码见上面"case WifiP2pManager.DISCOVER_PEERS:"
当WPAS搜索到周围的P2P Device后,将发送消息给WiFiMonitor,WiFiMonitor将根据这些信息构建一个WifiP2pDevice对象,然后发送 P2P_DEVICE_FOUND_EVENT 给 P2pStateMachine,P2P_DEVICE_FOUND_EVENT 也由InactiveState的父状态 P2pEnabledState来处理,相关代码见"case WifiMonitor.P2P_DEVICE_FOUND_EVENT:"
WifiP2pSettings收到 WIFI_P2P_PEERS_CHANGED_ACTION 广播后,将通过WifiP2pManager的requestPeers来获得当前搜索到的P2P Device信息(即mPeers的内容)。
现在用户将选择一个P2P Device然后通过 WifiP2pManager的connect函数向其发起连接,见下面的"case WifiP2pManager.CONNECT:":
class InactiveState extends State { @Override public void enter() { if (DBG) logd(getName()); mSavedPeerConfig.invalidate(); } @Override public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiP2pManager.CONNECT: if (DBG) logd(getName() + " sending connect"); //WifiP2pSettings将设置一个WifiP2pConfig对象以告诉 P2pStateMachine该连接哪一个 P2P Device WifiP2pConfig config = (WifiP2pConfig) message.obj; if (isConfigInvalid(config)) { loge("Dropping connect requeset " + config); replyToMessage(message, WifiP2pManager.CONNECT_FAILED); break; } mAutonomousGroup = false; mWifiNative.p2pStopFind(); if (reinvokePersistentGroup(config)) { transitionTo(mGroupNegotiationState); } else { transitionTo(mProvisionDiscoveryState); } mSavedPeerConfig = config; mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); sendPeersChangedBroadcast(); replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); break; case WifiP2pManager.STOP_DISCOVERY: if (mWifiNative.p2pStopFind()) { // When discovery stops in inactive state, flush to clear // state peer data mWifiNative.p2pFlush(); mServiceDiscReqId = null; replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, WifiP2pManager.ERROR); } break; case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: config = (WifiP2pConfig) message.obj; if (isConfigInvalid(config)) { loge("Dropping GO neg request " + config); break; } mSavedPeerConfig = config; mAutonomousGroup = false; mJoinExistingGroup = false; transitionTo(mUserAuthorizingNegotiationRequestState); break; case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT: WifiP2pGroup group = (WifiP2pGroup) message.obj; WifiP2pDevice owner = group.getOwner(); if (owner == null) { loge("Ignored invitation from null owner"); break; } config = new WifiP2pConfig(); config.deviceAddress = group.getOwner().deviceAddress; if (isConfigInvalid(config)) { loge("Dropping invitation request " + config); break; } mSavedPeerConfig = config; //Check if we have the owner in peer list and use appropriate //wps method. Default is to use PBC. if ((owner = mPeers.get(owner.deviceAddress)) != null) { if (owner.wpsPbcSupported()) { mSavedPeerConfig.wps.setup = WpsInfo.PBC; } else if (owner.wpsKeypadSupported()) { mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; } else if (owner.wpsDisplaySupported()) { mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; } } mAutonomousGroup = false; mJoinExistingGroup = true; transitionTo(mUserAuthorizingInviteRequestState); break; case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: //We let the supplicant handle the provision discovery response //and wait instead for the GO_NEGOTIATION_REQUEST_EVENT. //Handling provision discovery and issuing a p2p_connect before //group negotiation comes through causes issues break; case WifiP2pManager.CREATE_GROUP: mAutonomousGroup = true; int netId = message.arg1; boolean ret = false; if (netId == WifiP2pGroup.PERSISTENT_NET_ID) { // check if the go persistent group is present. netId = mGroups.getNetworkId(mThisDevice.deviceAddress); if (netId != -1) { ret = mWifiNative.p2pGroupAdd(netId); } else { ret = mWifiNative.p2pGroupAdd(true); } } else { ret = mWifiNative.p2pGroupAdd(false); } if (ret) { replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED); transitionTo(mGroupNegotiationState); } else { replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, WifiP2pManager.ERROR); // remain at this state. } break; case WifiMonitor.P2P_GROUP_STARTED_EVENT: mGroup = (WifiP2pGroup) message.obj; if (DBG) logd(getName() + " group started"); // We hit this scenario when a persistent group is reinvoked if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) { mAutonomousGroup = false; deferMessage(message); transitionTo(mGroupNegotiationState);//转入GroupCreatedState } else { loge("Unexpected group creation, remove " + mGroup); mWifiNative.p2pGroupRemove(mGroup.getInterface()); } break; case WifiP2pManager.START_LISTEN: if (DBG) logd(getName() + " start listen mode"); mWifiNative.p2pFlush(); if (mWifiNative.p2pExtListen(true, 500, 500)) { replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); } break; case WifiP2pManager.STOP_LISTEN: if (DBG) logd(getName() + " stop listen mode"); if (mWifiNative.p2pExtListen(false, 0, 0)) { replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); } mWifiNative.p2pFlush(); break; case WifiP2pManager.SET_CHANNEL: Bundle p2pChannels = (Bundle) message.obj; int lc = p2pChannels.getInt("lc", 0); int oc = p2pChannels.getInt("oc", 0); if (DBG) logd(getName() + " set listen and operating channel"); if (mWifiNative.p2pSetChannel(lc, oc)) { replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); } break; case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: String handoverSelect = null; if (message.obj != null) { handoverSelect = ((Bundle) message.obj) .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); } if (handoverSelect != null && mWifiNative.initiatorReportNfcHandover(handoverSelect)) { replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); transitionTo(mGroupCreatingState); } else { replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); } break; case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: String handoverRequest = null; if (message.obj != null) { handoverRequest = ((Bundle) message.obj) .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); } if (handoverRequest != null && mWifiNative.responderReportNfcHandover(handoverRequest)) { replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); transitionTo(mGroupCreatingState); } else { replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); } break; default: return NOT_HANDLED; } return HANDLED; } }
class ProvisionDiscoveryState extends State { @Override public void enter() { if (DBG) logd(getName()); //触发本机设备向对端设备发送 Provision Discovery Request帧 mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig); } @Override public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); 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) { if (DBG) logd("Found a match " + mSavedPeerConfig); //下面这个函数将调用WifiNative的P2pConnect函数,此函数将触发WPAS发送GON Request帧。接收端设备收到该帧后,将弹出提示框以提醒用户 p2pConnectWithPinDisplay(mSavedPeerConfig); //转入GroupNegotiationState transitionTo(mGroupNegotiationState); } break; case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: provDisc = (WifiP2pProvDiscEvent) message.obj; device = provDisc.device; if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break; if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) { if (DBG) logd("Found a match " + mSavedPeerConfig); /* we already have the pin */ if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) { p2pConnectWithPinDisplay(mSavedPeerConfig); transitionTo(mGroupNegotiationState); } else { mJoinExistingGroup = false; transitionTo(mUserAuthorizingNegotiationRequestState); } } break; case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: provDisc = (WifiP2pProvDiscEvent) message.obj; device = provDisc.device; if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break; if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) { if (DBG) logd("Found a match " + mSavedPeerConfig); mSavedPeerConfig.wps.pin = provDisc.pin; p2pConnectWithPinDisplay(mSavedPeerConfig); notifyInvitationSent(provDisc.pin, device.deviceAddress); transitionTo(mGroupNegotiationState); } break; case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT: loge("provision discovery failed"); handleGroupCreationFailure(); transitionTo(mInactiveState); break; default: return NOT_HANDLED; } return HANDLED; } }注意,由于WSC配置方法为PBC,所以对端设备的P2pStateMachine将收到一个P2P_PROV_DISC_PBC_REQ_EVENT 消息。当对端设备处理完毕后,将收到一个 P2P_PROV_DISC_PBC_RSP_EVENT消息。马上来看 P2P_PROV_DISC_PBC_RSP_EVENT 消息的处理流程,见上面代码中的"case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:"
P2pStateMachine通过 p2pConnectWithPinDisplay 向对端发起 Group Negotiation Request请求。接下来的工作就由WPAS来处理。当Group Formation结束后, P2pStateMachine将收到一个 P2P_GROUP_STARTED_EVENT 消息以通知 Group 建立完毕,详细代码见"case WifiMonitor.P2P_GROUP_STARTED_EVENT:"
P2pStateMachine将转入GroupCreatedState:
class GroupCreatedState extends State { @Override public void enter() { if (DBG) logd(getName()); // Once connected, peer config details are invalid mSavedPeerConfig.invalidate(); mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); updateThisDevice(WifiP2pDevice.CONNECTED);//连接成功 //DHCP server has already been started if I am a group owner if (mGroup.isGroupOwner()) { //SERVER_ADDRESS为192.168.49.1,该地址也被设置到Dhcp Server中 //另外,P2pStateMachine由一个名为mWifiP2pInfo的成员变量,其类型为 WifiP2pInfo, //下面这个函数也将GO的IP地址保存到mWifiP2pInfo中 setWifiP2pInfoOnGroupFormation(NetworkUtils.numericToInetAddress(SERVER_ADDRESS)); } // In case of a negotiation group, connection changed is sent // after a client joins. For autonomous, send now if (mAutonomousGroup) { sendP2pConnectionChangedBroadcast(); } } @Override public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiMonitor.AP_STA_CONNECTED_EVENT://该消息表示一个P2P Client关联上本机GO WifiP2pDevice device = (WifiP2pDevice) message.obj; String deviceAddress = device.deviceAddress; // Clear timeout that was set when group was started. mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0); if (deviceAddress != null) { if (mPeers.get(deviceAddress) != null) { mGroup.addClient(mPeers.get(deviceAddress));//添加一个P2P Client } else { mGroup.addClient(deviceAddress); } mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED); if (DBG) logd(getName() + " ap sta connected"); sendPeersChangedBroadcast(); } else { loge("Connect on null device address, ignore"); } sendP2pConnectionChangedBroadcast(); break; case WifiMonitor.AP_STA_DISCONNECTED_EVENT: device = (WifiP2pDevice) message.obj; deviceAddress = device.deviceAddress; if (deviceAddress != null) { mPeers.updateStatus(deviceAddress, WifiP2pDevice.***AILABLE); if (mGroup.removeClient(deviceAddress)) { if (DBG) logd("Removed client " + deviceAddress); if (!mAutonomousGroup && mGroup.isClientListEmpty()) { logd("Client list empty, remove non-persistent p2p group"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); // We end up sending connection changed broadcast // when this happens at exit() } else { // Notify when a client disconnects from group sendP2pConnectionChangedBroadcast(); } } else { if (DBG) logd("Failed to remove client " + deviceAddress); for (WifiP2pDevice c : mGroup.getClientList()) { if (DBG) logd("client " + c.deviceAddress); } } sendPeersChangedBroadcast(); if (DBG) logd(getName() + " ap sta disconnected"); } else { loge("Disconnect on unknown device: " + device); } break; case DhcpStateMachine.CMD_POST_DHCP_ACTION: DhcpResults dhcpResults = (DhcpResults) message.obj; if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS && dhcpResults != null) { if (DBG) logd("DhcpResults: " + dhcpResults); setWifiP2pInfoOnGroupFormation(dhcpResults.serverAddress); sendP2pConnectionChangedBroadcast(); //Turn on power save on client mWifiNative.setP2pPowerSave(mGroup.getInterface(), true); try { String iface = mGroup.getInterface(); mNwService.addInterfaceToLocalNetwork(iface, dhcpResults.getRoutes(iface)); } catch (RemoteException e) { loge("Failed to add iface to local network " + e); } } else { loge("DHCP failed"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); } break; case WifiP2pManager.REMOVE_GROUP: if (DBG) logd(getName() + " remove group"); if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { transitionTo(mOngoingGroupRemovalState); replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); } else { handleGroupRemoved(); transitionTo(mInactiveState); replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, WifiP2pManager.ERROR); } break; /* We do not listen to NETWORK_DISCONNECTION_EVENT for group removal * handling since supplicant actually tries to reconnect after a temporary * disconnect until group idle time out. Eventually, a group removal event * will come when group has been removed. * * When there are connectivity issues during temporary disconnect, the application * will also just remove the group. * * Treating network disconnection as group removal causes race conditions since * supplicant would still maintain the group at that stage. */ case WifiMonitor.P2P_GROUP_REMOVED_EVENT: if (DBG) logd(getName() + " group removed"); handleGroupRemoved(); transitionTo(mInactiveState); break; case WifiMonitor.P2P_DEVICE_LOST_EVENT: device = (WifiP2pDevice) message.obj; //Device loss for a connected device indicates it is not in discovery any more if (mGroup.contains(device)) { if (DBG) logd("Add device to lost list " + device); mPeersLostDuringConnection.updateSupplicantDetails(device); return HANDLED; } // Do the regular device lost handling return NOT_HANDLED; case WifiStateMachine.CMD_DISABLE_P2P_REQ: sendMessage(WifiP2pManager.REMOVE_GROUP); deferMessage(message); break; // This allows any client to join the GO during the // WPS window case WifiP2pManager.START_WPS: WpsInfo wps = (WpsInfo) message.obj; if (wps == null) { replyToMessage(message, WifiP2pManager.START_WPS_FAILED); break; } boolean ret = true; if (wps.setup == WpsInfo.PBC) { ret = mWifiNative.startWpsPbc(mGroup.getInterface(), null); } else { if (wps.pin == null) { String pin = mWifiNative.startWpsPinDisplay(mGroup.getInterface()); try { Integer.parseInt(pin); notifyInvitationSent(pin, "any"); } catch (NumberFormatException ignore) { ret = false; } } else { ret = mWifiNative.startWpsPinKeypad(mGroup.getInterface(), wps.pin); } } replyToMessage(message, ret ? WifiP2pManager.START_WPS_SUCCEEDED : WifiP2pManager.START_WPS_FAILED); break; case WifiP2pManager.CONNECT: WifiP2pConfig config = (WifiP2pConfig) message.obj; if (isConfigInvalid(config)) { loge("Dropping connect requeset " + config); replyToMessage(message, WifiP2pManager.CONNECT_FAILED); break; } logd("Inviting device : " + config.deviceAddress); mSavedPeerConfig = config; if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) { mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); sendPeersChangedBroadcast(); replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); } else { replyToMessage(message, WifiP2pManager.CONNECT_FAILED, WifiP2pManager.ERROR); } // TODO: figure out updating the status to declined when invitation is rejected break; case WifiMonitor.P2P_INVITATION_RESULT_EVENT: P2pStatus status = (P2pStatus)message.obj; if (status == P2pStatus.SUCCESS) { // invocation was succeeded. break; } loge("Invitation result " + status); if (status == P2pStatus.UNKNOWN_P2P_GROUP) { // target device has already removed the credential. // So, remove this credential accordingly. int netId = mGroup.getNetworkId(); if (netId >= 0) { if (DBG) logd("Remove unknown client from the list"); if (!removeClientFromList(netId, mSavedPeerConfig.deviceAddress, false)) { // not found the client on the list loge("Already removed the client, ignore"); break; } // try invitation. sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig); } } break; case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; mSavedPeerConfig = new WifiP2pConfig(); mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress; if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) { mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) { mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; mSavedPeerConfig.wps.pin = provDisc.pin; } else { mSavedPeerConfig.wps.setup = WpsInfo.PBC; } transitionTo(mUserAuthorizingJoinState); break; case WifiMonitor.P2P_GROUP_STARTED_EVENT: loge("Duplicate group creation event notice, ignore"); break; default: return NOT_HANDLED; } return HANDLED; } public void exit() { updateThisDevice(WifiP2pDevice.***AILABLE); resetWifiP2pInfo(); mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); sendP2pConnectionChangedBroadcast(); } }当对端P2P设备成功关联到本机后,WifiMonitor又将发送一个名为 AP_STA_CONNECTED_EVENT 的消息,见代码"case WifiMonitor.AP_STA_CONNECTED_EVENT:"
至此,一个P2P Device(扮演Client)就成功关联上本机的P2P Device(扮演GO)
相关文章推荐
- Android4.4 Wi-Fi P2P WifiP2pService中初始化流程
- WIFI工作流程
- android wifiservice enable流程
- Android Wifi的工作流程
- android wifi 工作流程
- Hadoop-2.4.1源码分析--HDFS HeartBeat(心跳检测)之BPServiceActor工作线程运行流程(下)
- HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程
- WifiP2pService的启动以及P2P的连接 -转载
- android wifi工作流程
- HDFS源码分析心跳汇报之BPServiceActor工作线程运行流程
- WifiP2pService的启动以及P2P的连接
- Android Wifi的工作流程
- Android WifiService的启动流程分析
- IntentService工作流程完全解析
- WifiP2pService的启动以及P2P的连接
- Android WifiService的启动流程分析
- 非常详细的android wifi工作流程
- Android Wifi的工作流程
- WIFI 介绍及其简单工作流程
- Android Wifi的工作流程