diff options
4 files changed, 287 insertions, 25 deletions
diff --git a/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java index 618f13b9b..0932363c8 100644 --- a/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java +++ b/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java @@ -36,13 +36,18 @@ import android.net.wifi.p2p.WifiP2pManager; import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; import android.os.HwRemoteBinder; import android.os.RemoteException; +import android.text.TextUtils; import android.util.Log; import com.android.internal.util.ArrayUtils; import com.android.server.wifi.util.NativeUtil; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Native calls sending requests to the P2P Hals, and callbacks for receiving P2P events @@ -54,6 +59,12 @@ public class SupplicantP2pIfaceHal { private static final String TAG = "SupplicantP2pIfaceHal"; private static final int RESULT_NOT_VALID = -1; private static final int DEFAULT_GROUP_OWNER_INTENT = 6; + /** + * Regex pattern for extracting the wps device type bytes. + * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; + */ + private static final Pattern WPS_DEVICE_TYPE_PATTERN = + Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$"); private Object mLock = new Object(); @@ -420,7 +431,7 @@ public class SupplicantP2pIfaceHal { /** * Initiate a P2P service discovery with a (optional) timeout. * - * @param timeoutInSec Max time to be spent is peforming discovery. + * @param timeout Max time to be spent is peforming discovery. * Set to 0 to indefinely continue discovery untill and explicit * |stopFind| is sent. * @return boolean value indicating whether operation was successful. @@ -444,10 +455,6 @@ public class SupplicantP2pIfaceHal { } } - public boolean find() { - return find(0); - } - /** * Stop an ongoing P2P service discovery. @@ -616,6 +623,7 @@ public class SupplicantP2pIfaceHal { * uses PIN. */ public String connect(WifiP2pConfig config, boolean joinExistingGroup) { + if (config == null) return null; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("setSsidPostfix")) return null; @@ -716,6 +724,7 @@ public class SupplicantP2pIfaceHal { * @return boolean value indicating whether operation was successful. */ public boolean provisionDiscovery(WifiP2pConfig config) { + if (config == null) return false; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("provisionDiscovery")) return false; @@ -759,13 +768,13 @@ public class SupplicantP2pIfaceHal { * the group owner device address for Invitation Request should it not be * known for some reason (this should not be needed in most cases). * - * @param groupIfName Group interface name to use. - * @param goDeviceAddress MAC address of the group owner device. + * @param group Group object to use. * @param peerAddress MAC address of the device to invite. * * @return boolean value indicating whether operation was successful. */ public boolean invite(WifiP2pGroup group, String peerAddress) { + if (TextUtils.isEmpty(peerAddress)) return false; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("invite")) return false; if (group == null) { @@ -892,7 +901,7 @@ public class SupplicantP2pIfaceHal { /** * Gets the operational SSID of the device. * - * @param peerAddress MAC address of the peer. + * @param address MAC address of the peer. * * @return SSID of the device. */ @@ -947,6 +956,7 @@ public class SupplicantP2pIfaceHal { * @return true, if operation was successful. */ public boolean reinvoke(int networkId, String peerAddress) { + if (TextUtils.isEmpty(peerAddress) || networkId < 0) return false; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("reinvoke")) return false; if (peerAddress == null) { @@ -1019,11 +1029,12 @@ public class SupplicantP2pIfaceHal { * the group, it must also be removed. The network interface name of the * group interface is used as a parameter for this command. * - * @param groupIfName Group interface name to use. + * @param groupName Group interface name to use. * * @return true, if operation was successful. */ public boolean groupRemove(String groupName) { + if (TextUtils.isEmpty(groupName)) return false; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("groupRemove")) return false; SupplicantResult<Void> result = new SupplicantResult("groupRemove(" + groupName + ")"); @@ -1101,6 +1112,9 @@ public class SupplicantP2pIfaceHal { * @return true, if operation was successful. */ public boolean configureExtListen(boolean enable, int periodInMillis, int intervalInMillis) { + if (enable && intervalInMillis < periodInMillis) { + return false; + } synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("configureExtListen")) return false; @@ -1174,8 +1188,7 @@ public class SupplicantP2pIfaceHal { /** * This command can be used to add a upnp/bonjour service. * - * @param query Hex dump of the query data. - * @param return Hex dump of the response data. + * @param servInfo List of service queries. * * @return true, if operation was successful. */ @@ -1251,7 +1264,7 @@ public class SupplicantP2pIfaceHal { /** * This command can be used to remove a upnp/bonjour service. * - * @param query Hex dump of the query data. + * @param servInfo List of service queries. * * @return true, if operation was successful. */ @@ -1459,6 +1472,7 @@ public class SupplicantP2pIfaceHal { * @return true, if operation was successful. */ public boolean startWpsPbc(String groupIfName, String bssid) { + if (TextUtils.isEmpty(groupIfName) || TextUtils.isEmpty(bssid)) return false; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("startWpsPbc")) return false; if (groupIfName == null) { @@ -1499,6 +1513,7 @@ public class SupplicantP2pIfaceHal { * @return true, if operation was successful. */ public boolean startWpsPinKeypad(String groupIfName, String pin) { + if (TextUtils.isEmpty(groupIfName) || TextUtils.isEmpty(pin)) return false; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("startWpsPinKeypad")) return false; if (groupIfName == null) { @@ -1532,6 +1547,7 @@ public class SupplicantP2pIfaceHal { * @return true, if operation was successful. */ public String startWpsPinDisplay(String groupIfName, String bssid) { + if (TextUtils.isEmpty(groupIfName) || TextUtils.isEmpty(bssid)) return null; synchronized (mLock) { if (!checkSupplicantP2pIfaceAndLogFailure("startWpsPinDisplay")) return null; if (groupIfName == null) { @@ -1657,6 +1673,29 @@ public class SupplicantP2pIfaceHal { } /** + * Remove network with provided id. + * + * @param networkId Id of the network to lookup. + * @return true, if operation was successful. + */ + public boolean removeNetwork(int networkId) { + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("removeNetwork")) return false; + + SupplicantResult<Void> result = new SupplicantResult( + "removeNetwork(" + networkId + ")"); + try { + result.setResult(mISupplicantP2pIface.removeNetwork(networkId)); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + + return result.isSuccess(); + } + } + + /** * List the networks saved in wpa_supplicant. * * @return List of network ids. @@ -1799,6 +1838,166 @@ public class SupplicantP2pIfaceHal { return true; } + /** + * Set WPS device name. + * + * @param name String to be set. + * @return true if request is sent successfully, false otherwise. + */ + public boolean setWpsDeviceName(String name) { + if (name == null) { + return false; + } + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("setWpsDeviceName")) return false; + SupplicantResult<Void> result = new SupplicantResult( + "setWpsDeviceName(" + name + ")"); + try { + result.setResult(mISupplicantP2pIface.setWpsDeviceName(name)); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + return result.isSuccess(); + } + } + + /** + * Set WPS device type. + * + * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> + * @return true if request is sent successfully, false otherwise. + */ + public boolean setWpsDeviceType(String typeStr) { + Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); + if (!match.find() || match.groupCount() != 3) { + Log.e(TAG, "Malformed WPS device type " + typeStr); + return false; + } + short categ = Short.parseShort(match.group(1)); + byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); + short subCateg = Short.parseShort(match.group(3)); + + byte[] bytes = new byte[8]; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); + byteBuffer.putShort(categ); + byteBuffer.put(oui); + byteBuffer.putShort(subCateg); + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("setWpsDeviceType")) return false; + SupplicantResult<Void> result = new SupplicantResult( + "setWpsDeviceType(" + typeStr + ")"); + try { + result.setResult(mISupplicantP2pIface.setWpsDeviceType(bytes)); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + return result.isSuccess(); + } + } + + /** + * Get NFC handover request message. + * + * @return select message if created successfully, null otherwise. + */ + public String getNfcHandoverRequest() { + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("getNfcHandoverRequest")) return null; + SupplicantResult<ArrayList> result = new SupplicantResult( + "getNfcHandoverRequest()"); + try { + mISupplicantP2pIface.createNfcHandoverRequestMessage( + (SupplicantStatus status, ArrayList<Byte> message) -> { + result.setResult(status, message); + }); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + if (!result.isSuccess()) { + return null; + + } + return NativeUtil.hexStringFromByteArray( + NativeUtil.byteArrayFromArrayList(result.getResult())); + } + } + + /** + * Get NFC handover select message. + * + * @return select message if created successfully, null otherwise. + */ + public String getNfcHandoverSelect() { + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("getNfcHandoverSelect")) return null; + SupplicantResult<ArrayList> result = new SupplicantResult( + "getNfcHandoverSelect()"); + try { + mISupplicantP2pIface.createNfcHandoverSelectMessage( + (SupplicantStatus status, ArrayList<Byte> message) -> { + result.setResult(status, message); + }); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + if (!result.isSuccess()) { + return null; + + } + return NativeUtil.hexStringFromByteArray( + NativeUtil.byteArrayFromArrayList(result.getResult())); + } + } + + /** + * Report NFC handover select message. + * + * @return true if reported successfully, false otherwise. + */ + public boolean initiatorReportNfcHandover(String selectMessage) { + if (selectMessage == null) return false; + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("initiatorReportNfcHandover")) return false; + SupplicantResult<Void> result = new SupplicantResult( + "initiatorReportNfcHandover(" + selectMessage + ")"); + try { + result.setResult(mISupplicantP2pIface.reportNfcHandoverInitiation( + NativeUtil.byteArrayToArrayList(NativeUtil.hexStringToByteArray( + selectMessage)))); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + return result.isSuccess(); + } + } + + /** + * Report NFC handover request message. + * + * @return true if reported successfully, false otherwise. + */ + public boolean responderReportNfcHandover(String requestMessage) { + if (requestMessage == null) return false; + synchronized (mLock) { + if (!checkSupplicantP2pIfaceAndLogFailure("responderReportNfcHandover")) return false; + SupplicantResult<Void> result = new SupplicantResult( + "responderReportNfcHandover(" + requestMessage + ")"); + try { + result.setResult(mISupplicantP2pIface.reportNfcHandoverResponse( + NativeUtil.byteArrayToArrayList(NativeUtil.hexStringToByteArray( + requestMessage)))); + } catch (RemoteException e) { + Log.e(TAG, "ISupplicantP2pIface exception: " + e); + supplicantServiceDiedHandler(); + } + return result.isSuccess(); + } + } /** Container class allowing propagation of status and/or value * from callbacks. * diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index fea8263b8..d84dd23e8 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -138,7 +138,7 @@ public class WifiNative { // TODO(b/34884202): Set this to true to enable HIDL once we're fully ready. private static final boolean HIDL_VENDOR_ENABLE = true; public static final boolean HIDL_SUP_ENABLE = true; - private static final boolean HIDL_P2P_ENABLE = false; + private static final boolean HIDL_P2P_ENABLE = true; private final String mTAG; private final String mInterfaceName; private final String mInterfacePrefix; @@ -1182,6 +1182,31 @@ public class WifiNative { } } + public boolean removeP2pNetwork(int netId) { + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.removeNetwork(netId); + } else { + return doBooleanCommand("REMOVE_NETWORK " + netId); + } + + } + + public boolean setP2pDeviceName(String name) { + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.setWpsDeviceName(name); + } else { + return doBooleanCommand("SET device_name " + name); + } + } + + public boolean setP2pDeviceType(String type) { + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.setWpsDeviceType(type); + } else { + return doBooleanCommand("SET device_type " + type); + } + } + public boolean setP2pSsidPostfix(String postfix) { if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { return mSupplicantP2pIfaceHal.setSsidPostfix(postfix); @@ -1695,25 +1720,64 @@ public class WifiNative { * NFC-related calls */ public String getNfcWpsConfigurationToken(int netId) { - return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId); + if (HIDL_SUP_ENABLE) { + return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken(); + } else { + return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId); + } } public String getNfcHandoverRequest() { - return doStringCommand("NFC_GET_HANDOVER_REQ NDEF P2P-CR"); + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.getNfcHandoverRequest(); + } else { + return doStringCommand("NFC_GET_HANDOVER_REQ NDEF P2P-CR"); + } } public String getNfcHandoverSelect() { - return doStringCommand("NFC_GET_HANDOVER_SEL NDEF P2P-CR"); + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.getNfcHandoverSelect(); + } else { + return doStringCommand("NFC_GET_HANDOVER_SEL NDEF P2P-CR"); + } } public boolean initiatorReportNfcHandover(String selectMessage) { - return doBooleanCommand("NFC_REPORT_HANDOVER INIT P2P 00 " + selectMessage); + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.initiatorReportNfcHandover(selectMessage); + } else { + return doBooleanCommand("NFC_REPORT_HANDOVER INIT P2P 00 " + selectMessage); + } } public boolean responderReportNfcHandover(String requestMessage) { - return doBooleanCommand("NFC_REPORT_HANDOVER RESP P2P " + requestMessage + " 00"); + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + return mSupplicantP2pIfaceHal.responderReportNfcHandover(requestMessage); + } else { + return doBooleanCommand("NFC_REPORT_HANDOVER RESP P2P " + requestMessage + " 00"); + } } + public String getP2pClientList(int netId) { + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + // TODO(b/36042785): Add HIDL method. + return null; + } else { + return getNetworkVariable(netId, "p2p_client_list"); + } + } + + public boolean setP2pClientList(int netId, String list) { + if (HIDL_P2P_ENABLE && mSupplicantP2pIfaceHal != null) { + // TODO(b/36042785): Add HIDL method. + return false; + } else { + return setNetworkVariable(netId, "p2p_client_list", list); + } + } + + /** WifiSupplicantControl methods. TODO: These should use HIDL soon. */ /** * Migrate all the configured networks from wpa_supplicant. diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java index bb8db39e6..58bce4a84 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java @@ -593,7 +593,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { @Override public void onDeleteGroup(int netId) { if (DBG) logd("called onDeleteGroup() netId=" + netId); - mWifiNative.removeNetwork(netId); + mWifiNative.removeP2pNetwork(netId); mWifiNative.saveConfig(); sendP2pPersistentGroupsChangedBroadcast(); } @@ -2711,7 +2711,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { * @return p2p client list. if not found, return null. */ private String[] getClientList(int netId) { - String p2pClients = mWifiNative.getNetworkVariable(netId, "p2p_client_list"); + String p2pClients = mWifiNative.getP2pClientList(netId); if (p2pClients == null) { return null; } @@ -2756,8 +2756,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (modifiedClientList.length() == 0) { modifiedClientList.append("\"\""); } - mWifiNative.setNetworkVariable(netId, - "p2p_client_list", modifiedClientList.toString()); + mWifiNative.setP2pClientList(netId, modifiedClientList.toString()); mWifiNative.saveConfig(); return true; } @@ -2837,10 +2836,10 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private void initializeP2pSettings() { mWifiNative.setPersistentReconnect(true); mThisDevice.deviceName = getPersistedDeviceName(); - mWifiNative.setDeviceName(mThisDevice.deviceName); + mWifiNative.setP2pDeviceName(mThisDevice.deviceName); // DIRECT-XY-DEVICENAME (XY is randomly generated) mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); - mWifiNative.setDeviceType(mThisDevice.primaryDeviceType); + mWifiNative.setP2pDeviceType(mThisDevice.primaryDeviceType); // Supplicant defaults to using virtual display with display // which refers to a remote display. Use physical_display mWifiNative.setConfigMethods("virtual_push_button physical_display keypad"); diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java index 665b47f7f..2ea492e60 100644 --- a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java @@ -305,7 +305,7 @@ public class SupplicantP2pIfaceHalTest { public void testFind_exception() throws Exception { executeAndValidateInitializationSequence(false, false, false); when(mISupplicantP2pIfaceMock.find(anyInt())).thenThrow(mRemoteException); - assertFalse(mDut.find()); + assertFalse(mDut.find(0)); // Check service is dead. assertFalse(mDut.isInitializationComplete()); } |