summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java92
-rw-r--r--service/java/com/android/server/wifi/SupplicantStaIfaceHal.java23
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java26
-rw-r--r--service/java/com/android/server/wifi/util/NativeUtil.java26
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java164
5 files changed, 303 insertions, 28 deletions
diff --git a/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java
index ba7064b4d..6a90f875f 100644
--- a/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantP2pIfaceHal.java
@@ -45,9 +45,11 @@ import com.android.server.wifi.util.NativeUtil;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* Native calls sending requests to the P2P Hals, and callbacks for receiving P2P events
@@ -1998,6 +2000,96 @@ public class SupplicantP2pIfaceHal {
return result.isSuccess();
}
}
+
+ /**
+ * Set the client list for the provided network.
+ *
+ * @param networkId Id of the network.
+ * @param clientListStr Space separated list of clients.
+ * @return true, if operation was successful.
+ */
+ public boolean setClientList(int networkId, String clientListStr) {
+ synchronized (mLock) {
+ if (!checkSupplicantP2pIfaceAndLogFailure("setClientList")) return false;
+ if (TextUtils.isEmpty(clientListStr)) {
+ Log.e(TAG, "Invalid client list");
+ return false;
+ }
+ ISupplicantP2pNetwork network = getNetwork(networkId);
+ if (network == null) {
+ Log.e(TAG, "Invalid network id ");
+ return false;
+ }
+ SupplicantResult<Void> result = new SupplicantResult(
+ "setClientList(" + networkId + ", " + clientListStr + ")");
+ ArrayList<byte[]> clients = new ArrayList<>();
+ for (String clientStr : Arrays.asList(clientListStr.split("\\s+"))) {
+ clients.add(NativeUtil.macAddressToByteArray(clientStr));
+ }
+ try {
+ result.setResult(network.setClientList(clients));
+ } catch (RemoteException e) {
+ Log.e(TAG, "ISupplicantP2pIface exception: " + e);
+ supplicantServiceDiedHandler();
+ }
+ return result.isSuccess();
+ }
+ }
+
+ /**
+ * Set the client list for the provided network.
+ *
+ * @param networkId Id of the network.
+ * @return Space separated list of clients if successfull, null otherwise.
+ */
+ public String getClientList(int networkId) {
+ synchronized (mLock) {
+ if (!checkSupplicantP2pIfaceAndLogFailure("getClientList")) return null;
+ ISupplicantP2pNetwork network = getNetwork(networkId);
+ if (network == null) {
+ Log.e(TAG, "Invalid network id ");
+ return null;
+ }
+ SupplicantResult<ArrayList> result = new SupplicantResult(
+ "getClientList(" + networkId + ")");
+ try {
+ network.getClientList(
+ (SupplicantStatus status, ArrayList<byte[]> clients) -> {
+ result.setResult(status, clients);
+ });
+ } catch (RemoteException e) {
+ Log.e(TAG, "ISupplicantP2pIface exception: " + e);
+ supplicantServiceDiedHandler();
+ }
+ if (!result.isSuccess()) {
+ return null;
+ }
+ ArrayList<byte[]> clients = result.getResult();
+ return clients.stream()
+ .map(NativeUtil::macAddressFromByteArray)
+ .collect(Collectors.joining(" "));
+ }
+ }
+
+ /**
+ * Persist the current configurations to disk.
+ *
+ * @return true, if operation was successful.
+ */
+ public boolean saveConfig() {
+ synchronized (mLock) {
+ if (!checkSupplicantP2pIfaceAndLogFailure("saveConfig")) return false;
+ SupplicantResult<Void> result = new SupplicantResult("saveConfig()");
+ try {
+ result.setResult(mISupplicantP2pIface.saveConfig());
+ } 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/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
index 8f141e6a2..8308b4c0d 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
@@ -1732,18 +1732,6 @@ public class SupplicantStaIfaceHal {
}
}
- /**
- * Helper utility to convert the bssid bytes to long.
- */
- private Long toLongBssid(byte[] bssidBytes) {
- try {
- return ByteBufferReader.readInteger(
- ByteBuffer.wrap(bssidBytes), ByteOrder.BIG_ENDIAN, bssidBytes.length);
- } catch (BufferUnderflowException | IllegalArgumentException e) {
- return 0L;
- }
- }
-
@Override
public void onNetworkAdded(int id) {
logCallback("onNetworkAdded");
@@ -1794,7 +1782,7 @@ public class SupplicantStaIfaceHal {
addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability);
addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList);
mWifiMonitor.broadcastAnqpDoneEvent(
- mIfaceName, new AnqpEvent(toLongBssid(bssid), elementsMap));
+ mIfaceName, new AnqpEvent(NativeUtil.macAddressToLong(bssid), elementsMap));
}
}
@@ -1805,7 +1793,7 @@ public class SupplicantStaIfaceHal {
synchronized (mLock) {
mWifiMonitor.broadcastIconDoneEvent(
mIfaceName,
- new IconEvent(toLongBssid(bssid), fileName, data.size(),
+ new IconEvent(NativeUtil.macAddressToLong(bssid), fileName, data.size(),
NativeUtil.byteArrayFromArrayList(data)));
}
}
@@ -1815,7 +1803,8 @@ public class SupplicantStaIfaceHal {
logCallback("onHs20SubscriptionRemediation");
synchronized (mLock) {
mWifiMonitor.broadcastWnmEvent(
- mIfaceName, new WnmData(toLongBssid(bssid), url, osuMethod));
+ mIfaceName,
+ new WnmData(NativeUtil.macAddressToLong(bssid), url, osuMethod));
}
}
@@ -1826,8 +1815,8 @@ public class SupplicantStaIfaceHal {
synchronized (mLock) {
mWifiMonitor.broadcastWnmEvent(
mIfaceName,
- new WnmData(toLongBssid(bssid), url, reasonCode == WnmData.ESS,
- reAuthDelayInSec));
+ new WnmData(NativeUtil.macAddressToLong(bssid), url,
+ reasonCode == WnmData.ESS, reAuthDelayInSec));
}
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 87ace7839..fb8c0e612 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -1276,29 +1276,33 @@ public class WifiNative {
}
/**
- * Get P2P client list for the given network ID.
- * @return true on success, false otherwise.
+ * Set the client list for the provided network.
+ *
+ * @param netId Id of the network.
+ * @return Space separated list of clients if successfull, null otherwise.
*/
public String getP2pClientList(int netId) {
- // TODO(b/36042785): Add HIDL method.
- return null;
+ return mSupplicantP2pIfaceHal.getClientList(netId);
}
/**
- * Set P2P client list for the given network ID.
- * @return true on success, false otherwise.
+ * Set the client list for the provided network.
+ *
+ * @param netId Id of the network.
+ * @param list Space separated list of clients.
+ * @return true, if operation was successful.
*/
public boolean setP2pClientList(int netId, String list) {
- // TODO(b/36042785): Add HIDL method.
- return false;
+ return mSupplicantP2pIfaceHal.setClientList(netId, list);
}
/**
- * Save the current configuration to wpa_supplicant.conf.
+ * Save the current configuration to p2p_supplicant.conf.
+ *
+ * @return true on success, false otherwise.
*/
public boolean saveConfig() {
- // TODO(b/36042785): Add HIDL method.
- return false;
+ return mSupplicantP2pIfaceHal.saveConfig();
}
/********************************************************
diff --git a/service/java/com/android/server/wifi/util/NativeUtil.java b/service/java/com/android/server/wifi/util/NativeUtil.java
index 50f32fa4d..a13b682a0 100644
--- a/service/java/com/android/server/wifi/util/NativeUtil.java
+++ b/service/java/com/android/server/wifi/util/NativeUtil.java
@@ -18,9 +18,13 @@ package com.android.server.wifi.util;
import android.text.TextUtils;
+import com.android.server.wifi.ByteBufferReader;
+
import libcore.util.HexEncoding;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
@@ -156,6 +160,28 @@ public class NativeUtil {
}
/**
+ * Converts an array of 6 bytes to a long representing the MAC address.
+ *
+ * @param macArray byte array of mac values, must have length 6
+ * @return Long value of the mac address.
+ * @throws IllegalArgumentException for malformed inputs.
+ */
+ public static Long macAddressToLong(byte[] macArray) {
+ if (macArray == null) {
+ throw new IllegalArgumentException("null mac bytes");
+ }
+ if (macArray.length != MAC_LENGTH) {
+ throw new IllegalArgumentException("invalid macArray length: " + macArray.length);
+ }
+ try {
+ return ByteBufferReader.readInteger(
+ ByteBuffer.wrap(macArray), ByteOrder.BIG_ENDIAN, macArray.length);
+ } catch (BufferUnderflowException | IllegalArgumentException e) {
+ throw new IllegalArgumentException("invalid macArray");
+ }
+ }
+
+ /**
* Remove enclosed quotes of the provided string.
*
* @param quotedStr String to be unquoted.
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java
index 19dc521fb..9f1607d3b 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantP2pIfaceHalTest.java
@@ -20,6 +20,8 @@ import static org.mockito.Matchers.*;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.test.MockAnswerUtil.AnswerWithArguments;
@@ -2259,6 +2261,168 @@ public class SupplicantP2pIfaceHalTest {
}
/**
+ * Sunny day scenario for setClientList()
+ */
+ @Test
+ public void testSetClientList() throws Exception {
+ int testNetworkId = 5;
+ final String client1 = mGroupOwnerMacAddress;
+ final String client2 = mPeerMacAddress;
+
+ executeAndValidateInitializationSequence(false, false, false);
+ doAnswer(new AnswerWithArguments() {
+ public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) {
+ if (networkId == testNetworkId) {
+ cb.onValues(mStatusSuccess, mISupplicantP2pNetworkMock);
+ } else {
+ cb.onValues(mStatusFailure, null);
+ }
+ return;
+ }
+ }).when(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ when(mISupplicantP2pNetworkMock.setClientList(any(ArrayList.class)))
+ .thenReturn(mStatusSuccess);
+
+ String clientList = client1 + " " + client2;
+ assertTrue(mDut.setClientList(testNetworkId, clientList));
+ verify(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ ArgumentCaptor<ArrayList> capturedClients = ArgumentCaptor.forClass(ArrayList.class);
+ verify(mISupplicantP2pNetworkMock).setClientList(capturedClients.capture());
+
+ // Convert these to long to help with comparisons.
+ ArrayList<byte[]> clients = capturedClients.getValue();
+ ArrayList<Long> expectedClients = new ArrayList<Long>() {{
+ add(NativeUtil.macAddressToLong(mGroupOwnerMacAddressBytes));
+ add(NativeUtil.macAddressToLong(mPeerMacAddressBytes));
+ }};
+ ArrayList<Long> receivedClients = new ArrayList<Long>();
+ for (byte[] client : clients) {
+ receivedClients.add(NativeUtil.macAddressToLong(client));
+ }
+ assertEquals(expectedClients, receivedClients);
+ }
+
+ /**
+ * Failure scenario for setClientList() when getNetwork returns null.
+ */
+ @Test
+ public void testSetClientListFailureDueToGetNetwork() throws Exception {
+ int testNetworkId = 5;
+ final String client1 = mGroupOwnerMacAddress;
+ final String client2 = mPeerMacAddress;
+
+ executeAndValidateInitializationSequence(false, false, false);
+ doAnswer(new AnswerWithArguments() {
+ public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) {
+ cb.onValues(mStatusFailure, null);
+ return;
+ }
+ }).when(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ when(mISupplicantP2pNetworkMock.setClientList(any(ArrayList.class)))
+ .thenReturn(mStatusSuccess);
+
+ String clientList = client1 + " " + client2;
+ assertFalse(mDut.setClientList(testNetworkId, clientList));
+ verify(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ verify(mISupplicantP2pNetworkMock, never()).setClientList(any(ArrayList.class));
+ }
+
+ /**
+ * Sunny day scenario for getClientList()
+ */
+ @Test
+ public void testGetClientList() throws Exception {
+ int testNetworkId = 5;
+ final String client1 = mGroupOwnerMacAddress;
+ final String client2 = mPeerMacAddress;
+
+ executeAndValidateInitializationSequence(false, false, false);
+ doAnswer(new AnswerWithArguments() {
+ public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) {
+ if (networkId == testNetworkId) {
+ cb.onValues(mStatusSuccess, mISupplicantP2pNetworkMock);
+ } else {
+ cb.onValues(mStatusFailure, null);
+ }
+ return;
+ }
+ }).when(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ doAnswer(new AnswerWithArguments() {
+ public void answer(ISupplicantP2pNetwork.getClientListCallback cb) {
+ ArrayList<byte[]> clients = new ArrayList<byte[]>() {{
+ add(mGroupOwnerMacAddressBytes);
+ add(mPeerMacAddressBytes);
+ }};
+ cb.onValues(mStatusSuccess, clients);
+ return;
+ }
+ }).when(mISupplicantP2pNetworkMock)
+ .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class));
+
+ String clientList = client1 + " " + client2;
+ assertEquals(clientList, mDut.getClientList(testNetworkId));
+ verify(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ verify(mISupplicantP2pNetworkMock)
+ .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class));
+ }
+
+ /**
+ * Failure scenario for getClientList() when getNetwork returns null.
+ */
+ @Test
+ public void testGetClientListFailureDueToGetNetwork() throws Exception {
+ int testNetworkId = 5;
+ final String client1 = mGroupOwnerMacAddress;
+ final String client2 = mPeerMacAddress;
+
+ executeAndValidateInitializationSequence(false, false, false);
+ doAnswer(new AnswerWithArguments() {
+ public void answer(final int networkId, ISupplicantP2pIface.getNetworkCallback cb) {
+ cb.onValues(mStatusFailure, null);
+ return;
+ }
+ }).when(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ doAnswer(new AnswerWithArguments() {
+ public void answer(ISupplicantP2pNetwork.getClientListCallback cb) {
+ ArrayList<byte[]> clients = new ArrayList<byte[]>() {{
+ add(mGroupOwnerMacAddressBytes);
+ add(mPeerMacAddressBytes);
+ }};
+ cb.onValues(mStatusSuccess, clients);
+ return;
+ }
+ }).when(mISupplicantP2pNetworkMock)
+ .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class));
+
+ assertEquals(null, mDut.getClientList(testNetworkId));
+ verify(mISupplicantP2pIfaceMock)
+ .getNetwork(anyInt(), any(ISupplicantP2pIface.getNetworkCallback.class));
+ verify(mISupplicantP2pNetworkMock, never())
+ .getClientList(any(ISupplicantP2pNetwork.getClientListCallback.class));
+ }
+
+ /**
+ * Sunny day scenario for saveConfig()
+ */
+ @Test
+ public void testSaveConfig() throws Exception {
+ when(mISupplicantP2pIfaceMock.saveConfig()).thenReturn(mStatusSuccess);
+
+ // Should fail before initialization.
+ assertFalse(mDut.saveConfig());
+ executeAndValidateInitializationSequence(false, false, false);
+ assertTrue(mDut.saveConfig());
+ verify(mISupplicantP2pIfaceMock).saveConfig();
+ }
+
+ /**
* Calls.initialize(), mocking various call back answers and verifying flow, asserting for the
* expected result. Verifies if ISupplicantP2pIface manager is initialized or reset.
* Each of the arguments will cause a different failure mode when set true.