Merge "Add RequiresApi annotation for T+ method call." into main
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 750bfce..f01e1bb 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -3622,6 +3622,43 @@
InetAddresses.parseNumericAddress(ifaceConfig.ipv4Addr), ifaceConfig.prefixLength);
assertFalse(sapPrefix.equals(lohsPrefix));
}
+
+ @Test
+ public void testWifiTetheringWhenP2pActive() throws Exception {
+ initTetheringOnTestThread();
+ // Enable wifi P2P.
+ sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
+ verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
+ verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
+ verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
+ verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
+ // Verify never enable upstream if only P2P active.
+ verify(mUpstreamNetworkMonitor, never()).setTryCell(true);
+ assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastErrorForTest(TEST_P2P_IFNAME));
+
+ when(mWifiManager.startTetheredHotspot(any())).thenReturn(true);
+ // Emulate pressing the WiFi tethering button.
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), TEST_CALLER_PKG,
+ null);
+ mLooper.dispatchAll();
+ verify(mWifiManager).startTetheredHotspot(null);
+ verifyNoMoreInteractions(mWifiManager);
+
+ mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
+
+ verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
+ verify(mWifiManager).updateInterfaceIpState(
+ TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
+
+ verify(mWifiManager).updateInterfaceIpState(TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
+ verifyNoMoreInteractions(mWifiManager);
+
+ verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
+ // FIXME: wifi tethering doesn't have upstream when P2P is enabled.
+ verify(mUpstreamNetworkMonitor, never()).setTryCell(true);
+ }
+
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}
diff --git a/framework/src/android/net/BpfNetMapsUtils.java b/framework/src/android/net/BpfNetMapsUtils.java
index 3c91db2..19ecafb 100644
--- a/framework/src/android/net/BpfNetMapsUtils.java
+++ b/framework/src/android/net/BpfNetMapsUtils.java
@@ -47,6 +47,7 @@
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
import static android.system.OsConstants.EINVAL;
+import android.os.Process;
import android.os.ServiceSpecificException;
import android.system.ErrnoException;
import android.system.Os;
@@ -239,6 +240,12 @@
) {
throwIfPreT("isUidBlockedByFirewallChains is not available on pre-T devices");
+ // System uid is not blocked by firewall chains, see bpf_progs/netd.c
+ // TODO: use UserHandle.isCore() once it is accessible
+ if (uid < Process.FIRST_APPLICATION_UID) {
+ return false;
+ }
+
final long uidRuleConfig;
final long uidMatch;
try {
diff --git a/netbpfload/netbpfload.mainline.rc b/netbpfload/netbpfload.mainline.rc
index d7202f7..d38a503 100644
--- a/netbpfload/netbpfload.mainline.rc
+++ b/netbpfload/netbpfload.mainline.rc
@@ -10,6 +10,7 @@
capabilities CHOWN SYS_ADMIN NET_ADMIN
group system root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw
user system
+ file /dev/kmsg w
rlimit memlock 1073741824 1073741824
oneshot
reboot_on_failure reboot,bpfloader-failed
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index bfcc171..9c8fd99 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -460,7 +460,7 @@
if (!include) {
removeTestData();
}
- mHandler.post(() -> trackAvailableInterfaces());
+ trackAvailableInterfaces();
});
}
diff --git a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
new file mode 100644
index 0000000..e92c906
--- /dev/null
+++ b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 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 android.net.cts
+
+import android.content.pm.PackageManager.FEATURE_WIFI
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.net.NetworkRequest
+import android.os.Build
+import android.system.OsConstants
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.PropertyUtil.isVendorApiLevelNewerThan
+import com.android.compatibility.common.util.SystemUtil
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.NetworkStackModuleTest
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
+import com.android.testutils.TestableNetworkCallback
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val TIMEOUT_MS = 2000L
+
+@RunWith(DevSdkIgnoreRunner::class)
+@NetworkStackModuleTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+class ApfIntegrationTest {
+ private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
+ private val cm by lazy { context.getSystemService(ConnectivityManager::class.java)!! }
+ private val pm by lazy { context.packageManager }
+ private lateinit var wifiIfaceName: String
+ @Before
+ fun setUp() {
+ assumeTrue(pm.hasSystemFeature(FEATURE_WIFI))
+ assumeTrue(isVendorApiLevelNewerThan(Build.VERSION_CODES.TIRAMISU))
+ val cb = TestableNetworkCallback()
+ cm.requestNetwork(
+ NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(),
+ cb
+ )
+ cb.eventuallyExpect<LinkPropertiesChanged>(TIMEOUT_MS) {
+ wifiIfaceName = assertNotNull(it.lp.interfaceName)
+ true
+ }
+ assertNotNull(wifiIfaceName)
+ }
+
+ @Test
+ fun testGetApfCapabilities() {
+ val capabilities = SystemUtil
+ .runShellCommand("cmd network_stack apf $wifiIfaceName capabilities").trim()
+ val (version, maxLen, packetFormat) = capabilities.split(",").map { it.toInt() }
+ assertEquals(4, version)
+ assertThat(maxLen).isAtLeast(1024)
+ if (isVendorApiLevelNewerThan(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) {
+ assertThat(maxLen).isAtLeast(2000)
+ }
+ assertEquals(OsConstants.ARPHRD_ETHER, packetFormat)
+ }
+}
diff --git a/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt b/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt
index ca98269..a9ccbdd 100644
--- a/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt
+++ b/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt
@@ -26,6 +26,7 @@
import android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY
import android.net.BpfNetMapsUtils.getMatchByFirewallChain
import android.os.Build.VERSION_CODES
+import android.os.Process.FIRST_APPLICATION_UID
import com.android.net.module.util.IBpfMap
import com.android.net.module.util.Struct.S32
import com.android.net.module.util.Struct.U32
@@ -42,7 +43,7 @@
import org.junit.Test
import org.junit.runner.RunWith
-private const val TEST_UID1 = 1234
+private const val TEST_UID1 = 11234
private const val TEST_UID2 = TEST_UID1 + 1
private const val TEST_UID3 = TEST_UID2 + 1
private const val NO_IIF = 0
@@ -231,6 +232,24 @@
}
@Test
+ fun testIsUidNetworkingBlocked_SystemUid() {
+ mockDataSaverEnabled(enabled = false)
+ testConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, U32(0))
+ mockChainEnabled(ConnectivityManager.FIREWALL_CHAIN_DOZABLE, true)
+
+ for (uid in FIRST_APPLICATION_UID - 5..FIRST_APPLICATION_UID + 5) {
+ // system uid is not blocked regardless of firewall chains
+ val expectBlocked = uid >= FIRST_APPLICATION_UID
+ testUidOwnerMap.updateEntry(S32(uid), UidOwnerValue(NO_IIF, PENALTY_BOX_MATCH))
+ assertEquals(
+ expectBlocked,
+ isUidNetworkingBlocked(uid, metered = true),
+ "isUidNetworkingBlocked returns unexpected value for uid = " + uid
+ )
+ }
+ }
+
+ @Test
fun testGetDataSaverEnabled() {
testDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, U8(DATA_SAVER_DISABLED))
assertFalse(bpfNetMapsReader.dataSaverEnabled)
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index f41d7b2..1f8a743 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -17434,11 +17434,12 @@
}
mWiFiAgent.disconnect();
- waitForIdle();
if (expectUnavailable) {
+ testFactory.expectRequestRemove();
testFactory.assertRequestCountEquals(0);
} else {
+ testFactory.expectRequestAdd();
testFactory.assertRequestCountEquals(1);
}
diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
index 155296d..0b13d1b 100644
--- a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
+++ b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
@@ -405,7 +405,10 @@
public void initialize() {
mHandler.post(
() -> {
- Log.d(TAG, "Initializing Thread system service...");
+ Log.d(
+ TAG,
+ "Initializing Thread system service: Thread is "
+ + (isEnabled() ? "enabled" : "disabled"));
try {
mTunIfController.createTunInterface();
} catch (IOException e) {
@@ -490,6 +493,8 @@
return;
}
+ Log.i(TAG, "Set Thread enabled: " + isEnabled + ", persist: " + persist);
+
if (persist) {
// The persistent setting keeps the desired enabled state, thus it's set regardless
// the otDaemon set enabled state operation succeeded or not, so that it can recover
diff --git a/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java b/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java
index 5cb53fe..923f002 100644
--- a/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java
+++ b/thread/service/java/com/android/server/thread/ThreadPersistentSettings.java
@@ -61,7 +61,7 @@
/******** Thread persistent setting keys ***************/
/** Stores the Thread feature toggle state, true for enabled and false for disabled. */
- public static final Key<Boolean> THREAD_ENABLED = new Key<>("Thread_enabled", true);
+ public static final Key<Boolean> THREAD_ENABLED = new Key<>("thread_enabled", true);
/******** Thread persistent setting keys ***************/
diff --git a/thread/tests/integration/src/android/net/thread/ThreadNetworkControllerTest.java b/thread/tests/integration/src/android/net/thread/ThreadNetworkControllerTest.java
index 496ec9f..ba04348 100644
--- a/thread/tests/integration/src/android/net/thread/ThreadNetworkControllerTest.java
+++ b/thread/tests/integration/src/android/net/thread/ThreadNetworkControllerTest.java
@@ -27,6 +27,7 @@
import static org.junit.Assert.assertThrows;
import android.content.Context;
+import android.net.thread.utils.ThreadFeatureCheckerRule;
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresThreadFeature;
import android.os.OutcomeReceiver;
import android.util.SparseIntArray;
@@ -37,6 +38,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,6 +66,8 @@
}
};
+ @Rule public final ThreadFeatureCheckerRule mThreadRule = new ThreadFeatureCheckerRule();
+
private final Context mContext = ApplicationProvider.getApplicationContext();
private ExecutorService mExecutor;
private ThreadNetworkController mController;