summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Quang Anh Luong <qal@google.com> 2024-11-14 15:08:52 +0900
committer Quang Anh Luong <qal@google.com> 2024-11-14 15:08:52 +0900
commit7d3fc37d9454d1d93c08af028f438a6c6c787413 (patch)
tree5ac9975ba577a02237e0db71741632a68a945cd8
parent791976156514c58385d7dc352cedfad55ea1de7e (diff)
Add overlay allowlist for AP/NAN concurrency
Add an overlay allowlist of packages that can use AP/NAN concurrency. If a non-allowlisted app tries to request AP (or Bridged AP) when NAN is up (or viceversa), then pretend AP/NAN concurrency isn't supported and force an interface conflict decision (reject request, delete existing, or show the ICM dialog). Updated-Overlayable: TRUE Flag: EXEMPT gated by overlay Bug: 365865790 Test: atest HalDeviceManagerTest Change-Id: Icb56a1b1850aeb7d67e62ab3de7ae71a64d2b14d
-rw-r--r--service/ServiceWifiResources/res/values/config.xml8
-rw-r--r--service/ServiceWifiResources/res/values/overlayable.xml1
-rw-r--r--service/java/com/android/server/wifi/HalDeviceManager.java49
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java154
4 files changed, 211 insertions, 1 deletions
diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml
index c6068b0ab9..da98aa9694 100644
--- a/service/ServiceWifiResources/res/values/config.xml
+++ b/service/ServiceWifiResources/res/values/config.xml
@@ -1114,6 +1114,14 @@
<item>com.company2.example.test.name2</item>
-->
</string-array>
+ <!-- list of package names that the framework will allow to use SoftAp/Aware concurrency. If
+ this list is empty, then all packages are allowed -->
+ <string-array translatable="false" name="config_wifiSoftApAwareConcurrencyAllowlist">
+ <!-- Below is a sample configuration for this list:
+ <item>com.company1.example.test.name1</item>
+ <item>com.company2.example.test.name2</item>
+ -->
+ </string-array>
<!-- boolean indicating whether the Easy Connect (DPP) AKM is supported -->
<bool translatable="false" name ="config_wifiDppAkmSupported">false</bool>
<!-- Indicates the number of octets to mask for each BSSID in the SecurityLog output.
diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml
index 7409ad1414..1c0c6a348d 100644
--- a/service/ServiceWifiResources/res/values/overlayable.xml
+++ b/service/ServiceWifiResources/res/values/overlayable.xml
@@ -308,6 +308,7 @@
<item type="bool" name="config_wifiUserApprovalNotRequireForDisconnectedP2p" />
<item type="integer" name="config_disconnectedP2pIfaceLowPriorityTimeoutMs" />
<item type="array" name="config_wifiP2pAwareConcurrencyAllowlist" />
+ <item type="array" name="config_wifiSoftApAwareConcurrencyAllowlist" />
<item type="bool" name="config_wifiNetworkCentricQosPolicyFeatureEnabled" />
<item type="bool" name="config_wifiApplicationCentricQosPolicyFeatureEnabled" />
<item type="string" name="config_wifiDriverWorldModeCountryCode" />
diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java
index 57d12f58b4..a251af8578 100644
--- a/service/java/com/android/server/wifi/HalDeviceManager.java
+++ b/service/java/com/android/server/wifi/HalDeviceManager.java
@@ -1900,6 +1900,51 @@ public class HalDeviceManager {
return false;
}
+ private boolean isRequestorAllowedToUseApNanConcurrency(WorkSource requestorWs) {
+ String[] allowlistArray = mContext.getResources().getStringArray(
+ R.array.config_wifiSoftApAwareConcurrencyAllowlist);
+ if (allowlistArray == null || allowlistArray.length == 0) {
+ // No allowlist defined, so allow.
+ return true;
+ }
+ List<String> allowlist = Arrays.asList(allowlistArray);
+ for (int i = 0; i < requestorWs.size(); i++) {
+ if (allowlist.contains(requestorWs.getPackageName(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove AP from the combo if NAN requested (or NAN if AP is requested) if the current
+ * requestor is not allowed to use AP/NAN concurrency.
+ */
+ @NonNull
+ private int[] removeApNanConcurrencyIfNotAllowed(
+ @NonNull int[] chipCreateTypeCombo,
+ @HdmIfaceTypeForCreation int requestedCreateType,
+ WorkSource requestorWs) {
+ if (isRequestorAllowedToUseApNanConcurrency(requestorWs)) {
+ return chipCreateTypeCombo;
+ }
+
+ int[] newCombo = chipCreateTypeCombo.clone();
+ switch (requestedCreateType) {
+ case HDM_CREATE_IFACE_AP:
+ case HDM_CREATE_IFACE_AP_BRIDGE:
+ newCombo[HDM_CREATE_IFACE_NAN] = 0;
+ break;
+ case HDM_CREATE_IFACE_NAN:
+ newCombo[HDM_CREATE_IFACE_AP] = 0;
+ newCombo[HDM_CREATE_IFACE_AP_BRIDGE] = 0;
+ break;
+ default:
+ break;
+ }
+ return newCombo;
+ }
+
/**
* Checks whether the input chip-create-type-combo can support the requested create type:
* if not then returns null, if yes then returns information containing the list of interfaces
@@ -1947,6 +1992,10 @@ public class HalDeviceManager {
}
}
+ // Remove AP/NAN concurrency if the requestor isn't on the allowlist.
+ chipCreateTypeCombo = removeApNanConcurrencyIfNotAllowed(
+ chipCreateTypeCombo, requestedCreateType, requestorWs);
+
IfaceCreationData ifaceCreationData = new IfaceCreationData();
ifaceCreationData.chipInfo = chipInfo;
ifaceCreationData.chipModeId = chipModeId;
diff --git a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
index a53be5d328..40fd2597c6 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java
@@ -4222,6 +4222,157 @@ public class HalDeviceManagerTest extends WifiBaseTest {
collector.checkThat("interface was null", p2pIface, IsNull.notNullValue());
}
+ /**
+ * Validate an AP request from requestors not on the AP/NAN concurrency allowlist.
+ */
+ @Test
+ public void testApNanConcurrencyNotAllowedTestChipV11()
+ throws Exception {
+ when(mResources.getStringArray(R.array.config_wifiSoftApAwareConcurrencyAllowlist))
+ .thenReturn(new String[]{"Some other package"});
+
+ TestChipV11 chipMock = new TestChipV11();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+ executeAndValidateStartupSequence();
+
+ InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class);
+
+ // Create a NAN
+ WifiInterface nanIface = validateInterfaceSequence(chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_NAN,
+ "wlan0",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+ collector.checkThat("interface was null", nanIface, IsNull.notNullValue());
+
+ // AP request from Worksource 1 (lower priority) should be blocked.
+ when(mWorkSourceHelper1.getRequestorWsPriority())
+ .thenReturn(WorkSourceHelper.PRIORITY_FG_APP);
+ List<Pair<Integer, WorkSource>> apDetails = mDut.reportImpactToCreateIface(
+ HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_1);
+ if (SdkLevel.isAtLeastS()) {
+ assertNull("Should not be able to create this AP", apDetails);
+ } else {
+ // Pre-S lets AP/NAN destroy each other.
+ assertEquals(apDetails.get(0).second, TEST_WORKSOURCE_0);
+ }
+
+ // Bridged AP request should also be blocked
+ apDetails = mDut.reportImpactToCreateIface(
+ HDM_CREATE_IFACE_AP_BRIDGE, true, TEST_WORKSOURCE_1);
+ if (SdkLevel.isAtLeastS()) {
+ assertNull("Should not be able to create this Bridged AP", apDetails);
+ } else {
+ // Pre-S lets AP/NAN destroy each other.
+ assertEquals(apDetails.get(0).second, TEST_WORKSOURCE_0);
+ }
+
+ // AP request from Worksource 2 (same privileged priority) should tear down NAN.
+ WifiInterface ApIface = validateInterfaceSequence(chipMock,
+ true, // chipModeValid
+ TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_AP,
+ "wlan1",
+ TestChipV11.CHIP_MODE_ID,
+ new WifiInterface[]{nanIface}, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_2 // requestorWs
+ );
+ collector.checkThat("interface was null", ApIface, IsNull.notNullValue());
+ }
+
+ /**
+ * Validate an AP request from a requestor on the AP/NAN concurrency allowlist.
+ */
+ @Test
+ public void testSingleApNanConcurrencyAllowedTestChipV11()
+ throws Exception {
+ when(mResources.getStringArray(R.array.config_wifiSoftApAwareConcurrencyAllowlist))
+ .thenReturn(new String[]{TEST_WORKSOURCE_1.getPackageName(0)});
+
+ TestChipV11 chipMock = new TestChipV11();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+ executeAndValidateStartupSequence();
+
+ InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class);
+
+ // Create a NAN
+ WifiInterface nanIface = validateInterfaceSequence(chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_NAN,
+ "wlan0",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+ collector.checkThat("interface was null", nanIface, IsNull.notNullValue());
+
+ // AP request from Worksource 1 (on allowlist) should be allowed.
+ WifiInterface apIface = validateInterfaceSequence(chipMock,
+ true, // chipModeValid
+ TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_AP,
+ "wlan1",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_1 // requestorWs
+ );
+ collector.checkThat("interface was null", apIface, IsNull.notNullValue());
+ }
+
+ /**
+ * Validate a Bridged AP request from a requestor on the AP/NAN concurrency allowlist.
+ */
+ @Test
+ public void testBridgedApNanConcurrencyAllowedTestChipV11()
+ throws Exception {
+ when(mResources.getStringArray(R.array.config_wifiSoftApAwareConcurrencyAllowlist))
+ .thenReturn(new String[]{TEST_WORKSOURCE_1.getPackageName(0)});
+
+ TestChipV11 chipMock = new TestChipV11();
+ chipMock.initialize();
+ mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock);
+ executeAndValidateStartupSequence();
+
+ InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class);
+
+ // Create a NAN
+ WifiInterface nanIface = validateInterfaceSequence(chipMock,
+ false, // chipModeValid
+ -1000, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_NAN,
+ "wlan0",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_0 // requestorWs
+ );
+ collector.checkThat("interface was null", nanIface, IsNull.notNullValue());
+
+ // Bridged AP request from Worksource 1 (on allowlist) should be allowed.
+ WifiInterface apIface = validateInterfaceSequence(chipMock,
+ true, // chipModeValid
+ TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true)
+ HDM_CREATE_IFACE_AP_BRIDGE,
+ "wlan1",
+ TestChipV11.CHIP_MODE_ID,
+ null, // tearDownList
+ idl, // destroyedListener
+ TEST_WORKSOURCE_1 // requestorWs
+ );
+ collector.checkThat("interface was null", apIface, IsNull.notNullValue());
+ }
+
///////////////////////////////////////////////////////////////////////////////////////
// utilities
///////////////////////////////////////////////////////////////////////////////////////
@@ -5533,7 +5684,7 @@ public class HalDeviceManagerTest extends WifiBaseTest {
// Test chip configuration V11 for P2P/NAN concurrency
// mode:
- // (STA + AP + NAN + P2P)
+ // (STA + AP + AP_BRIDGE + NAN + P2P)
private class TestChipV11 extends ChipMockBase {
static final int CHIP_MODE_ID = 90;
@@ -5555,6 +5706,7 @@ public class HalDeviceManagerTest extends WifiBaseTest {
WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo(
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA),
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP),
+ createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP_BRIDGED),
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P),
createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_NAN));
availableModes.add(createChipMode(CHIP_MODE_ID, combo1));