Merge "Unicast state of existing ethernet interfaces when registering new Ethernet Listener."
diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java
index 29add1c..2c50c73 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -1076,11 +1076,12 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final void sendNetworkInfo(NetworkInfo networkInfo) {
- queueOrSendNetworkInfo(new NetworkInfo(networkInfo));
+ queueOrSendNetworkInfo(networkInfo);
}
private void queueOrSendNetworkInfo(NetworkInfo networkInfo) {
- queueOrSendMessage(reg -> reg.sendNetworkInfo(networkInfo));
+ final NetworkInfo ni = new NetworkInfo(networkInfo);
+ queueOrSendMessage(reg -> reg.sendNetworkInfo(ni));
}
/**
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 500c696..ba836b2 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -314,7 +314,11 @@
}
// TODO: use android::base::ScopeGuard.
- if (int ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK)) {
+ if (int ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK
+#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
+ | POSIX_SPAWN_CLOEXEC_DEFAULT
+#endif
+ )) {
posix_spawnattr_destroy(&attr);
throwIOException(env, "posix_spawnattr_setflags failed", ret);
return -1;
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index ae253f5..6414497 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -3431,6 +3431,10 @@
pw.increaseIndent();
nai.dumpInactivityTimers(pw);
pw.decreaseIndent();
+ pw.println("Nat464Xlat:");
+ pw.increaseIndent();
+ nai.dumpNat464Xlat(pw);
+ pw.decreaseIndent();
pw.decreaseIndent();
}
}
diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java
index cc81522..4a7c77a 100644
--- a/service/src/com/android/server/connectivity/ClatCoordinator.java
+++ b/service/src/com/android/server/connectivity/ClatCoordinator.java
@@ -36,6 +36,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.IBpfMap;
@@ -742,6 +743,69 @@
mClatdTracker = null;
}
+ private void dumpBpfIngress(@NonNull IndentingPrintWriter pw) {
+ if (mIngressMap == null) {
+ pw.println("No BPF ingress6 map");
+ return;
+ }
+
+ try {
+ if (mIngressMap.isEmpty()) {
+ pw.println("<empty>");
+ }
+ pw.println("BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif");
+ pw.increaseIndent();
+ mIngressMap.forEach((k, v) -> {
+ // TODO: print interface name
+ pw.println(String.format("%d %s/96 %s -> %s %d", k.iif, k.pfx96, k.local6,
+ v.local4, v.oif));
+ });
+ pw.decreaseIndent();
+ } catch (ErrnoException e) {
+ pw.println("Error dumping BPF ingress6 map: " + e);
+ }
+ }
+
+ private void dumpBpfEgress(@NonNull IndentingPrintWriter pw) {
+ if (mEgressMap == null) {
+ pw.println("No BPF egress4 map");
+ return;
+ }
+
+ try {
+ if (mEgressMap.isEmpty()) {
+ pw.println("<empty>");
+ }
+ pw.println("BPF egress map: iif v4Addr -> v6Addr nat64Prefix oif");
+ pw.increaseIndent();
+ mEgressMap.forEach((k, v) -> {
+ // TODO: print interface name
+ pw.println(String.format("%d %s -> %s %s/96 %d %s", k.iif, k.local4, v.local6,
+ v.pfx96, v.oif, v.oifIsEthernet != 0 ? "ether" : "rawip"));
+ });
+ pw.decreaseIndent();
+ } catch (ErrnoException e) {
+ pw.println("Error dumping BPF egress4 map: " + e);
+ }
+ }
+
+ /**
+ * Dump the cordinator information.
+ *
+ * @param pw print writer.
+ */
+ public void dump(@NonNull IndentingPrintWriter pw) {
+ // TODO: dump ClatdTracker
+ // TODO: move map dump to a global place to avoid duplicate dump while there are two or
+ // more IPv6 only networks.
+ pw.println("Forwarding rules:");
+ pw.increaseIndent();
+ dumpBpfIngress(pw);
+ dumpBpfEgress(pw);
+ pw.decreaseIndent();
+ pw.println();
+ }
+
/**
* Get clatd tracker. For test only.
*/
diff --git a/service/src/com/android/server/connectivity/Nat464Xlat.java b/service/src/com/android/server/connectivity/Nat464Xlat.java
index 35e02ca..e8fc06d 100644
--- a/service/src/com/android/server/connectivity/Nat464Xlat.java
+++ b/service/src/com/android/server/connectivity/Nat464Xlat.java
@@ -36,6 +36,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.NetworkStackConstants;
import com.android.server.ConnectivityService;
@@ -526,6 +527,24 @@
mNetwork.handler().post(() -> handleInterfaceRemoved(iface));
}
+ /**
+ * Dump the NAT64 xlat information.
+ *
+ * @param pw print writer.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ if (SdkLevel.isAtLeastT()) {
+ if (isStarted()) {
+ pw.println("ClatCoordinator:");
+ pw.increaseIndent();
+ mClatCoordinator.dump(pw);
+ pw.decreaseIndent();
+ } else {
+ pw.println("<not start>");
+ }
+ }
+ }
+
@Override
public String toString() {
return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState;
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 1fc5a8f..323888a 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -59,6 +59,7 @@
import android.util.Pair;
import android.util.SparseArray;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.WakeupMessage;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.ConnectivityService;
@@ -1186,6 +1187,15 @@
}
/**
+ * Dump the NAT64 xlat information.
+ *
+ * @param pw print writer.
+ */
+ public void dumpNat464Xlat(IndentingPrintWriter pw) {
+ clatd.dump(pw);
+ }
+
+ /**
* Sets the most recent ConnectivityReport for this network.
*
* <p>This should only be called from the ConnectivityService thread.
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 96ce65f..524bd65 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -898,7 +898,7 @@
final Intent intent = new Intent();
if (type == TYPE_COMPONENT_ACTIVTIY) {
intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_ACTIVITY_CLASS))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
} else if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_SERVICE_CLASS))
.setFlags(1);
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java
new file mode 100644
index 0000000..098f295
--- /dev/null
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 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.cts.net.hostside;
+
+
+import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getUiDevice;
+import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
+import static com.android.cts.net.hostside.Property.APP_STANDBY_MODE;
+import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
+import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
+import static com.android.cts.net.hostside.Property.DOZE_MODE;
+import static com.android.cts.net.hostside.Property.METERED_NETWORK;
+import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK;
+
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+@RequiredProperties({NON_METERED_NETWORK})
+public class ConnOnActivityStartTest extends AbstractRestrictBackgroundNetworkTestCase {
+ private static final int TEST_ITERATION_COUNT = 5;
+
+ @Before
+ public final void setUp() throws Exception {
+ super.setUp();
+ resetDeviceState();
+ }
+
+ @After
+ public final void tearDown() throws Exception {
+ super.tearDown();
+ resetDeviceState();
+ }
+
+ private void resetDeviceState() throws Exception {
+ resetBatteryState();
+ setBatterySaverMode(false);
+ setRestrictBackground(false);
+ setAppIdle(false);
+ setDozeMode(false);
+ }
+
+
+ @Test
+ @RequiredProperties({BATTERY_SAVER_MODE})
+ public void testStartActivity_batterySaver() throws Exception {
+ setBatterySaverMode(true);
+ assertLaunchedActivityHasNetworkAccess("testStartActivity_batterySaver");
+ }
+
+ @Test
+ @RequiredProperties({DATA_SAVER_MODE, METERED_NETWORK})
+ public void testStartActivity_dataSaver() throws Exception {
+ setRestrictBackground(true);
+ assertLaunchedActivityHasNetworkAccess("testStartActivity_dataSaver");
+ }
+
+ @Test
+ @RequiredProperties({DOZE_MODE})
+ public void testStartActivity_doze() throws Exception {
+ setDozeMode(true);
+ assertLaunchedActivityHasNetworkAccess("testStartActivity_doze");
+ }
+
+ @Test
+ @RequiredProperties({APP_STANDBY_MODE})
+ public void testStartActivity_appStandby() throws Exception {
+ turnBatteryOn();
+ setAppIdle(true);
+ assertLaunchedActivityHasNetworkAccess("testStartActivity_appStandby");
+ }
+
+ private void assertLaunchedActivityHasNetworkAccess(String testName) throws Exception {
+ for (int i = 0; i < TEST_ITERATION_COUNT; ++i) {
+ Log.i(TAG, testName + " start #" + i);
+ launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
+ getUiDevice().pressHome();
+ assertBackgroundState();
+ Log.i(TAG, testName + " end #" + i);
+ }
+ }
+}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
index 56be3e3..c53276b 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java
@@ -57,6 +57,7 @@
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
@@ -438,6 +439,10 @@
return InstrumentationRegistry.getInstrumentation();
}
+ public static UiDevice getUiDevice() {
+ return UiDevice.getInstance(getInstrumentation());
+ }
+
// When power saver mode or restrict background enabled or adding any white/black list into
// those modes, NetworkPolicy may need to take some time to update the rules of uids. So having
// this function and using PollingCheck to try to make sure the uid has updated and reduce the
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
index 9fdb9c9..08cdea7 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
@@ -43,15 +43,6 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "MyActivity.onCreate()");
- Common.notifyNetworkStateObserver(this, getIntent(), TYPE_COMPONENT_ACTIVTY);
- finishCommandReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "Finishing MyActivity");
- MyActivity.this.finish();
- }
- };
- registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY));
}
@Override
@@ -69,6 +60,28 @@
}
@Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ Log.d(TAG, "MyActivity.onNewIntent()");
+ setIntent(intent);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Log.d(TAG, "MyActivity.onResume(): " + getIntent());
+ Common.notifyNetworkStateObserver(this, getIntent(), TYPE_COMPONENT_ACTIVTY);
+ finishCommandReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "Finishing MyActivity");
+ MyActivity.this.finish();
+ }
+ };
+ registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY));
+ }
+
+ @Override
protected void onDestroy() {
Log.d(TAG, "MyActivity.onDestroy()");
super.onDestroy();
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java b/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java
new file mode 100644
index 0000000..3387fd7
--- /dev/null
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.cts.net;
+
+public class HostsideConnOnActivityStartTest extends HostsideNetworkTestCase {
+ private static final String TEST_CLASS = TEST_PKG + ".ConnOnActivityStartTest";
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ uninstallPackage(TEST_APP2_PKG, false);
+ installPackage(TEST_APP2_APK);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ uninstallPackage(TEST_APP2_PKG, true);
+ }
+
+ public void testStartActivity_batterySaver() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testStartActivity_batterySaver");
+ }
+
+ public void testStartActivity_dataSaver() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testStartActivity_dataSaver");
+ }
+
+ public void testStartActivity_doze() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testStartActivity_doze");
+ }
+
+ public void testStartActivity_appStandby() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testStartActivity_appStandby");
+ }
+}
diff --git a/tests/cts/net/src/android/net/cts/DnsResolverTest.java b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
index c6fc38f..0c53411 100644
--- a/tests/cts/net/src/android/net/cts/DnsResolverTest.java
+++ b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
@@ -49,6 +49,7 @@
import android.os.Handler;
import android.os.Looper;
import android.platform.test.annotations.AppModeFull;
+import android.provider.Settings;
import android.system.ErrnoException;
import android.util.Log;
@@ -727,6 +728,18 @@
@Test
public void testPrivateDnsBypass() throws InterruptedException {
+ final String dataStallSetting = Settings.Global.getString(mCR,
+ Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK);
+ Settings.Global.putInt(mCR, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 0);
+ try {
+ doTestPrivateDnsBypass();
+ } finally {
+ Settings.Global.putString(mCR, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK,
+ dataStallSetting);
+ }
+ }
+
+ private void doTestPrivateDnsBypass() throws InterruptedException {
final Network[] testNetworks = getTestableNetworks();
// Set an invalid private DNS server
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 0504973..d4f3d57 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -1275,4 +1275,23 @@
matchAllCallback.expectCallback<Lost>(wifiNetwork)
wifiAgent.expectCallback<OnNetworkUnwanted>()
}
+
+ @Test
+ fun testUnregisterAgentBeforeAgentFullyConnected() {
+ val specifier = UUID.randomUUID().toString()
+ val callback = TestableNetworkCallback()
+ val transports = intArrayOf(TRANSPORT_CELLULAR)
+ // Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
+ requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
+ val nc = makeTestNetworkCapabilities(specifier, transports)
+ val agent = createNetworkAgent(realContext, initialNc = nc)
+ // Connect the agent
+ agent.register()
+ // Mark agent connected then unregister agent immediately. Verify that both available and
+ // lost callback should be sent still.
+ agent.markConnected()
+ agent.unregister()
+ callback.expectCallback<Available>(agent.network!!)
+ callback.eventuallyExpect<Lost> { it.network == agent.network }
+ }
}