Merge "Make it clear that legacyTether always uses IpServer.STATE_TETHERED." into main
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index eedf427..9b3c7ba 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -397,6 +397,16 @@
return mFactory.hasInterface(iface);
}
+ private List<String> getAllInterfaces() {
+ final ArrayList<String> interfaces = new ArrayList<>(
+ List.of(mFactory.getAvailableInterfaces(/* includeRestricted */ true)));
+
+ if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER && mTetheringInterface != null) {
+ interfaces.add(mTetheringInterface);
+ }
+ return interfaces;
+ }
+
String[] getClientModeInterfaces(boolean includeRestricted) {
return mFactory.getAvailableInterfaces(includeRestricted);
}
@@ -459,10 +469,16 @@
public void setIncludeTestInterfaces(boolean include) {
mHandler.post(() -> {
mIncludeTestInterfaces = include;
- if (!include) {
+ if (include) {
+ trackAvailableInterfaces();
+ } else {
removeTestData();
+ // remove all test interfaces
+ for (String iface : getAllInterfaces()) {
+ if (isValidEthernetInterface(iface)) continue;
+ stopTrackingInterface(iface);
+ }
}
- trackAvailableInterfaces();
});
}
@@ -952,17 +968,7 @@
if (mIsEthernetEnabled == enabled) return;
mIsEthernetEnabled = enabled;
-
- // Interface in server mode should also be included.
- ArrayList<String> interfaces =
- new ArrayList<>(
- List.of(mFactory.getAvailableInterfaces(/* includeRestricted */ true)));
-
- if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER) {
- interfaces.add(mTetheringInterface);
- }
-
- for (String iface : interfaces) {
+ for (String iface : getAllInterfaces()) {
setInterfaceUpState(iface, enabled);
}
broadcastEthernetStateChange(mIsEthernetEnabled);
diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
index 1afe3b8..f17a7ec 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java
@@ -357,7 +357,8 @@
// interface, including change in administrative state. While RTM_SETLINK is used to
// modify an existing link rather than creating a new one.
return RtNetlinkLinkMessage.build(
- new StructNlMsgHdr(/*payloadLen*/ 0, RTM_NEWLINK, NLM_F_REQUEST, sequenceNumber),
+ new StructNlMsgHdr(
+ /*payloadLen*/ 0, RTM_NEWLINK, NLM_F_REQUEST_ACK, sequenceNumber),
new StructIfinfoMsg((short) AF_UNSPEC, /*type*/ 0, interfaceIndex,
flagsBits, changeBits),
DEFAULT_MTU, /*hardwareAddress*/ null, /*interfaceName*/ null);
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java
index 8104e3a..b29fc73 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java
@@ -308,7 +308,7 @@
@Test
public void testCreateSetInterfaceFlagsMessage() {
final String expectedHexBytes =
- "20000000100001006824000000000000" // struct nlmsghdr
+ "20000000100005006824000000000000" // struct nlmsghdr
+ "00000000080000000100000001000100"; // struct ifinfomsg
final String interfaceName = "wlan0";
final int interfaceIndex = 8;
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index ce94f87..1ba581a 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -24,9 +24,6 @@
"framework-connectivity-test-defaults",
],
- // TODO(b/391766151): remove when NetworkAgentTest passes with Kotlin 2.
- kotlin_lang_version: "1.9",
-
// Include both the 32 and 64 bit versions
compile_multilib: "both",
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 286e08c..4ba41cd 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -722,9 +722,15 @@
val cv = ConditionVariable()
val cpb = PrivilegeWaiterCallback(cv)
- tryTest {
+ // The lambda below is capturing |cpb|, whose type inherits from a class that appeared in
+ // T. This means the lambda will compile as a private method of this class taking a
+ // PrivilegeWaiterCallback argument. As JUnit uses reflection to enumerate all methods
+ // including private methods, this would fail with a link error when running on S-.
+ // To solve this, make the lambda serializable, which causes the compiler to emit a
+ // synthetic class instead of a synthetic method.
+ tryTest @JvmSerializableLambda {
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
- runAsShell(READ_PRIVILEGED_PHONE_STATE) {
+ runAsShell(READ_PRIVILEGED_PHONE_STATE) @JvmSerializableLambda {
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
}
// Wait for the callback to be registered
@@ -747,8 +753,8 @@
carrierConfigRule.cleanUpNow()
}
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't change carrier privilege")
- } cleanup {
- runAsShell(READ_PRIVILEGED_PHONE_STATE) {
+ } cleanup @JvmSerializableLambda {
+ runAsShell(READ_PRIVILEGED_PHONE_STATE) @JvmSerializableLambda {
tm.unregisterCarrierPrivilegesCallback(cpb)
}
}
@@ -762,9 +768,15 @@
val cv = ConditionVariable()
val cpb = CarrierServiceChangedWaiterCallback(cv)
- tryTest {
+ // The lambda below is capturing |cpb|, whose type inherits from a class that appeared in
+ // T. This means the lambda will compile as a private method of this class taking a
+ // PrivilegeWaiterCallback argument. As JUnit uses reflection to enumerate all methods
+ // including private methods, this would fail with a link error when running on S-.
+ // To solve this, make the lambda serializable, which causes the compiler to emit a
+ // synthetic class instead of a synthetic method.
+ tryTest @JvmSerializableLambda {
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
- runAsShell(READ_PRIVILEGED_PHONE_STATE) {
+ runAsShell(READ_PRIVILEGED_PHONE_STATE) @JvmSerializableLambda {
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
}
// Wait for the callback to be registered
@@ -786,8 +798,8 @@
}
}
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't modify carrier service package")
- } cleanup {
- runAsShell(READ_PRIVILEGED_PHONE_STATE) {
+ } cleanup @JvmSerializableLambda {
+ runAsShell(READ_PRIVILEGED_PHONE_STATE) @JvmSerializableLambda {
tm.unregisterCarrierPrivilegesCallback(cpb)
}
}
diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java
index 243cd27..82a295d 100644
--- a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java
@@ -126,6 +126,67 @@
}
}
+ public static class StopTetheringCallback implements TetheringManager.StopTetheringCallback {
+ private static final int TIMEOUT_MS = 30_000;
+ public static class CallbackValue {
+ public final int error;
+
+ private CallbackValue(final int e) {
+ error = e;
+ }
+
+ public static class OnStopTetheringSucceeded extends CallbackValue {
+ OnStopTetheringSucceeded() {
+ super(TETHER_ERROR_NO_ERROR);
+ }
+ }
+
+ public static class OnStopTetheringFailed extends CallbackValue {
+ OnStopTetheringFailed(final int error) {
+ super(error);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s(%d)", getClass().getSimpleName(), error);
+ }
+ }
+
+ private final ArrayTrackRecord<CallbackValue>.ReadHead mHistory =
+ new ArrayTrackRecord<CallbackValue>().newReadHead();
+
+ @Override
+ public void onStopTetheringSucceeded() {
+ mHistory.add(new CallbackValue.OnStopTetheringSucceeded());
+ }
+
+ @Override
+ public void onStopTetheringFailed(final int error) {
+ mHistory.add(new CallbackValue.OnStopTetheringFailed(error));
+ }
+
+ /**
+ * Verifies that {@link #onStopTetheringSucceeded()} was called
+ */
+ public void verifyStopTetheringSucceeded() {
+ final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
+ assertNotNull("No onStopTetheringSucceeded after " + TIMEOUT_MS + " ms", cv);
+ assertTrue("Fail stop tethering:" + cv,
+ cv instanceof CallbackValue.OnStopTetheringSucceeded);
+ }
+
+ /**
+ * Verifies that {@link #onStopTetheringFailed(int)} was called
+ */
+ public void expectStopTetheringFailed(final int expected) {
+ final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
+ assertNotNull("No onStopTetheringFailed after " + TIMEOUT_MS + " ms", cv);
+ assertTrue("Expect fail with error code " + expected + ", but received: " + cv,
+ (cv instanceof CallbackValue.OnStopTetheringFailed) && (cv.error == expected));
+ }
+ }
+
private static boolean isRegexMatch(final String[] ifaceRegexs, String iface) {
if (ifaceRegexs == null) fail("ifaceRegexs should not be null");
@@ -574,6 +635,23 @@
expectSoftApDisabled();
}
+ /**
+ * Calls {@link TetheringManager#stopTethering(TetheringRequest, Executor,
+ * TetheringManager.StopTetheringCallback)} and verifies it throws an
+ * UnsupportedOperationException.
+ */
+ public void stopTethering(final TetheringRequest request) {
+ final StopTetheringCallback callback = new StopTetheringCallback();
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ try {
+ mTm.stopTethering(request, Runnable::run /* Executor */, callback);
+ fail("stopTethering should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ // Success.
+ }
+ });
+ }
+
public void stopAllTethering() {
final TestTetheringEventCallback callback = registerTetheringEventCallback();
try {
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index d103f75..a2cac69 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -101,7 +101,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -458,14 +457,9 @@
@Test
public void testStopTetheringRequest() throws Exception {
+ assumeTrue(isTetheringWithSoftApConfigEnabled());
TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build();
- Executor executor = Runnable::run;
- TetheringManager.StopTetheringCallback callback =
- new TetheringManager.StopTetheringCallback() {};
- try {
- mTM.stopTethering(request, executor, callback);
- fail("stopTethering should throw UnsupportedOperationException");
- } catch (UnsupportedOperationException expect) { }
+ mCtsTetheringUtils.stopTethering(request);
}
private boolean isTetheringWithSoftApConfigEnabled() {
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index b7cfaf9..533bbf8 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -79,6 +79,7 @@
initMockResources();
doReturn(false).when(mFactory).updateInterfaceLinkState(anyString(), anyBoolean());
doReturn(new String[0]).when(mNetd).interfaceGetList();
+ doReturn(new String[0]).when(mFactory).getAvailableInterfaces(anyBoolean());
mHandlerThread = new HandlerThread(THREAD_NAME);
mHandlerThread.start();
tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd,