summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Wiszkowski <ender@google.com>2017-02-08 12:59:31 -0800
committerTomasz Wiszkowski <ender@google.com>2017-02-28 09:12:38 -0800
commitd3c761e72a5f89c81bd74889a9fec663adcc491e (patch)
tree75d76bc8409b58379b4c3bad8732842cd6155504
parent56a8ff2e077bdbcd1511ad48c05df99c4d8ae300 (diff)
HIDLization of WifiDirect, stage 3: callbacks.
Callback class crafted to be compatible with legacy code. Several calls currently generate no action (never used before). Change-Id: I1e1d94fd23dfb069cd387bc511c979ebeb2e72cf
-rw-r--r--service/java/com/android/server/wifi/SupplicantP2pIfaceCallback.java534
-rw-r--r--service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java26
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java2
-rw-r--r--service/java/com/android/server/wifi/WifiMonitor.java238
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceCallbackTest.java360
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java4
6 files changed, 1138 insertions, 26 deletions
diff --git a/service/java/com/android/server/wifi/SupplicantP2pIfaceCallback.java b/service/java/com/android/server/wifi/SupplicantP2pIfaceCallback.java
new file mode 100644
index 000000000..829d32e1e
--- /dev/null
+++ b/service/java/com/android/server/wifi/SupplicantP2pIfaceCallback.java
@@ -0,0 +1,534 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIface;
+import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback;
+import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
+import android.net.wifi.WpsInfo;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pProvDiscEvent;
+import android.net.wifi.p2p.WifiP2pWfdInfo;
+import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
+import android.util.Log;
+
+import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus;
+import com.android.server.wifi.util.NativeUtil;
+
+import libcore.util.HexEncoding;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SupplicantP2pIfaceCallback extends ISupplicantP2pIfaceCallback.Stub {
+ private static final String TAG = "SupplicantP2pIfaceCallback";
+ private static final boolean DBG = true;
+
+ private final String mInterface;
+ private final WifiMonitor mMonitor;
+
+ public SupplicantP2pIfaceCallback(String iface, WifiMonitor monitor) {
+ mInterface = iface;
+ mMonitor = monitor;
+ }
+
+
+ protected static void logd(String s) {
+ if (DBG) Log.d(TAG, s);
+ }
+
+ /**
+ * Used to indicate that a new network has been added.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ */
+ public void onNetworkAdded(int networkId) {
+ }
+
+
+ /**
+ * Used to indicate that a network has been removed.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ */
+ public void onNetworkRemoved(int networkId) {
+ }
+
+
+ /**
+ * Used to indicate that a P2P device has been found.
+ *
+ * @param srcAddress MAC address of the device found. This must either
+ * be the P2P device address or the P2P interface address.
+ * @param p2pDeviceAddress P2P device address.
+ * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
+ * Technical specification v1.2.
+ * @param deviceName Name of the device.
+ * @param configMethods Mask of WPS configuration methods supported by the
+ * device.
+ * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+ * specification v1.2.
+ * @param groupCapabilites Refer to section 4.1.4 of Wifi P2P Technical
+ * specification v1.2.
+ * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
+ * technical specification v1.0.0.
+ */
+ public void onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType,
+ String deviceName, short configMethods, byte deviceCapabilities, int groupCapabilities,
+ byte[] wfdDeviceInfo) {
+ WifiP2pDevice device = new WifiP2pDevice();
+ device.deviceName = deviceName;
+
+ if (deviceName == null) {
+ Log.e(TAG, "Missing device name.");
+ return;
+ }
+
+ try {
+ device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode device address.", e);
+ return;
+ }
+
+ try {
+ device.primaryDeviceType = new String(HexEncoding.encode(
+ primaryDeviceType, 0, primaryDeviceType.length));
+ } catch (Exception e) {
+ Log.e(TAG, "Could not encode device primary type.", e);
+ return;
+ }
+
+ device.deviceCapability = deviceCapabilities;
+ device.groupCapability = groupCapabilities;
+ device.wpsConfigMethodsSupported = configMethods;
+ device.status = WifiP2pDevice.AVAILABLE;
+
+ if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) {
+ device.wfdInfo = new WifiP2pWfdInfo(
+ (wfdDeviceInfo[0] << 8) + wfdDeviceInfo[1],
+ (wfdDeviceInfo[2] << 8) + wfdDeviceInfo[3],
+ (wfdDeviceInfo[4] << 8) + wfdDeviceInfo[5]);
+ }
+
+ logd("Device discovered on " + mInterface + ": " + device);
+ mMonitor.broadcastP2pDeviceFound(mInterface, device);
+ }
+
+
+ /**
+ * Used to indicate that a P2P device has been lost.
+ *
+ * @param p2pDeviceAddress P2P device address.
+ */
+ public void onDeviceLost(byte[] p2pDeviceAddress) {
+ WifiP2pDevice device = new WifiP2pDevice();
+
+ try {
+ device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode device address.", e);
+ return;
+ }
+
+ device.status = WifiP2pDevice.UNAVAILABLE;
+
+ logd("Device lost on " + mInterface + ": " + device);
+ mMonitor.broadcastP2pDeviceLost(mInterface, device);
+ }
+
+
+ /**
+ * Used to indicate the termination of P2P find operation.
+ */
+ public void onFindStopped() {
+ logd("Search stopped on " + mInterface);
+ mMonitor.broadcastP2pFindStopped(mInterface);
+ }
+
+
+ /**
+ * Used to indicate the reception of a P2P Group Owner negotiation request.
+ *
+ * @param srcAddress MAC address of the device that initiated the GO
+ * negotiation request.
+ * @param passwordId Type of password.
+ */
+ public void onGoNegotiationRequest(byte[] srcAddress, short passwordId) {
+ WifiP2pConfig config = new WifiP2pConfig();
+
+ try {
+ config.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode device address.", e);
+ return;
+ }
+
+ config.wps = new WpsInfo();
+
+ switch (passwordId) {
+ case WpsDevPasswordId.USER_SPECIFIED:
+ config.wps.setup = WpsInfo.DISPLAY;
+ break;
+
+ case WpsDevPasswordId.PUSHBUTTON:
+ config.wps.setup = WpsInfo.PBC;
+ break;
+
+ case WpsDevPasswordId.REGISTRAR_SPECIFIED:
+ config.wps.setup = WpsInfo.KEYPAD;
+ break;
+
+ default:
+ config.wps.setup = WpsInfo.PBC;
+ break;
+ }
+
+ logd("Group Owner negotiation initiated on " + mInterface + ": " + config);
+ mMonitor.broadcastP2pGoNegotiationRequest(mInterface, config);
+ }
+
+
+ /**
+ * Used to indicate the completion of a P2P Group Owner negotiation request.
+ *
+ * @param status Status of the GO negotiation.
+ */
+ public void onGoNegotiationCompleted(int status) {
+ logd("Group Owner negotiation completed with status: " + status);
+ P2pStatus result = halStatusToP2pStatus(status);
+
+ if (result == P2pStatus.SUCCESS) {
+ mMonitor.broadcastP2pGoNegotiationSuccess(mInterface);
+ } else {
+ mMonitor.broadcastP2pGoNegotiationFailure(mInterface, result);
+ }
+ }
+
+
+ /**
+ * Used to indicate a successful formation of a P2P group.
+ */
+ public void onGroupFormationSuccess() {
+ logd("Group formation successful on " + mInterface);
+ mMonitor.broadcastP2pGroupFormationSuccess(mInterface);
+ }
+
+
+ /**
+ * Used to indicate a failure to form a P2P group.
+ *
+ * @param failureReason Failure reason string for debug purposes.
+ */
+ public void onGroupFormationFailure(String failureReason) {
+ // TODO(ender): failureReason should probably be an int (P2pStatusCode).
+ logd("Group formation failed on " + mInterface + ": " + failureReason);
+ mMonitor.broadcastP2pGroupFormationFailure(mInterface, failureReason);
+ }
+
+
+ /**
+ * Used to indicate the start of a P2P group.
+ *
+ * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
+ * @param isGo Whether this device is owner of the group.
+ * @param ssid SSID of the group.
+ * @param frequency Frequency on which this group is created.
+ * @param psk PSK used to secure the group.
+ * @param passphrase PSK passphrase used to secure the group.
+ * @param goDeviceAddress MAC Address of the owner of this group.
+ * @param isPersistent Whether this group is persisted or not.
+ */
+ public void onGroupStarted(String groupIfName, boolean isGo, ArrayList<Byte> ssid,
+ int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress,
+ boolean isPersistent) {
+ if (groupIfName == null) {
+ Log.e(TAG, "Missing group interface name.");
+ return;
+ }
+
+ logd("Group " + groupIfName + " started on " + mInterface);
+
+ WifiP2pGroup group = new WifiP2pGroup();
+ group.setInterface(groupIfName);
+
+ try {
+ group.setNetworkName(NativeUtil.encodeSsid(ssid));
+ } catch (Exception e) {
+ Log.e(TAG, "Could not encode SSID.", e);
+ return;
+ }
+
+ group.setIsGroupOwner(isGo);
+ group.setPassphrase(passphrase);
+
+ if (isPersistent) {
+ group.setNetworkId(WifiP2pGroup.PERSISTENT_NET_ID);
+ } else {
+ group.setNetworkId(WifiP2pGroup.TEMPORARY_NET_ID);
+ }
+
+ WifiP2pDevice owner = new WifiP2pDevice();
+
+ try {
+ owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode Group Owner address.", e);
+ return;
+ }
+
+ group.setOwner(owner);
+ mMonitor.broadcastP2pGroupStarted(mInterface, group);
+ }
+
+
+ /**
+ * Used to indicate the removal of a P2P group.
+ *
+ * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
+ * @param isGo Whether this device is owner of the group.
+ */
+ public void onGroupRemoved(String groupIfName, boolean isGo) {
+ if (groupIfName == null) {
+ Log.e(TAG, "Missing group name.");
+ return;
+ }
+
+ logd("Group " + groupIfName + " removed from " + mInterface);
+ WifiP2pGroup group = new WifiP2pGroup();
+ group.setInterface(groupIfName);
+ group.setIsGroupOwner(isGo);
+ mMonitor.broadcastP2pGroupRemoved(mInterface, group);
+ }
+
+
+ /**
+ * Used to indicate the reception of a P2P invitation.
+ *
+ * @param srcAddress MAC address of the device that sent the invitation.
+ * @param goDeviceAddress MAC Address of the owner of this group.
+ * @param Bssid Bssid of the group.
+ * @param persistentNetworkId Persistent network Id of the group.
+ * @param operatingFrequency Frequency on which the invitation was received.
+ */
+ public void onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress,
+ byte[] bssid, int persistentNetworkId, int operatingFrequency) {
+ WifiP2pGroup group = new WifiP2pGroup();
+ group.setNetworkId(persistentNetworkId);
+
+ WifiP2pDevice client = new WifiP2pDevice();
+
+ try {
+ client.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode MAC address.", e);
+ return;
+ }
+
+ group.addClient(client);
+
+ WifiP2pDevice owner = new WifiP2pDevice();
+
+ try {
+ owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode Group Owner MAC address.", e);
+ return;
+ }
+
+ group.setOwner(owner);
+
+ logd("Invitation received on " + mInterface + ": " + group);
+ mMonitor.broadcastP2pInvitationReceived(mInterface, group);
+ }
+
+
+ /**
+ * Used to indicate the result of the P2P invitation request.
+ *
+ * @param Bssid Bssid of the group.
+ * @param status Status of the invitation.
+ */
+ public void onInvitationResult(byte[] bssid, int status) {
+ logd("Invitation completed with status: " + status);
+ mMonitor.broadcastP2pInvitationResult(mInterface, halStatusToP2pStatus(status));
+ }
+
+
+ /**
+ * Used to indicate the completion of a P2P provision discovery request.
+ *
+ * @param p2pDeviceAddress P2P device address.
+ * @param isRequest Whether we received or sent the provision discovery.
+ * @param status Status of the provision discovery (SupplicantStatusCode).
+ * @param configMethods Mask of WPS configuration methods supported.
+ * Only one configMethod bit should be set per call.
+ * @param generatedPin 8 digit pin generated.
+ */
+ public void onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest,
+ byte status, short configMethods, String generatedPin) {
+ if (status != 0) {
+ Log.e(TAG, "Provision discovery failed: " + status);
+ mMonitor.broadcastP2pProvisionDiscoveryFailure(mInterface);
+ return;
+ }
+
+ logd("Provision discovery " + (isRequest ? "request" : "response") +
+ " for WPS Config method: " + configMethods);
+
+ WifiP2pProvDiscEvent event = new WifiP2pProvDiscEvent();
+ event.device = new WifiP2pDevice();
+
+ try {
+ event.device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not decode MAC address.", e);
+ return;
+ }
+
+ if ((configMethods & ISupplicantP2pIface.WpsProvisionMethod.PBC) != 0) {
+ if (isRequest) {
+ event.event = WifiP2pProvDiscEvent.PBC_REQ;
+ mMonitor.broadcastP2pProvisionDiscoveryPbcRequest(mInterface, event);
+ } else {
+ event.event = WifiP2pProvDiscEvent.PBC_RSP;
+ mMonitor.broadcastP2pProvisionDiscoveryPbcResponse(mInterface, event);
+ }
+ } else if ((configMethods & ISupplicantP2pIface.WpsProvisionMethod.DISPLAY) != 0) {
+ event.event = WifiP2pProvDiscEvent.SHOW_PIN;
+ event.pin = generatedPin;
+ mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event);
+ } else if ((configMethods & ISupplicantP2pIface.WpsProvisionMethod.KEYPAD) != 0) {
+ event.event = WifiP2pProvDiscEvent.ENTER_PIN;
+ mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event);
+ } else {
+ Log.e(TAG, "Unsupported config methods: " + configMethods);
+ }
+ }
+
+
+ /**
+ * Used to indicate the reception of a P2P service discovery response.
+ *
+ * @param srcAddress MAC address of the device that sent the service discovery.
+ * @param updateIndicator Service update indicator. Refer to section 3.1.3 of
+ * Wifi P2P Technical specification v1.2.
+ * @param tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2.
+ */
+ public void onServiceDiscoveryResponse(byte[] srcAddress, short updateIndicator,
+ ArrayList<Byte> tlvs) {
+ List<WifiP2pServiceResponse> response = null;
+
+ logd("Service discovery response received on " + mInterface);
+ try {
+ StringBuilder event = new StringBuilder();
+ event.append(NativeUtil.macAddressFromByteArray(srcAddress));
+ event.append(" ");
+ event.append(updateIndicator);
+ event.append(" ");
+ event.append(NativeUtil.stringFromByteArrayList(tlvs));
+ response = WifiP2pServiceResponse.newInstance(event.toString());
+ } catch (Exception e) {
+ Log.e(TAG, "Could not process service discovery response.", e);
+ return;
+ }
+
+ mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response);
+ }
+
+
+ /**
+ * Used to indicate when a STA device is connected to this device.
+ *
+ * @param srcAddress MAC address of the device that was authorized.
+ * @param p2pDeviceAddress P2P device address.
+ */
+ public void onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress) {
+ logd("STA authorized on " + mInterface);
+ }
+
+
+ /**
+ * Used to indicate when a STA device is disconnected from this device.
+ *
+ * @param srcAddress MAC address of the device that was deauthorized.
+ * @param p2pDeviceAddress P2P device address.
+ */
+ public void onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress) {
+ logd("STA deauthorized on " + mInterface);
+ }
+
+
+ private static P2pStatus halStatusToP2pStatus(int status) {
+ P2pStatus result = P2pStatus.UNKNOWN;
+
+ switch (status) {
+ case P2pStatusCode.SUCCESS:
+ case P2pStatusCode.SUCCESS_DEFERRED:
+ result = P2pStatus.SUCCESS;
+ break;
+
+ case P2pStatusCode.FAIL_INFO_CURRENTLY_UNAVAILABLE:
+ result = P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE;
+ break;
+
+ case P2pStatusCode.FAIL_INCOMPATIBLE_PARAMS:
+ result = P2pStatus.INCOMPATIBLE_PARAMETERS;
+ break;
+
+ case P2pStatusCode.FAIL_LIMIT_REACHED:
+ result = P2pStatus.LIMIT_REACHED;
+ break;
+
+ case P2pStatusCode.FAIL_INVALID_PARAMS:
+ result = P2pStatus.INVALID_PARAMETER;
+ break;
+
+ case P2pStatusCode.FAIL_UNABLE_TO_ACCOMMODATE:
+ result = P2pStatus.UNABLE_TO_ACCOMMODATE_REQUEST;
+ break;
+
+ case P2pStatusCode.FAIL_PREV_PROTOCOL_ERROR:
+ result = P2pStatus.PREVIOUS_PROTOCOL_ERROR;
+ break;
+
+ case P2pStatusCode.FAIL_NO_COMMON_CHANNELS:
+ result = P2pStatus.NO_COMMON_CHANNEL;
+ break;
+
+ case P2pStatusCode.FAIL_UNKNOWN_GROUP:
+ result = P2pStatus.UNKNOWN_P2P_GROUP;
+ break;
+
+ case P2pStatusCode.FAIL_BOTH_GO_INTENT_15:
+ result = P2pStatus.BOTH_GO_INTENT_15;
+ break;
+
+ case P2pStatusCode.FAIL_INCOMPATIBLE_PROV_METHOD:
+ result = P2pStatus.INCOMPATIBLE_PROVISIONING_METHOD;
+ break;
+
+ case P2pStatusCode.FAIL_REJECTED_BY_USER:
+ result = P2pStatus.REJECTED_BY_USER;
+ break;
+ };
+ return result;
+ }
+}
+
diff --git a/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java
index cb6e2689b..7b96dc4c4 100644
--- a/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java
@@ -75,6 +75,13 @@ public class SupplicantP2pIfaceHal {
private Object mLock = new Object();
private boolean mServiceCallbackInstalled = false;
+ private final WifiMonitor mMonitor;
+ private SupplicantP2pIfaceCallback mCallback = null;
+
+ public SupplicantP2pIfaceHal(WifiMonitor monitor) {
+ mMonitor = monitor;
+ }
+
/**
* Registers a service notification for the ISupplicant service, which triggers intialization of
* the ISupplicantP2pIface
@@ -118,12 +125,16 @@ public class SupplicantP2pIfaceHal {
mIServiceManager = null; // Will need to register a new ServiceNotification
return false;
}
+
+ // Successful completion by the end of the 'try' block. This will prevent reporting
+ // proper initialization after exception is caught.
+ return true;
} catch (RemoteException e) {
Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: "
+ e);
supplicantServiceDiedHandler();
}
- return true;
+ return false;
}
}
@@ -190,9 +201,20 @@ public class SupplicantP2pIfaceHal {
return false;
}
mISupplicantP2pIface = getP2pIfaceMockable(supplicantIface.getResult());
+ }
- return true;
+ if (mISupplicantP2pIface != null && mMonitor != null) {
+ // TODO(ender): Get rid of hard-coded interface name, which is
+ // assumed to be the group interface name in several other classes
+ // ("p2p0" should probably become getName()).
+ mCallback = new SupplicantP2pIfaceCallback("p2p0", mMonitor);
+ if (!registerCallback(mCallback)) {
+ Log.e(TAG, "Callback registration failed. Initialization incomplete.");
+ return false;
+ }
}
+
+ return true;
}
private void supplicantServiceDiedHandler() {
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 1e5f6fc49..0b4200de9 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -161,7 +161,7 @@ public class WifiInjector {
mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mWifiStateMachineHandlerThread);
mSupplicantStaIfaceHal = new SupplicantStaIfaceHal(mContext, WifiMonitor.getInstance());
mWificondControl = new WificondControl(this, WifiMonitor.getInstance());
- mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal();
+ mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(WifiMonitor.getInstance());
mWifiNative = WifiNative.getWlanNativeInterface();
mWifiNative.setSupplicantStaIfaceHal(mSupplicantStaIfaceHal);
mWifiNative.setSupplicantP2pIfaceHal(mSupplicantP2pIfaceHal);
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index bc715413c..35098ec68 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -1161,47 +1161,43 @@ public class WifiMonitor {
*/
private void handleP2pEvents(String dataString, String iface) {
if (dataString.startsWith(P2P_DEVICE_FOUND_STR)) {
- WifiP2pDevice device = getWifiP2pDevice(dataString);
- if (device != null) sendMessage(iface, P2P_DEVICE_FOUND_EVENT, device);
+ broadcastP2pDeviceFound(iface, getWifiP2pDevice(dataString));
} else if (dataString.startsWith(P2P_DEVICE_LOST_STR)) {
- WifiP2pDevice device = getWifiP2pDevice(dataString);
- if (device != null) sendMessage(iface, P2P_DEVICE_LOST_EVENT, device);
+ broadcastP2pDeviceLost(iface, getWifiP2pDevice(dataString));
} else if (dataString.startsWith(P2P_FIND_STOPPED_STR)) {
- sendMessage(iface, P2P_FIND_STOPPED_EVENT);
+ broadcastP2pFindStopped(iface);
} else if (dataString.startsWith(P2P_GO_NEG_REQUEST_STR)) {
- sendMessage(iface, P2P_GO_NEGOTIATION_REQUEST_EVENT, new WifiP2pConfig(dataString));
+ broadcastP2pGoNegotiationRequest(iface, new WifiP2pConfig(dataString));
} else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) {
- sendMessage(iface, P2P_GO_NEGOTIATION_SUCCESS_EVENT);
+ broadcastP2pGoNegotiationSuccess(iface);
} else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) {
- sendMessage(iface, P2P_GO_NEGOTIATION_FAILURE_EVENT, p2pError(dataString));
+ broadcastP2pGoNegotiationFailure(iface, p2pError(dataString));
} else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) {
- sendMessage(iface, P2P_GROUP_FORMATION_SUCCESS_EVENT);
+ broadcastP2pGroupFormationSuccess(iface);
} else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) {
- sendMessage(iface, P2P_GROUP_FORMATION_FAILURE_EVENT, p2pError(dataString));
+ broadcastP2pGroupFormationFailure(iface, dataString);
} else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) {
- WifiP2pGroup group = getWifiP2pGroup(dataString);
- if (group != null) sendMessage(iface, P2P_GROUP_STARTED_EVENT, group);
+ broadcastP2pGroupStarted(iface, getWifiP2pGroup(dataString));
} else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) {
- WifiP2pGroup group = getWifiP2pGroup(dataString);
- if (group != null) sendMessage(iface, P2P_GROUP_REMOVED_EVENT, group);
+ broadcastP2pGroupRemoved(iface, getWifiP2pGroup(dataString));
} else if (dataString.startsWith(P2P_INVITATION_RECEIVED_STR)) {
- sendMessage(iface, P2P_INVITATION_RECEIVED_EVENT, new WifiP2pGroup(dataString));
+ broadcastP2pInvitationReceived(iface, new WifiP2pGroup(dataString));
} else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) {
- sendMessage(iface, P2P_INVITATION_RESULT_EVENT, p2pError(dataString));
+ broadcastP2pInvitationResult(iface, p2pError(dataString));
} else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) {
- sendMessage(iface, P2P_PROV_DISC_PBC_REQ_EVENT, new WifiP2pProvDiscEvent(dataString));
+ broadcastP2pProvisionDiscoveryPbcRequest(iface, new WifiP2pProvDiscEvent(dataString));
} else if (dataString.startsWith(P2P_PROV_DISC_PBC_RSP_STR)) {
- sendMessage(iface, P2P_PROV_DISC_PBC_RSP_EVENT, new WifiP2pProvDiscEvent(dataString));
+ broadcastP2pProvisionDiscoveryPbcResponse(iface, new WifiP2pProvDiscEvent(dataString));
} else if (dataString.startsWith(P2P_PROV_DISC_ENTER_PIN_STR)) {
- sendMessage(iface, P2P_PROV_DISC_ENTER_PIN_EVENT, new WifiP2pProvDiscEvent(dataString));
+ broadcastP2pProvisionDiscoveryEnterPin(iface, new WifiP2pProvDiscEvent(dataString));
} else if (dataString.startsWith(P2P_PROV_DISC_SHOW_PIN_STR)) {
- sendMessage(iface, P2P_PROV_DISC_SHOW_PIN_EVENT, new WifiP2pProvDiscEvent(dataString));
+ broadcastP2pProvisionDiscoveryShowPin(iface, new WifiP2pProvDiscEvent(dataString));
} else if (dataString.startsWith(P2P_PROV_DISC_FAILURE_STR)) {
- sendMessage(iface, P2P_PROV_DISC_FAILURE_EVENT);
+ broadcastP2pProvisionDiscoveryFailure(iface);
} else if (dataString.startsWith(P2P_SERV_DISC_RESP_STR)) {
List<WifiP2pServiceResponse> list = WifiP2pServiceResponse.newInstance(dataString);
if (list != null) {
- sendMessage(iface, P2P_SERV_DISC_RESP_EVENT, list);
+ broadcastP2pServiceDiscoveryResponse(iface, list);
} else {
Log.e(TAG, "Null service resp " + dataString);
}
@@ -1738,4 +1734,202 @@ public class WifiMonitor {
public void broadcastSupplicantDisconnectionEvent(String iface) {
sendMessage(iface, SUP_DISCONNECTION_EVENT);
}
+
+ /**
+ * Broadcast new p2p device discovered event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param device Device that has been discovered during recent scan.
+ */
+ public void broadcastP2pDeviceFound(String iface, WifiP2pDevice device) {
+ if (device != null) {
+ sendMessage(iface, P2P_DEVICE_FOUND_EVENT, device);
+ }
+ }
+
+ /**
+ * Broadcast p2p device lost event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param device Device that has been lost in recent scan.
+ */
+ public void broadcastP2pDeviceLost(String iface, WifiP2pDevice device) {
+ if (device != null) {
+ sendMessage(iface, P2P_DEVICE_LOST_EVENT, device);
+ }
+ }
+
+ /**
+ * Broadcast scan termination event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ */
+ public void broadcastP2pFindStopped(String iface) {
+ sendMessage(iface, P2P_FIND_STOPPED_EVENT);
+ }
+
+ /**
+ * Broadcast group owner negotiation request event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param config P2p configuration.
+ */
+ public void broadcastP2pGoNegotiationRequest(String iface, WifiP2pConfig config) {
+ if (config != null) {
+ sendMessage(iface, P2P_GO_NEGOTIATION_REQUEST_EVENT, config);
+ }
+ }
+
+ /**
+ * Broadcast group owner negotiation success event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ */
+ public void broadcastP2pGoNegotiationSuccess(String iface) {
+ sendMessage(iface, P2P_GO_NEGOTIATION_SUCCESS_EVENT);
+ }
+
+ /**
+ * Broadcast group owner negotiation failure event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param reason Failure reason.
+ */
+ public void broadcastP2pGoNegotiationFailure(String iface, P2pStatus reason) {
+ sendMessage(iface, P2P_GO_NEGOTIATION_FAILURE_EVENT, reason);
+ }
+
+ /**
+ * Broadcast group formation success event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ */
+ public void broadcastP2pGroupFormationSuccess(String iface) {
+ sendMessage(iface, P2P_GROUP_FORMATION_SUCCESS_EVENT);
+ }
+
+ /**
+ * Broadcast group formation failure event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param reason Failure reason.
+ */
+ public void broadcastP2pGroupFormationFailure(String iface, String reason) {
+ sendMessage(iface, P2P_GROUP_FORMATION_FAILURE_EVENT, p2pError(reason));
+ }
+
+ /**
+ * Broadcast group started event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param group Started group.
+ */
+ public void broadcastP2pGroupStarted(String iface, WifiP2pGroup group) {
+ if (group != null) {
+ sendMessage(iface, P2P_GROUP_STARTED_EVENT, group);
+ }
+ }
+
+ /**
+ * Broadcast group removed event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param group Removed group.
+ */
+ public void broadcastP2pGroupRemoved(String iface, WifiP2pGroup group) {
+ if (group != null) {
+ sendMessage(iface, P2P_GROUP_REMOVED_EVENT, group);
+ }
+ }
+
+ /**
+ * Broadcast invitation received event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param group Group to which invitation has been received.
+ */
+ public void broadcastP2pInvitationReceived(String iface, WifiP2pGroup group) {
+ if (group != null) {
+ sendMessage(iface, P2P_INVITATION_RECEIVED_EVENT, group);
+ }
+ }
+
+ /**
+ * Broadcast invitation result event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param result Result of invitation.
+ */
+ public void broadcastP2pInvitationResult(String iface, P2pStatus result) {
+ sendMessage(iface, P2P_INVITATION_RESULT_EVENT, result);
+ }
+
+ /**
+ * Broadcast PB discovery request event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param event Provision discovery request event.
+ */
+ public void broadcastP2pProvisionDiscoveryPbcRequest(String iface, WifiP2pProvDiscEvent event) {
+ if (event != null) {
+ sendMessage(iface, P2P_PROV_DISC_PBC_REQ_EVENT, event);
+ }
+ }
+
+ /**
+ * Broadcast PB discovery response event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param event Provision discovery response event.
+ */
+ public void broadcastP2pProvisionDiscoveryPbcResponse(
+ String iface, WifiP2pProvDiscEvent event) {
+ if (event != null) {
+ sendMessage(iface, P2P_PROV_DISC_PBC_RSP_EVENT, event);
+ }
+ }
+
+ /**
+ * Broadcast PIN discovery request event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param event Provision discovery request event.
+ */
+ public void broadcastP2pProvisionDiscoveryEnterPin(String iface, WifiP2pProvDiscEvent event) {
+ if (event != null) {
+ sendMessage(iface, P2P_PROV_DISC_ENTER_PIN_EVENT, event);
+ }
+ }
+
+ /**
+ * Broadcast PIN discovery response event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param event Provision discovery response event.
+ */
+ public void broadcastP2pProvisionDiscoveryShowPin(String iface, WifiP2pProvDiscEvent event) {
+ if (event != null) {
+ sendMessage(iface, P2P_PROV_DISC_SHOW_PIN_EVENT, event);
+ }
+ }
+
+ /**
+ * Broadcast P2P discovery failure event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ */
+ public void broadcastP2pProvisionDiscoveryFailure(String iface) {
+ sendMessage(iface, P2P_PROV_DISC_FAILURE_EVENT);
+ }
+
+ /**
+ * Broadcast service discovery response event to all handlers registered for this event.
+ *
+ * @param iface Name of iface on which this occurred.
+ * @param services List of discovered services.
+ */
+ public void broadcastP2pServiceDiscoveryResponse(
+ String iface, List<WifiP2pServiceResponse> services) {
+ sendMessage(iface, P2P_SERV_DISC_RESP_EVENT, services);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceCallbackTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceCallbackTest.java
new file mode 100644
index 000000000..bf6299672
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceCallbackTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.wifi;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.test.MockAnswerUtil.AnswerWithArguments;
+import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback;
+import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
+import android.net.wifi.WpsInfo;
+import android.net.wifi.p2p.WifiP2pConfig;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pWfdInfo;
+
+import org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * Unit tests for SupplicantP2pIfaceCallback
+ */
+public class SupplicantP2pIfaceCallbackTest {
+ private static final String TAG = "SupplicantP2pIfaceCallbackTest";
+
+ private String mIface = "test_p2p0";
+ private WifiMonitor mMonitor;
+ private SupplicantP2pIfaceCallback mDut;
+
+ private byte[] mDeviceAddressInvalid1 = { 0x00 };
+ private byte[] mDeviceAddressInvalid2 = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
+ private byte[] mDeviceAddress1Bytes = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
+ private String mDeviceAddress1String = "00:11:22:33:44:55";
+ private byte[] mDeviceAddress2Bytes = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56 };
+ private String mDeviceAddress2String = "01:12:23:34:45:56";
+ private byte[] mDeviceInfoBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ private class SupplicantP2pIfaceCallbackSpy extends SupplicantP2pIfaceCallback {
+ SupplicantP2pIfaceCallbackSpy(String iface, WifiMonitor monitor) {
+ super(iface, monitor);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mMonitor = mock(WifiMonitor.class);
+ mDut = new SupplicantP2pIfaceCallbackSpy(mIface, mMonitor);
+ }
+
+ /**
+ * Sunny day scenario for onDeviceFound call.
+ */
+ @Test
+ public void testOnDeviceFound_success() throws Exception {
+ byte[] fakePrimaryDeviceTypeBytes = { 0x01, 0x02, 0x03 };
+ String fakePrimaryDeviceTypeString = "010203";
+ String fakeDeviceName = "test device name";
+ short fakeConfigMethods = 0x1234;
+ byte fakeCapabilities = 123;
+ int fakeGroupCapabilities = 456;
+
+ doAnswer(new AnswerWithArguments() {
+ public void answer(String iface, WifiP2pDevice device) {
+ // NOTE: mDeviceAddress1Bytes seems to be ignored by
+ // legacy implementation of WifiP2pDevice.
+ assertEquals(iface, mIface);
+ assertEquals(device.deviceName, fakeDeviceName);
+ assertEquals(device.primaryDeviceType, fakePrimaryDeviceTypeString);
+ assertEquals(device.deviceCapability, fakeCapabilities);
+ assertEquals(device.groupCapability, fakeGroupCapabilities);
+ assertEquals(device.wpsConfigMethodsSupported, fakeConfigMethods);
+ assertEquals(device.deviceAddress, mDeviceAddress2String);
+ assertEquals(device.status, WifiP2pDevice.AVAILABLE);
+ }
+ })
+ .when(mMonitor).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+
+ mDut.onDeviceFound(
+ mDeviceAddress1Bytes, mDeviceAddress2Bytes,
+ fakePrimaryDeviceTypeBytes,
+ fakeDeviceName, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ mDeviceInfoBytes);
+
+ mDut.onDeviceFound(
+ mDeviceAddress1Bytes, mDeviceAddress2Bytes,
+ fakePrimaryDeviceTypeBytes,
+ fakeDeviceName, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ null);
+
+ // Make sure we issued a broadcast each time.
+ verify(mMonitor, times(2)).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+ }
+
+ /**
+ * Failing scenarios for onDeviceFound call.
+ */
+ @Test
+ public void testOnDeviceFound_invalidArguments() throws Exception {
+ byte[] fakePrimaryDeviceTypeBytes = { 0x01, 0x02, 0x03 };
+ String fakePrimaryDeviceTypeString = "010203";
+ String fakeDeviceName = "test device name";
+ short fakeConfigMethods = 0x1234;
+ byte fakeCapabilities = 123;
+ int fakeGroupCapabilities = 456;
+
+ mDut.onDeviceFound(
+ mDeviceAddress2Bytes, null,
+ fakePrimaryDeviceTypeBytes,
+ fakeDeviceName, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ mDeviceInfoBytes);
+ verify(mMonitor, never()).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+
+
+ mDut.onDeviceFound(
+ mDeviceAddress1Bytes, mDeviceAddress2Bytes,
+ null,
+ fakeDeviceName, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ mDeviceInfoBytes);
+ verify(mMonitor, never()).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+
+
+ mDut.onDeviceFound(
+ mDeviceAddress1Bytes, mDeviceAddress2Bytes,
+ fakePrimaryDeviceTypeBytes,
+ null, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ mDeviceInfoBytes);
+ verify(mMonitor, never()).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+
+
+ mDut.onDeviceFound(
+ mDeviceAddress1Bytes, mDeviceAddressInvalid1,
+ fakePrimaryDeviceTypeBytes,
+ null, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ mDeviceInfoBytes);
+ verify(mMonitor, never()).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+
+
+ mDut.onDeviceFound(
+ mDeviceAddress1Bytes, mDeviceAddressInvalid2,
+ fakePrimaryDeviceTypeBytes,
+ null, fakeConfigMethods,
+ fakeCapabilities, fakeGroupCapabilities,
+ mDeviceInfoBytes);
+ verify(mMonitor, never()).broadcastP2pDeviceFound(
+ anyString(), any(WifiP2pDevice.class));
+ }
+
+ /**
+ * Sunny day scenario for onDeviceLost call.
+ */
+ @Test
+ public void testOnDeviceLost_success() throws Exception {
+ doAnswer(new AnswerWithArguments() {
+ public void answer(String iface, WifiP2pDevice device) {
+ assertEquals(iface, mIface);
+ assertEquals(device.deviceAddress, mDeviceAddress1String);
+ assertEquals(device.status, WifiP2pDevice.UNAVAILABLE);
+ }
+ })
+ .when(mMonitor).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+
+ mDut.onDeviceLost(mDeviceAddress1Bytes);
+
+ // Make sure we issued a broadcast each time.
+ verify(mMonitor, times(1)).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+ }
+
+ /**
+ * Failing scenarios for onDeviceLost call.
+ */
+ @Test
+ public void testOnDeviceLost_invalidArguments() throws Exception {
+ mDut.onDeviceLost(null);
+ verify(mMonitor, never()).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+
+ mDut.onDeviceLost(mDeviceAddressInvalid1);
+ verify(mMonitor, never()).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+
+ mDut.onDeviceLost(mDeviceAddressInvalid2);
+ verify(mMonitor, never()).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+ }
+
+ /**
+ * Sunny day scenario for onGoNegotiationRequest call.
+ */
+ @Test
+ public void testOnGoNegotiationRequest_success() throws Exception {
+ HashSet<Integer> setups = new HashSet<Integer>();
+
+ doAnswer(new AnswerWithArguments() {
+ public void answer(String iface, WifiP2pConfig config) {
+ assertEquals(iface, mIface);
+ assertNotNull(config.wps);
+ setups.add(config.wps.setup);
+ assertEquals(config.deviceAddress, mDeviceAddress1String);
+ }
+ })
+ .when(mMonitor).broadcastP2pGoNegotiationRequest(
+ anyString(), any(WifiP2pConfig.class));
+
+ mDut.onGoNegotiationRequest(mDeviceAddress1Bytes,
+ (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.USER_SPECIFIED);
+ assertTrue(setups.contains(WpsInfo.DISPLAY));
+
+ mDut.onGoNegotiationRequest(mDeviceAddress1Bytes,
+ (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.PUSHBUTTON);
+ assertTrue(setups.contains(WpsInfo.PBC));
+
+ mDut.onGoNegotiationRequest(mDeviceAddress1Bytes,
+ (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.REGISTRAR_SPECIFIED);
+ assertTrue(setups.contains(WpsInfo.KEYPAD));
+
+ // Invalid should default to PBC
+ setups.clear();
+ mDut.onGoNegotiationRequest(mDeviceAddress1Bytes, (short)0xffff);
+ assertTrue(setups.contains(WpsInfo.PBC));
+ }
+
+ /**
+ * Failing scenarios for onGoNegotiationRequest call.
+ */
+ @Test
+ public void testOnGoNegotiationRequest_invalidArguments() throws Exception {
+ mDut.onGoNegotiationRequest(null, (short)0);
+ verify(mMonitor, never()).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+
+ mDut.onGoNegotiationRequest(mDeviceAddressInvalid1, (short)0);
+ verify(mMonitor, never()).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+
+ mDut.onGoNegotiationRequest(mDeviceAddressInvalid2, (short)0);
+ verify(mMonitor, never()).broadcastP2pDeviceLost(
+ anyString(), any(WifiP2pDevice.class));
+ }
+
+ /**
+ * Sunny day scenario for onGroupStarted call.
+ */
+ @Test
+ public void testOnGroupStarted_success() throws Exception {
+ String fakeName = "group name";
+ String fakePassphrase = "secret";
+ ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{
+ add((byte)0x30);
+ add((byte)0x31);
+ add((byte)0x32);
+ add((byte)0x33);
+ }};
+ String fakeSsidString = "\"0123\"";
+ HashSet<String> passwords = new HashSet<String>();
+
+ doAnswer(new AnswerWithArguments() {
+ public void answer(String iface, WifiP2pGroup group) {
+ assertEquals(iface, mIface);
+ assertNotNull(group.getOwner());
+ assertEquals(group.getOwner().deviceAddress, mDeviceAddress1String);
+ assertEquals(group.getNetworkId(), WifiP2pGroup.PERSISTENT_NET_ID);
+ passwords.add(group.getPassphrase());
+ assertEquals(group.getInterface(), fakeName);
+ assertEquals(group.getNetworkName(), fakeSsidString);
+ }
+ })
+ .when(mMonitor).broadcastP2pGroupStarted(
+ anyString(), any(WifiP2pGroup.class));
+
+ mDut.onGroupStarted(
+ fakeName, true, fakeSsidBytesList, 1, null, fakePassphrase,
+ mDeviceAddress1Bytes, true);
+ assertTrue(passwords.contains(fakePassphrase));
+
+ mDut.onGroupStarted(
+ fakeName, true, fakeSsidBytesList, 1, null, null,
+ mDeviceAddress1Bytes, true);
+ assertTrue(passwords.contains(null));
+
+ verify(mMonitor, times(2)).broadcastP2pGroupStarted(
+ anyString(), any(WifiP2pGroup.class));
+ }
+
+ /**
+ * Failing scenarios for onGroupStarted call.
+ */
+ @Test
+ public void testOnGroupStarted_invalidArguments() throws Exception {
+ String fakeName = "group name";
+ String fakePassphrase = "secret";
+ ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{
+ add((byte)0x30);
+ add((byte)0x31);
+ add((byte)0x32);
+ add((byte)0x33);
+ }};
+ String fakeSsidString = "0123";
+
+ mDut.onGroupStarted(
+ null, true, fakeSsidBytesList, 1, null, fakePassphrase,
+ mDeviceAddress1Bytes, true);
+ verify(mMonitor, never()).broadcastP2pGroupStarted(
+ anyString(), any(WifiP2pGroup.class));
+
+ mDut.onGroupStarted(
+ fakeName, true, null, 1, null, fakePassphrase,
+ mDeviceAddress1Bytes, true);
+ verify(mMonitor, never()).broadcastP2pGroupStarted(
+ anyString(), any(WifiP2pGroup.class));
+
+ mDut.onGroupStarted(
+ fakeName, true, fakeSsidBytesList, 1, null, fakePassphrase,
+ null, true);
+ verify(mMonitor, never()).broadcastP2pGroupStarted(
+ anyString(), any(WifiP2pGroup.class));
+ }
+
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java
index ca9c29592..b08ebdf97 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java
@@ -129,7 +129,9 @@ public class SupplicantP2pIfaceHalTest {
private InOrder mInOrder;
private class SupplicantP2pIfaceHalSpy extends SupplicantP2pIfaceHal {
- SupplicantP2pIfaceHalSpy() {}
+ SupplicantP2pIfaceHalSpy() {
+ super(null);
+ }
@Override
protected IServiceManager getServiceManagerMockable() throws RemoteException {