Merge "Stop using PerUidCounter#transact"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 60c1f2b..495c9d7 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -41,6 +41,7 @@
"net-utils-device-common",
"net-utils-device-common-netlink",
"netd-client",
+ "NetworkStackApiCurrentShims",
],
libs: [
"framework-connectivity",
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index f652772..6e64570 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -22,7 +22,19 @@
defaults: ["framework-module-defaults"],
impl_library_visibility: [
"//packages/modules/Connectivity/Tethering:__subpackages__",
+
+ // Using for test only
+ "//cts/tests/netlegacy22.api",
+ "//external/sl4a:__subpackages__",
+ "//frameworks/base/packages/Connectivity/tests:__subpackages__",
+ "//frameworks/libs/net/common/testutils",
+ "//frameworks/libs/net/common/tests:__subpackages__",
+ "//frameworks/opt/telephony/tests/telephonytests",
+ "//packages/modules/CaptivePortalLogin/tests",
+ "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/NetworkStack/tests:__subpackages__",
+ "//packages/modules/Wifi/service/tests/wifitests",
],
srcs: [":framework-tethering-srcs"],
diff --git a/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
index cf094aa..77e78bd 100644
--- a/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
+++ b/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
@@ -49,4 +49,6 @@
void stopAllTethering(String callerPkg, String callingAttributionTag,
IIntResultListener receiver);
+
+ void setPreferTestNetworks(boolean prefer, IIntResultListener listener);
}
diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 73ab908..65b2650 100644
--- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -1538,4 +1538,25 @@
}
}));
}
+
+ /**
+ * Whether to treat networks that have TRANSPORT_TEST as Tethering upstreams. The effects of
+ * this method apply to any test networks that are already present on the system.
+ *
+ * @throws SecurityException If the caller doesn't have the NETWORK_SETTINGS permission.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void setPreferTestNetworks(final boolean prefer) {
+ Log.i(TAG, "setPreferTestNetworks caller: " + mContext.getOpPackageName());
+
+ final RequestDispatcher dispatcher = new RequestDispatcher();
+ final int ret = dispatcher.waitForResult((connector, listener) -> {
+ try {
+ connector.setPreferTestNetworks(prefer, listener);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ });
+ }
}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 08170f9..1559f3b 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -2601,4 +2601,13 @@
private static String[] copy(String[] strarray) {
return Arrays.copyOf(strarray, strarray.length);
}
+
+ void setPreferTestNetworks(final boolean prefer, IIntResultListener listener) {
+ mHandler.post(() -> {
+ mUpstreamNetworkMonitor.setPreferTestNetworks(prefer);
+ try {
+ listener.onResult(TETHER_ERROR_NO_ERROR);
+ } catch (RemoteException e) { }
+ });
+ }
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java b/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java
index ff38f71..d0a1ac3 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringInterfaceUtils.java
@@ -16,6 +16,10 @@
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
@@ -78,13 +82,17 @@
// Minimal amount of IPv6 provisioning:
&& ns.linkProperties.hasGlobalIpv6Address()
// Temporary approximation of "dedicated prefix":
- && ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
+ && allowIpv6Tethering(ns.networkCapabilities);
return canTether
? getInterfaceForDestination(ns.linkProperties, IN6ADDR_ANY)
: null;
}
+ private static boolean allowIpv6Tethering(@NonNull final NetworkCapabilities nc) {
+ return nc.hasTransport(TRANSPORT_CELLULAR) || nc.hasTransport(TRANSPORT_TEST);
+ }
+
private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) {
final RouteInfo ri = (lp != null)
? NetUtils.selectBestRoute(lp.getAllRoutes(), dst)
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index 5ab3401..9fb61fe 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -17,6 +17,7 @@
package com.android.networkstack.tethering;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -46,13 +47,14 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.networkstack.apishim.SettingsShimImpl;
+import com.android.networkstack.apishim.common.SettingsShim;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -66,6 +68,7 @@
private static final String TAG = TetheringService.class.getSimpleName();
private TetheringConnector mConnector;
+ private SettingsShim mSettingsShim;
@Override
public void onCreate() {
@@ -73,6 +76,8 @@
// The Tethering object needs a fully functional context to start, so this can't be done
// in the constructor.
mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this);
+
+ mSettingsShim = SettingsShimImpl.newInstance();
}
/**
@@ -200,6 +205,18 @@
}
@Override
+ public void setPreferTestNetworks(boolean prefer, IIntResultListener listener) {
+ if (!checkCallingOrSelfPermission(NETWORK_SETTINGS)) {
+ try {
+ listener.onResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ } catch (RemoteException e) { }
+ return;
+ }
+
+ mTethering.setPreferTestNetworks(prefer, listener);
+ }
+
+ @Override
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
@Nullable String[] args) {
mTethering.dump(fd, writer, args);
@@ -294,8 +311,8 @@
boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
@NonNull String callingPackage, @Nullable String callingAttributionTag,
boolean throwException) {
- return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
- throwException);
+ return mSettingsShim.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
+ callingAttributionTag, throwException);
}
/**
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 5584db2..5a86b84 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -135,6 +135,7 @@
private Network mDefaultInternetNetwork;
// The current upstream network used for tethering.
private Network mTetheringUpstreamNetwork;
+ private boolean mPreferTestNetworks;
public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
mContext = ctx;
@@ -325,6 +326,11 @@
final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null)
? mNetworkMap.get(mDefaultInternetNetwork)
: null;
+ if (mPreferTestNetworks) {
+ final UpstreamNetworkState testState = findFirstTestNetwork(mNetworkMap.values());
+ if (testState != null) return testState;
+ }
+
if (isNetworkUsableAndNotCellular(dfltState)) return dfltState;
if (!isCellularUpstreamPermitted()) return null;
@@ -656,6 +662,20 @@
return null;
}
+ static boolean isTestNetwork(UpstreamNetworkState ns) {
+ return ((ns != null) && (ns.networkCapabilities != null)
+ && ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_TEST));
+ }
+
+ private UpstreamNetworkState findFirstTestNetwork(
+ Iterable<UpstreamNetworkState> netStates) {
+ for (UpstreamNetworkState ns : netStates) {
+ if (isTestNetwork(ns)) return ns;
+ }
+
+ return null;
+ }
+
/**
* Given a legacy type (TYPE_WIFI, ...) returns the corresponding NetworkCapabilities instance.
* This function is used for deprecated legacy type and be disabled by default.
@@ -681,4 +701,9 @@
}
return builder.build();
}
+
+ /** Set test network as preferred upstream. */
+ public void setPreferTestNetworks(boolean prefer) {
+ mPreferTestNetworks = prefer;
+ }
}
diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp
index 2593b1b..c7f5527 100644
--- a/Tethering/tests/integration/Android.bp
+++ b/Tethering/tests/integration/Android.bp
@@ -19,6 +19,7 @@
java_defaults {
name: "TetheringIntegrationTestsDefaults",
+ defaults: ["framework-connectivity-test-defaults"],
srcs: [
"src/**/*.java",
"src/**/*.kt",
diff --git a/Tethering/tests/integration/AndroidManifest.xml b/Tethering/tests/integration/AndroidManifest.xml
index fddfaad..c89c556 100644
--- a/Tethering/tests/integration/AndroidManifest.xml
+++ b/Tethering/tests/integration/AndroidManifest.xml
@@ -17,6 +17,11 @@
package="com.android.networkstack.tethering.tests.integration">
<uses-permission android:name="android.permission.INTERNET"/>
+ <!-- The test need CHANGE_NETWORK_STATE permission to use requestNetwork API to setup test
+ network. Since R shell application don't have such permission, grant permission to the test
+ here. TODO: Remove CHANGE_NETWORK_STATE permission here and use adopt shell perssion to
+ obtain CHANGE_NETWORK_STATE for testing once R device is no longer supported. -->
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 26297a2..15f07f2 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.TETHER_PRIVILEGED;
+import static android.net.InetAddresses.parseNumericAddress;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
import static android.net.TetheringManager.TETHERING_ETHERNET;
@@ -29,6 +30,7 @@
import static com.android.net.module.util.ConnectivityUtils.isIPv6ULA;
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
+import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -45,14 +47,10 @@
import android.net.TetheringManager.StartTetheringCallback;
import android.net.TetheringManager.TetheringEventCallback;
import android.net.TetheringManager.TetheringRequest;
-import android.net.dhcp.DhcpAckPacket;
-import android.net.dhcp.DhcpOfferPacket;
-import android.net.dhcp.DhcpPacket;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.system.Os;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -65,6 +63,7 @@
import com.android.net.module.util.structs.Ipv6Header;
import com.android.testutils.HandlerUtils;
import com.android.testutils.TapPacketReader;
+import com.android.testutils.TestNetworkTracker;
import org.junit.After;
import org.junit.Before;
@@ -72,12 +71,12 @@
import org.junit.runner.RunWith;
import java.io.FileDescriptor;
-import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Random;
@@ -93,24 +92,19 @@
private static final String TAG = EthernetTetheringTest.class.getSimpleName();
private static final int TIMEOUT_MS = 5000;
- private static final int PACKET_READ_TIMEOUT_MS = 100;
- private static final int DHCP_DISCOVER_ATTEMPTS = 10;
- private static final byte[] DHCP_REQUESTED_PARAMS = new byte[] {
- DhcpPacket.DHCP_SUBNET_MASK,
- DhcpPacket.DHCP_ROUTER,
- DhcpPacket.DHCP_DNS_SERVER,
- DhcpPacket.DHCP_LEASE_TIME,
- };
- private static final String DHCP_HOSTNAME = "testhostname";
+ private static final LinkAddress TEST_IP4_ADDR = new LinkAddress("10.0.0.1/8");
+ private static final LinkAddress TEST_IP6_ADDR = new LinkAddress("2001:db8:1::101/64");
+ private static final InetAddress TEST_IP4_DNS = parseNumericAddress("8.8.8.8");
+ private static final InetAddress TEST_IP6_DNS = parseNumericAddress("2001:db8:1::888");
private final Context mContext = InstrumentationRegistry.getContext();
private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class);
private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class);
- private TestNetworkInterface mTestIface;
+ private TestNetworkInterface mDownstreamIface;
private HandlerThread mHandlerThread;
private Handler mHandler;
- private TapPacketReader mTapPacketReader;
+ private TapPacketReader mDownstreamReader;
private TetheredInterfaceRequester mTetheredInterfaceRequester;
private MyTetheringEventCallback mTetheringEventCallback;
@@ -119,6 +113,8 @@
InstrumentationRegistry.getInstrumentation().getUiAutomation();
private boolean mRunTests;
+ private TestNetworkTracker mUpstreamTracker;
+
@Before
public void setUp() throws Exception {
// Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive
@@ -138,16 +134,23 @@
}
private void cleanUp() throws Exception {
+ mTm.setPreferTestNetworks(false);
+
+ if (mUpstreamTracker != null) {
+ mUpstreamTracker.teardown();
+ mUpstreamTracker = null;
+ }
+
mTm.stopTethering(TETHERING_ETHERNET);
if (mTetheringEventCallback != null) {
mTetheringEventCallback.awaitInterfaceUntethered();
mTetheringEventCallback.unregister();
mTetheringEventCallback = null;
}
- if (mTapPacketReader != null) {
- TapPacketReader reader = mTapPacketReader;
+ if (mDownstreamReader != null) {
+ TapPacketReader reader = mDownstreamReader;
mHandler.post(() -> reader.stop());
- mTapPacketReader = null;
+ mDownstreamReader = null;
}
mHandlerThread.quitSafely();
mTetheredInterfaceRequester.release();
@@ -169,21 +172,21 @@
// This test requires manipulating packets. Skip if there is a physical Ethernet connected.
assumeFalse(mEm.isAvailable());
- mTestIface = createTestInterface();
+ mDownstreamIface = createTestInterface();
// This must be done now because as soon as setIncludeTestInterfaces(true) is called, the
// interface will be placed in client mode, which will delete the link-local address.
// At that point NetworkInterface.getByName() will cease to work on the interface, because
// starting in R NetworkInterface can no longer see interfaces without IP addresses.
- int mtu = getMTU(mTestIface);
+ int mtu = getMTU(mDownstreamIface);
Log.d(TAG, "Including test interfaces");
mEm.setIncludeTestInterfaces(true);
final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
+ mDownstreamIface.getInterfaceName(), iface);
- checkVirtualEthernet(mTestIface, mtu);
+ checkVirtualEthernet(mDownstreamIface, mtu);
}
@Test
@@ -195,13 +198,13 @@
mEm.setIncludeTestInterfaces(true);
- mTestIface = createTestInterface();
+ mDownstreamIface = createTestInterface();
final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
+ mDownstreamIface.getInterfaceName(), iface);
- checkVirtualEthernet(mTestIface, getMTU(mTestIface));
+ checkVirtualEthernet(mDownstreamIface, getMTU(mDownstreamIface));
}
@Test
@@ -210,11 +213,11 @@
mEm.setIncludeTestInterfaces(true);
- mTestIface = createTestInterface();
+ mDownstreamIface = createTestInterface();
final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
+ mDownstreamIface.getInterfaceName(), iface);
assertInvalidStaticIpv4Request(iface, null, null);
assertInvalidStaticIpv4Request(iface, "2001:db8::1/64", "2001:db8:2::/64");
@@ -235,13 +238,14 @@
byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray();
byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray();
- FileDescriptor fd = mTestIface.getFileDescriptor().getFileDescriptor();
- mTapPacketReader = makePacketReader(fd, getMTU(mTestIface));
- DhcpResults dhcpResults = runDhcp(fd, client1);
+ FileDescriptor fd = mDownstreamIface.getFileDescriptor().getFileDescriptor();
+ mDownstreamReader = makePacketReader(fd, getMTU(mDownstreamIface));
+ TetheringTester tester = new TetheringTester(mDownstreamReader);
+ DhcpResults dhcpResults = tester.runDhcp(client1);
assertEquals(new LinkAddress(clientAddr), dhcpResults.ipAddress);
try {
- runDhcp(fd, client2);
+ tester.runDhcp(client2);
fail("Only one client should get an IP address");
} catch (TimeoutException expected) { }
@@ -301,11 +305,11 @@
mEm.setIncludeTestInterfaces(true);
- mTestIface = createTestInterface();
+ mDownstreamIface = createTestInterface();
final String iface = mTetheredInterfaceRequester.getInterface();
assertEquals("TetheredInterfaceCallback for unexpected interface",
- mTestIface.getInterfaceName(), iface);
+ mDownstreamIface.getInterfaceName(), iface);
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_ETHERNET)
.setConnectivityScope(CONNECTIVITY_SCOPE_LOCAL).build();
@@ -316,10 +320,9 @@
// does not have an IP address, and unprivileged apps cannot see interfaces without IP
// addresses. This shouldn't be flaky because the TAP interface will buffer all packets even
// before the reader is started.
- FileDescriptor fd = mTestIface.getFileDescriptor().getFileDescriptor();
- mTapPacketReader = makePacketReader(fd, getMTU(mTestIface));
+ mDownstreamReader = makePacketReader(mDownstreamIface);
- expectRouterAdvertisement(mTapPacketReader, iface, 2000 /* timeoutMs */);
+ expectRouterAdvertisement(mDownstreamReader, iface, 2000 /* timeoutMs */);
expectLocalOnlyAddresses(iface);
}
@@ -354,12 +357,14 @@
private final CountDownLatch mLocalOnlyStartedLatch = new CountDownLatch(1);
private final CountDownLatch mLocalOnlyStoppedLatch = new CountDownLatch(1);
private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1);
+ private final CountDownLatch mUpstreamConnectedLatch = new CountDownLatch(1);
private final TetheringInterface mIface;
private volatile boolean mInterfaceWasTethered = false;
private volatile boolean mInterfaceWasLocalOnly = false;
private volatile boolean mUnregistered = false;
private volatile Collection<TetheredClient> mClients = null;
+ private volatile Network mUpstream = null;
MyTetheringEventCallback(TetheringManager tm, String iface) {
mTm = tm;
@@ -465,6 +470,22 @@
mClientConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
return mClients;
}
+
+ @Override
+ public void onUpstreamChanged(Network network) {
+ // Ignore stale callbacks registered by previous test cases.
+ if (mUnregistered) return;
+
+ Log.d(TAG, "Got upstream changed: " + network);
+ mUpstream = network;
+ if (mUpstream != null) mUpstreamConnectedLatch.countDown();
+ }
+
+ public Network awaitFirstUpstreamConnected() throws Exception {
+ assertTrue("Did not receive upstream connected callback after " + TIMEOUT_MS + "ms",
+ mUpstreamConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ return mUpstream;
+ }
}
private MyTetheringEventCallback enableEthernetTethering(String iface,
@@ -508,6 +529,11 @@
return nif.getMTU();
}
+ private TapPacketReader makePacketReader(final TestNetworkInterface iface) throws Exception {
+ FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor();
+ return makePacketReader(fd, getMTU(iface));
+ }
+
private TapPacketReader makePacketReader(FileDescriptor fd, int mtu) {
final TapPacketReader reader = new TapPacketReader(mHandler, fd, mtu);
mHandler.post(() -> reader.start());
@@ -517,40 +543,18 @@
private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception {
FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor();
- mTapPacketReader = makePacketReader(fd, mtu);
+ mDownstreamReader = makePacketReader(fd, mtu);
mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName());
- checkTetheredClientCallbacks(fd);
+ checkTetheredClientCallbacks(mDownstreamReader);
}
- private DhcpResults runDhcp(FileDescriptor fd, byte[] clientMacAddr) throws Exception {
- // We have to retransmit DHCP requests because IpServer declares itself to be ready before
- // its DhcpServer is actually started. TODO: fix this race and remove this loop.
- DhcpPacket offerPacket = null;
- for (int i = 0; i < DHCP_DISCOVER_ATTEMPTS; i++) {
- Log.d(TAG, "Sending DHCP discover");
- sendDhcpDiscover(fd, clientMacAddr);
- offerPacket = getNextDhcpPacket();
- if (offerPacket instanceof DhcpOfferPacket) break;
- }
- if (!(offerPacket instanceof DhcpOfferPacket)) {
- throw new TimeoutException("No DHCPOFFER received on interface within timeout");
- }
-
- sendDhcpRequest(fd, offerPacket, clientMacAddr);
- DhcpPacket ackPacket = getNextDhcpPacket();
- if (!(ackPacket instanceof DhcpAckPacket)) {
- throw new TimeoutException("No DHCPACK received on interface within timeout");
- }
-
- return ackPacket.toDhcpResults();
- }
-
- private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception {
+ private void checkTetheredClientCallbacks(TapPacketReader packetReader) throws Exception {
// Create a fake client.
byte[] clientMacAddr = new byte[6];
new Random().nextBytes(clientMacAddr);
- DhcpResults dhcpResults = runDhcp(fd, clientMacAddr);
+ TetheringTester tester = new TetheringTester(packetReader);
+ DhcpResults dhcpResults = tester.runDhcp(clientMacAddr);
final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected();
assertEquals(1, clients.size());
@@ -563,7 +567,7 @@
// Check the hostname.
assertEquals(1, client.getAddresses().size());
TetheredClient.AddressInfo info = client.getAddresses().get(0);
- assertEquals(DHCP_HOSTNAME, info.getHostname());
+ assertEquals(TetheringTester.DHCP_HOSTNAME, info.getHostname());
// Check the address is the one that was handed out in the DHCP ACK.
assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress());
@@ -576,18 +580,6 @@
assertTrue(msg, Math.abs(dhcpResults.leaseDuration - actualLeaseDuration) < 10);
}
- private DhcpPacket getNextDhcpPacket() throws ParseException {
- byte[] packet;
- while ((packet = mTapPacketReader.popPacket(PACKET_READ_TIMEOUT_MS)) != null) {
- try {
- return DhcpPacket.decodeFullPacket(packet, packet.length, DhcpPacket.ENCAP_L2);
- } catch (DhcpPacket.ParseException e) {
- // Not a DHCP packet. Continue.
- }
- }
- return null;
- }
-
private static final class TetheredInterfaceRequester implements TetheredInterfaceCallback {
private final Handler mHandler;
private final EthernetManager mEm;
@@ -631,31 +623,6 @@
}
}
- private void sendDhcpDiscover(FileDescriptor fd, byte[] macAddress) throws Exception {
- ByteBuffer packet = DhcpPacket.buildDiscoverPacket(DhcpPacket.ENCAP_L2,
- new Random().nextInt() /* transactionId */, (short) 0 /* secs */,
- macAddress, false /* unicast */, DHCP_REQUESTED_PARAMS,
- false /* rapid commit */, DHCP_HOSTNAME);
- sendPacket(fd, packet);
- }
-
- private void sendDhcpRequest(FileDescriptor fd, DhcpPacket offerPacket, byte[] macAddress)
- throws Exception {
- DhcpResults results = offerPacket.toDhcpResults();
- Inet4Address clientIp = (Inet4Address) results.ipAddress.getAddress();
- Inet4Address serverIdentifier = results.serverAddress;
- ByteBuffer packet = DhcpPacket.buildRequestPacket(DhcpPacket.ENCAP_L2,
- 0 /* transactionId */, (short) 0 /* secs */, DhcpPacket.INADDR_ANY /* clientIp */,
- false /* broadcast */, macAddress, clientIp /* requestedIpAddress */,
- serverIdentifier, DHCP_REQUESTED_PARAMS, DHCP_HOSTNAME);
- sendPacket(fd, packet);
- }
-
- private void sendPacket(FileDescriptor fd, ByteBuffer packet) throws Exception {
- assertNotNull("Only tests on virtual interfaces can send packets", fd);
- Os.write(fd, packet);
- }
-
public void assertLinkAddressMatches(LinkAddress l1, LinkAddress l2) {
// Check all fields except the deprecation and expiry times.
String msg = String.format("LinkAddresses do not match. expected: %s actual: %s", l1, l2);
@@ -701,10 +668,45 @@
}
private void maybeDeleteTestInterface() throws Exception {
- if (mTestIface != null) {
- mTestIface.getFileDescriptor().close();
- Log.d(TAG, "Deleted test interface " + mTestIface.getInterfaceName());
- mTestIface = null;
+ if (mDownstreamIface != null) {
+ mDownstreamIface.getFileDescriptor().close();
+ Log.d(TAG, "Deleted test interface " + mDownstreamIface.getInterfaceName());
+ mDownstreamIface = null;
}
}
+
+ private TestNetworkTracker createTestUpstream(final List<LinkAddress> addresses)
+ throws Exception {
+ mTm.setPreferTestNetworks(true);
+
+ return initTestNetwork(mContext, addresses, TIMEOUT_MS);
+ }
+
+ @Test
+ public void testTestNetworkUpstream() throws Exception {
+ assumeFalse(mEm.isAvailable());
+
+ // MyTetheringEventCallback currently only support await first available upstream. Tethering
+ // may select internet network as upstream if test network is not available and not be
+ // preferred yet. Create test upstream network before enable tethering.
+ mUpstreamTracker = createTestUpstream(toList(TEST_IP4_ADDR, TEST_IP6_ADDR));
+
+ mDownstreamIface = createTestInterface();
+ mEm.setIncludeTestInterfaces(true);
+
+ final String iface = mTetheredInterfaceRequester.getInterface();
+ assertEquals("TetheredInterfaceCallback for unexpected interface",
+ mDownstreamIface.getInterfaceName(), iface);
+
+ mTetheringEventCallback = enableEthernetTethering(mDownstreamIface.getInterfaceName());
+ assertEquals("onUpstreamChanged for unexpected network", mUpstreamTracker.getNetwork(),
+ mTetheringEventCallback.awaitFirstUpstreamConnected());
+
+ mDownstreamReader = makePacketReader(mDownstreamIface);
+ // TODO: do basic forwarding test here.
+ }
+
+ private <T> List<T> toList(T... array) {
+ return Arrays.asList(array);
+ }
}
diff --git a/Tethering/tests/integration/src/android/net/TetheringTester.java b/Tethering/tests/integration/src/android/net/TetheringTester.java
new file mode 100644
index 0000000..38d74ad
--- /dev/null
+++ b/Tethering/tests/integration/src/android/net/TetheringTester.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static org.junit.Assert.fail;
+
+import android.net.dhcp.DhcpAckPacket;
+import android.net.dhcp.DhcpOfferPacket;
+import android.net.dhcp.DhcpPacket;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.testutils.TapPacketReader;
+
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+import java.util.Random;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
+
+/**
+ * A class simulate tethered client. When caller create TetheringTester, it would connect to
+ * tethering module that do the dhcp and slaac to obtain ipv4 and ipv6 address. Then caller can
+ * send/receive packets by this class.
+ */
+public final class TetheringTester {
+ private static final String TAG = TetheringTester.class.getSimpleName();
+ private static final int PACKET_READ_TIMEOUT_MS = 100;
+ private static final int DHCP_DISCOVER_ATTEMPTS = 10;
+ private static final byte[] DHCP_REQUESTED_PARAMS = new byte[] {
+ DhcpPacket.DHCP_SUBNET_MASK,
+ DhcpPacket.DHCP_ROUTER,
+ DhcpPacket.DHCP_DNS_SERVER,
+ DhcpPacket.DHCP_LEASE_TIME,
+ };
+
+ public static final String DHCP_HOSTNAME = "testhostname";
+
+ private final ArrayMap<MacAddress, TetheredDevice> mTetheredDevices;
+ private final TapPacketReader mDownstreamReader;
+
+ public TetheringTester(TapPacketReader downstream) {
+ if (downstream == null) fail("Downstream reader could not be NULL");
+
+ mDownstreamReader = downstream;
+ mTetheredDevices = new ArrayMap<>();
+ }
+
+ public TetheredDevice createTetheredDevice(MacAddress macAddr) throws Exception {
+ if (mTetheredDevices.get(macAddr) != null) {
+ fail("Tethered device already created");
+ }
+
+ TetheredDevice tethered = new TetheredDevice(macAddr);
+ mTetheredDevices.put(macAddr, tethered);
+
+ return tethered;
+ }
+
+ public class TetheredDevice {
+ private final MacAddress mMacAddr;
+
+ public final Inet4Address mIpv4Addr;
+
+ private TetheredDevice(MacAddress mac) throws Exception {
+ mMacAddr = mac;
+
+ DhcpResults dhcpResults = runDhcp(mMacAddr.toByteArray());
+ mIpv4Addr = (Inet4Address) dhcpResults.ipAddress.getAddress();
+ }
+ }
+
+ /** Simulate dhcp client to obtain ipv4 address. */
+ public DhcpResults runDhcp(byte[] clientMacAddr)
+ throws Exception {
+ // We have to retransmit DHCP requests because IpServer declares itself to be ready before
+ // its DhcpServer is actually started. TODO: fix this race and remove this loop.
+ DhcpPacket offerPacket = null;
+ for (int i = 0; i < DHCP_DISCOVER_ATTEMPTS; i++) {
+ Log.d(TAG, "Sending DHCP discover");
+ sendDhcpDiscover(clientMacAddr);
+ offerPacket = getNextDhcpPacket();
+ if (offerPacket instanceof DhcpOfferPacket) break;
+ }
+ if (!(offerPacket instanceof DhcpOfferPacket)) {
+ throw new TimeoutException("No DHCPOFFER received on interface within timeout");
+ }
+
+ sendDhcpRequest(offerPacket, clientMacAddr);
+ DhcpPacket ackPacket = getNextDhcpPacket();
+ if (!(ackPacket instanceof DhcpAckPacket)) {
+ throw new TimeoutException("No DHCPACK received on interface within timeout");
+ }
+
+ return ackPacket.toDhcpResults();
+ }
+
+ private void sendDhcpDiscover(byte[] macAddress) throws Exception {
+ ByteBuffer packet = DhcpPacket.buildDiscoverPacket(DhcpPacket.ENCAP_L2,
+ new Random().nextInt() /* transactionId */, (short) 0 /* secs */,
+ macAddress, false /* unicast */, DHCP_REQUESTED_PARAMS,
+ false /* rapid commit */, DHCP_HOSTNAME);
+ mDownstreamReader.sendResponse(packet);
+ }
+
+ private void sendDhcpRequest(DhcpPacket offerPacket, byte[] macAddress)
+ throws Exception {
+ DhcpResults results = offerPacket.toDhcpResults();
+ Inet4Address clientIp = (Inet4Address) results.ipAddress.getAddress();
+ Inet4Address serverIdentifier = results.serverAddress;
+ ByteBuffer packet = DhcpPacket.buildRequestPacket(DhcpPacket.ENCAP_L2,
+ 0 /* transactionId */, (short) 0 /* secs */, DhcpPacket.INADDR_ANY /* clientIp */,
+ false /* broadcast */, macAddress, clientIp /* requestedIpAddress */,
+ serverIdentifier, DHCP_REQUESTED_PARAMS, DHCP_HOSTNAME);
+ mDownstreamReader.sendResponse(packet);
+ }
+
+ private DhcpPacket getNextDhcpPacket() {
+ return getNextMatchedPacket((p) -> {
+ try {
+ return DhcpPacket.decodeFullPacket(p, p.length, DhcpPacket.ENCAP_L2);
+ } catch (DhcpPacket.ParseException e) {
+ // Not a DHCP packet. Continue.
+ }
+
+ return null;
+ });
+ }
+
+ private <R> R getNextMatchedPacket(Function<byte[], R> match) {
+ byte[] packet;
+ R result;
+ while ((packet = mDownstreamReader.popPacket(PACKET_READ_TIMEOUT_MS)) != null) {
+ result = match.apply(packet);
+
+ if (result != null) return result;
+ }
+
+ return null;
+ }
+}
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 7294ec9..4f10abc 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -1163,10 +1163,11 @@
* default data network. In the event that the current active default data
* network disconnects, the returned {@code Network} object will no longer
* be usable. This will return {@code null} when there is no default
- * network.
+ * network, or when the default network is blocked.
*
* @return a {@link Network} object for the current default network or
- * {@code null} if no default network is currently active
+ * {@code null} if no default network is currently active or if
+ * the default network is blocked for the caller
*/
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
@Nullable
@@ -2326,6 +2327,7 @@
void onNetworkActive();
}
+ @GuardedBy("mNetworkActivityListeners")
private final ArrayMap<OnNetworkActiveListener, INetworkActivityListener>
mNetworkActivityListeners = new ArrayMap<>();
@@ -2342,18 +2344,20 @@
* @param l The listener to be told when the network is active.
*/
public void addDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
- INetworkActivityListener rl = new INetworkActivityListener.Stub() {
+ final INetworkActivityListener rl = new INetworkActivityListener.Stub() {
@Override
public void onNetworkActive() throws RemoteException {
l.onNetworkActive();
}
};
- try {
- mService.registerNetworkActivityListener(rl);
- mNetworkActivityListeners.put(l, rl);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ synchronized (mNetworkActivityListeners) {
+ try {
+ mService.registerNetworkActivityListener(rl);
+ mNetworkActivityListeners.put(l, rl);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
}
@@ -2364,14 +2368,17 @@
* @param l Previously registered listener.
*/
public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) {
- INetworkActivityListener rl = mNetworkActivityListeners.get(l);
- if (rl == null) {
- throw new IllegalArgumentException("Listener was not registered.");
- }
- try {
- mService.unregisterNetworkActivityListener(rl);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ synchronized (mNetworkActivityListeners) {
+ final INetworkActivityListener rl = mNetworkActivityListeners.get(l);
+ if (rl == null) {
+ throw new IllegalArgumentException("Listener was not registered.");
+ }
+ try {
+ mService.unregisterNetworkActivityListener(rl);
+ mNetworkActivityListeners.remove(l);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 33b08c2..39fb349 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -2985,9 +2985,9 @@
}
pw.println();
- pw.print("Current per-app default networks: ");
+ pw.println("Current network preferences: ");
pw.increaseIndent();
- dumpPerAppNetworkPreferences(pw);
+ dumpNetworkPreferences(pw);
pw.decreaseIndent();
pw.println();
@@ -3115,37 +3115,55 @@
}
}
- private void dumpPerAppNetworkPreferences(IndentingPrintWriter pw) {
- pw.println("Per-App Network Preference:");
- pw.increaseIndent();
- if (0 == mOemNetworkPreferences.getNetworkPreferences().size()) {
- pw.println("none");
- } else {
- pw.println(mOemNetworkPreferences.toString());
+ private void dumpNetworkPreferences(IndentingPrintWriter pw) {
+ if (!mProfileNetworkPreferences.isEmpty()) {
+ pw.println("Profile preferences:");
+ pw.increaseIndent();
+ pw.println(mProfileNetworkPreferences.preferences);
+ pw.decreaseIndent();
}
- pw.decreaseIndent();
+ if (!mOemNetworkPreferences.isEmpty()) {
+ pw.println("OEM preferences:");
+ pw.increaseIndent();
+ pw.println(mOemNetworkPreferences);
+ pw.decreaseIndent();
+ }
+ if (!mMobileDataPreferredUids.isEmpty()) {
+ pw.println("Mobile data preferred UIDs:");
+ pw.increaseIndent();
+ pw.println(mMobileDataPreferredUids);
+ pw.decreaseIndent();
+ }
+ pw.println("Default requests:");
+ pw.increaseIndent();
+ dumpPerAppDefaultRequests(pw);
+ pw.decreaseIndent();
+ }
+
+ private void dumpPerAppDefaultRequests(IndentingPrintWriter pw) {
for (final NetworkRequestInfo defaultRequest : mDefaultNetworkRequests) {
if (mDefaultRequest == defaultRequest) {
continue;
}
- final boolean isActive = null != defaultRequest.getSatisfier();
- pw.println("Is per-app network active:");
- pw.increaseIndent();
- pw.println(isActive);
- if (isActive) {
- pw.println("Active network: " + defaultRequest.getSatisfier().network.netId);
- }
- pw.println("Tracked UIDs:");
- pw.increaseIndent();
- if (0 == defaultRequest.mRequests.size()) {
- pw.println("none, this should never occur.");
+ final NetworkAgentInfo satisfier = defaultRequest.getSatisfier();
+ final String networkOutput;
+ if (null == satisfier) {
+ networkOutput = "null";
+ } else if (mNoServiceNetwork.equals(satisfier)) {
+ networkOutput = "no service network";
} else {
- pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUidRanges());
+ networkOutput = String.valueOf(satisfier.network.netId);
}
- pw.decreaseIndent();
- pw.decreaseIndent();
+ final String asUidString = (defaultRequest.mAsUid == defaultRequest.mUid)
+ ? "" : " asUid: " + defaultRequest.mAsUid;
+ final String requestInfo = "Request: [uid/pid:" + defaultRequest.mUid + "/"
+ + defaultRequest.mPid + asUidString + "]";
+ final String satisfierOutput = "Satisfier: [" + networkOutput + "]"
+ + " Preference order: " + defaultRequest.mPreferenceOrder
+ + " Tracked UIDs: " + defaultRequest.getUids();
+ pw.println(requestInfo + " - " + satisfierOutput);
}
}
@@ -3819,9 +3837,7 @@
private void handleNetworkAgentDisconnected(Message msg) {
NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
- if (mNetworkAgentInfos.contains(nai)) {
- disconnectAndDestroyNetwork(nai);
- }
+ disconnectAndDestroyNetwork(nai);
}
// Destroys a network, remove references to it from the internal state managed by
@@ -3829,6 +3845,9 @@
// Must be called on the Handler thread.
private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) {
ensureRunningOnConnectivityServiceThread();
+
+ if (!mNetworkAgentInfos.contains(nai)) return;
+
if (DBG) {
log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests());
}
@@ -3914,7 +3933,7 @@
try {
mNetd.networkSetPermissionForNetwork(nai.network.netId, INetd.PERMISSION_SYSTEM);
} catch (RemoteException e) {
- Log.d(TAG, "Error marking network restricted during teardown: " + e);
+ Log.d(TAG, "Error marking network restricted during teardown: ", e);
}
mHandler.postDelayed(() -> destroyNetwork(nai), nai.teardownDelayMs);
}
@@ -6869,7 +6888,11 @@
if (DBG) {
log("unregister offer from providerId " + noi.offer.providerId + " : " + noi.offer);
}
- mNetworkOffers.remove(noi);
+
+ // If the provider removes the offer and dies immediately afterwards this
+ // function may be called twice in a row, but the array will no longer contain
+ // the offer.
+ if (!mNetworkOffers.remove(noi)) return;
noi.offer.callback.asBinder().unlinkToDeath(noi, 0 /* flags */);
}
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index f596c4a..4c6b669 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -222,6 +222,10 @@
mIntentReceiver, intentFilter, null /* broadcastPermission */,
null /* scheduler */);
+ // Listen to EXTERNAL_APPLICATIONS_AVAILABLE is that an app becoming available means it may
+ // need to gain a permission. But an app that becomes unavailable can neither gain nor lose
+ // permissions on that account, it just can no longer run. Thus, doesn't need to listen to
+ // EXTERNAL_APPLICATIONS_UNAVAILABLE.
final IntentFilter externalIntentFilter =
new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
userAllContext.registerReceiver(
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index e1fab09..9b136d5 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -115,6 +115,7 @@
// meaning @hide APIs in framework-connectivity are resolved before @SystemApi
// stubs in framework
"framework-connectivity.impl",
+ "framework-tethering.impl",
"framework",
// if sdk_version="" this gets automatically included, but here we need to add manually.
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index f5c43d6..199244f 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -75,6 +75,7 @@
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
+import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static com.android.testutils.TestPermissionUtil.runAsShell;
@@ -236,6 +237,7 @@
private static final int MIN_KEEPALIVE_INTERVAL = 10;
private static final int NETWORK_CALLBACK_TIMEOUT_MS = 30_000;
+ private static final int LISTEN_ACTIVITY_TIMEOUT_MS = 5_000;
private static final int NO_CALLBACK_TIMEOUT_MS = 100;
private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20;
private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500;
@@ -278,6 +280,7 @@
private ConnectivityManagerShim mCmShim;
private WifiManager mWifiManager;
private PackageManager mPackageManager;
+ private TelephonyManager mTm;
private final ArraySet<Integer> mNetworkTypes = new ArraySet<>();
private UiAutomation mUiAutomation;
private CtsNetUtils mCtsNetUtils;
@@ -297,6 +300,7 @@
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mPackageManager = mContext.getPackageManager();
mCtsNetUtils = new CtsNetUtils(mContext);
+ mTm = mContext.getSystemService(TelephonyManager.class);
if (DevSdkIgnoreRuleKt.isDevSdkInRange(null /* minExclusive */,
Build.VERSION_CODES.R /* maxInclusive */)) {
@@ -2793,6 +2797,36 @@
System.currentTimeMillis() + WIFI_CONNECT_TIMEOUT_MS);
}
+ @AppModeFull(reason = "Need WiFi support to test the default active network")
+ @Test
+ public void testDefaultNetworkActiveListener() throws Exception {
+ final boolean supportWifi = mPackageManager.hasSystemFeature(FEATURE_WIFI);
+ final boolean supportTelephony = mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
+ assumeTrue("testDefaultNetworkActiveListener cannot execute"
+ + " unless device supports WiFi or telephony", (supportWifi || supportTelephony));
+
+ if (supportWifi) {
+ mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
+ } else {
+ mCtsNetUtils.disconnectFromCell();
+ }
+
+ final CompletableFuture<Boolean> future = new CompletableFuture<>();
+ final ConnectivityManager.OnNetworkActiveListener listener = () -> future.complete(true);
+ mCm.addDefaultNetworkActiveListener(listener);
+ testAndCleanup(() -> {
+ // New default network connected will trigger a network activity notification.
+ if (supportWifi) {
+ mCtsNetUtils.ensureWifiConnected();
+ } else {
+ mCtsNetUtils.connectToCell();
+ }
+ assertTrue(future.get(LISTEN_ACTIVITY_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }, () -> {
+ mCm.removeDefaultNetworkActiveListener(listener);
+ });
+ }
+
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testMobileDataPreferredUids() throws Exception {
diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
index fd0cd18..7d9a24b 100644
--- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -582,6 +582,9 @@
}
if (mOldPrivateDnsMode != ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {
+ // Also restore hostname even if the value is not used since private dns is not in
+ // the strict mode to prevent setting being changed after test.
+ ConnectivitySettingsUtils.setPrivateDnsHostname(mContext, mOldPrivateDnsSpecifier);
ConnectivitySettingsUtils.setPrivateDnsMode(mContext, mOldPrivateDnsMode);
return;
}
diff --git a/tests/deflake/Android.bp b/tests/deflake/Android.bp
index 806f805..8205f1c 100644
--- a/tests/deflake/Android.bp
+++ b/tests/deflake/Android.bp
@@ -19,8 +19,17 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+// FrameworksNetDeflakeTest depends on FrameworksNetTests so it should be disabled
+// if FrameworksNetTests is disabled.
+enable_frameworks_net_deflake_test = true
+// Placeholder
+// This is a placeholder comment to minimize merge conflicts, as enable_frameworks_net_deflake_test
+// may have different values depending on the branch
+// Placeholder
+
java_test_host {
name: "FrameworksNetDeflakeTest",
+ enabled: enable_frameworks_net_deflake_test,
srcs: ["src/**/*.kt"],
libs: [
"junit",
@@ -32,4 +41,14 @@
],
data: [":FrameworksNetTests"],
test_suites: ["device-tests"],
+ // It will get build error if just set enabled to true. It fails with "windows_common"
+ // depends on some disabled modules that are used by this test and it looks like set
+ // enable_frameworks_net_deflake_test to true also enables "windows" variant. Thus,
+ // disable this on target windows.
+ // TODO: Remove this when b/201754360 is fixed.
+ target: {
+ windows: {
+ enabled: false,
+ },
+ },
}
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 7b23255..e2ea661 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -6,6 +6,15 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+// Whether to enable the FrameworksNetTests. Set to false in the branches that might have older
+// frameworks/base since FrameworksNetTests includes the test for classes that are not in
+// connectivity module.
+enable_frameworks_net_tests = true
+// Placeholder
+// This is a placeholder comment to minimize merge conflicts, as enable_frameworks_net_tests
+// may have different values depending on the branch
+// Placeholder
+
java_defaults {
name: "FrameworksNetTests-jni-defaults",
jni_libs: [
@@ -44,6 +53,42 @@
],
}
+filegroup {
+ name: "non-connectivity-module-test",
+ srcs: [
+ "java/android/app/usage/*.java",
+ "java/android/net/Ikev2VpnProfileTest.java",
+ "java/android/net/IpMemoryStoreTest.java",
+ "java/android/net/IpSecAlgorithmTest.java",
+ "java/android/net/IpSecConfigTest.java",
+ "java/android/net/IpSecManagerTest.java",
+ "java/android/net/IpSecTransformTest.java",
+ "java/android/net/KeepalivePacketDataUtilTest.java",
+ "java/android/net/NetworkIdentityTest.kt",
+ "java/android/net/NetworkStatsTest.java",
+ "java/android/net/NetworkStatsHistoryTest.java",
+ "java/android/net/NetworkTemplateTest.kt",
+ "java/android/net/TelephonyNetworkSpecifierTest.java",
+ "java/android/net/VpnManagerTest.java",
+ "java/android/net/ipmemorystore/*.java",
+ "java/android/net/nsd/*.java",
+ "java/com/android/internal/net/NetworkUtilsInternalTest.java",
+ "java/com/android/internal/net/VpnProfileTest.java",
+ "java/com/android/server/IpSecServiceParameterizedTest.java",
+ "java/com/android/server/IpSecServiceRefcountedResourceTest.java",
+ "java/com/android/server/IpSecServiceTest.java",
+ "java/com/android/server/NetworkManagementServiceTest.java",
+ "java/com/android/server/NsdServiceTest.java",
+ "java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java",
+ "java/com/android/server/connectivity/IpConnectivityMetricsTest.java",
+ "java/com/android/server/connectivity/MultipathPolicyTrackerTest.java",
+ "java/com/android/server/connectivity/NetdEventListenerServiceTest.java",
+ "java/com/android/server/connectivity/VpnTest.java",
+ "java/com/android/server/net/ipmemorystore/*.java",
+ "java/com/android/server/net/NetworkStats*.java",
+ ]
+}
+
android_library {
name: "FrameworksNetTestsLib",
min_sdk_version: "30",
@@ -54,6 +99,7 @@
"java/**/*.java",
"java/**/*.kt",
],
+ exclude_srcs: [":non-connectivity-module-test"],
jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
@@ -66,6 +112,7 @@
"framework-protos",
"mockito-target-minus-junit4",
"net-tests-utils",
+ "platform-compat-test-rules",
"platform-test-annotations",
"service-connectivity-pre-jarjar",
"services.core",
@@ -83,15 +130,22 @@
android_test {
name: "FrameworksNetTests",
+ enabled: enable_frameworks_net_tests,
min_sdk_version: "30",
defaults: [
"framework-connectivity-test-defaults",
"FrameworksNetTests-jni-defaults",
],
+ // this is in addition to FrameworksNetTestsLib.
+ srcs: [":non-connectivity-module-test"],
test_suites: ["device-tests"],
static_libs: [
"FrameworksNetTestsLib",
],
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ ],
jni_libs: [
"libservice-connectivity",
]
diff --git a/tests/unit/java/android/net/ConnectivityManagerTest.java b/tests/unit/java/android/net/ConnectivityManagerTest.java
index e7873af..f324630 100644
--- a/tests/unit/java/android/net/ConnectivityManagerTest.java
+++ b/tests/unit/java/android/net/ConnectivityManagerTest.java
@@ -37,6 +37,8 @@
import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
+import static com.android.testutils.MiscAsserts.assertThrows;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -45,6 +47,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
@@ -83,6 +86,8 @@
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
public class ConnectivityManagerTest {
+ private static final int TIMEOUT_MS = 30_000;
+ private static final int SHORT_TIMEOUT_MS = 150;
@Mock Context mCtx;
@Mock IConnectivityManager mService;
@@ -231,7 +236,7 @@
// callback triggers
captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
- verify(callback, timeout(500).times(1)).onAvailable(any(Network.class),
+ verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
// unregister callback
@@ -240,7 +245,7 @@
// callback does not trigger anymore.
captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_LOSING));
- verify(callback, timeout(500).times(0)).onLosing(any(), anyInt());
+ verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
}
@Test
@@ -260,7 +265,7 @@
// callback triggers
captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
- verify(callback, timeout(100).times(1)).onAvailable(any(Network.class),
+ verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
// unregister callback
@@ -269,7 +274,7 @@
// callback does not trigger anymore.
captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_LOSING));
- verify(callback, timeout(100).times(0)).onLosing(any(), anyInt());
+ verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
// callback can be registered again
when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
@@ -278,7 +283,7 @@
// callback triggers
captor.getValue().send(makeMessage(req2, ConnectivityManager.CALLBACK_LOST));
- verify(callback, timeout(100).times(1)).onLost(any());
+ verify(callback, timeout(TIMEOUT_MS).times(1)).onLost(any());
// unregister callback
manager.unregisterNetworkCallback(callback);
@@ -314,6 +319,21 @@
}
@Test
+ public void testDefaultNetworkActiveListener() throws Exception {
+ final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+ final ConnectivityManager.OnNetworkActiveListener listener =
+ mock(ConnectivityManager.OnNetworkActiveListener.class);
+ assertThrows(IllegalArgumentException.class,
+ () -> manager.removeDefaultNetworkActiveListener(listener));
+ manager.addDefaultNetworkActiveListener(listener);
+ verify(mService, times(1)).registerNetworkActivityListener(any());
+ manager.removeDefaultNetworkActiveListener(listener);
+ verify(mService, times(1)).unregisterNetworkActivityListener(any());
+ assertThrows(IllegalArgumentException.class,
+ () -> manager.removeDefaultNetworkActiveListener(listener));
+ }
+
+ @Test
public void testArgumentValidation() throws Exception {
ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 31c8927..de77d23 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -16,6 +16,9 @@
package android.net.nsd;
+import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
@@ -27,6 +30,7 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -44,7 +48,9 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -56,6 +62,9 @@
static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD;
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
@Mock Context mContext;
@Mock INsdManager mService;
MockServiceHandler mServiceHandler;
@@ -70,8 +79,6 @@
mServiceHandler = spy(MockServiceHandler.create(mContext));
doReturn(new Messenger(mServiceHandler)).when(mService).getMessenger();
-
- mManager = makeManager();
}
@After
@@ -85,7 +92,76 @@
}
@Test
- public void testResolveService() {
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testResolveServiceS() {
+ mManager = makeNsdManagerS();
+ doTestResolveService();
+ }
+
+ @Test
+ @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testResolveServicePreS() {
+ mManager = makeNsdManagerPreS();
+ doTestResolveService();
+ }
+
+ @Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testDiscoverServiceS() {
+ mManager = makeNsdManagerS();
+ doTestDiscoverService();
+ }
+
+ @Test
+ @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testDiscoverServicePreS() {
+ mManager = makeNsdManagerPreS();
+ doTestDiscoverService();
+ }
+
+ @Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testParallelResolveServiceS() {
+ mManager = makeNsdManagerS();
+ doTestParallelResolveService();
+ }
+
+ @Test
+ @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testParallelResolveServicePreS() {
+ mManager = makeNsdManagerPreS();
+ doTestParallelResolveService();
+ }
+
+ @Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testInvalidCallsS() {
+ mManager = makeNsdManagerS();
+ doTestInvalidCalls();
+ }
+
+ @Test
+ @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testInvalidCallsPreS() {
+ mManager = makeNsdManagerPreS();
+ doTestInvalidCalls();
+ }
+
+ @Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testRegisterServiceS() {
+ mManager = makeNsdManagerS();
+ doTestRegisterService();
+ }
+
+ @Test
+ @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testRegisterServicePreS() {
+ mManager = makeNsdManagerPreS();
+ doTestRegisterService();
+ }
+
+ public void doTestResolveService() {
NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
@@ -104,8 +180,7 @@
verify(listener, timeout(mTimeoutMs).times(1)).onServiceResolved(reply);
}
- @Test
- public void testParallelResolveService() {
+ public void doTestParallelResolveService() {
NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
@@ -127,8 +202,7 @@
verify(listener2, timeout(mTimeoutMs).times(1)).onServiceResolved(reply);
}
- @Test
- public void testRegisterService() {
+ public void doTestRegisterService() {
NsdManager manager = mManager;
NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type");
@@ -186,8 +260,7 @@
//verify(listener2, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request2);
}
- @Test
- public void testDiscoverService() {
+ public void doTestDiscoverService() {
NsdManager manager = mManager;
NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type");
@@ -264,8 +337,7 @@
verify(listener, timeout(mTimeoutMs).times(0)).onServiceFound(reply1);
}
- @Test
- public void testInvalidCalls() {
+ public void doTestInvalidCalls() {
NsdManager manager = mManager;
NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
@@ -326,10 +398,21 @@
}
}
- NsdManager makeManager() {
+ NsdManager makeNsdManagerS() {
+ // Expect we'll get 2 AsyncChannel related msgs.
+ return makeManager(2);
+ }
+
+ NsdManager makeNsdManagerPreS() {
+ // Expect we'll get 3 msgs. 2 AsyncChannel related msgs + 1 additional daemon startup msg.
+ return makeManager(3);
+ }
+
+ NsdManager makeManager(int expectedMsgCount) {
NsdManager manager = new NsdManager(mContext, mService);
// Acknowledge first two messages connecting the AsyncChannel.
- verify(mServiceHandler, timeout(mTimeoutMs).times(2)).handleMessage(any());
+ verify(mServiceHandler, timeout(mTimeoutMs).times(expectedMsgCount)).handleMessage(any());
+
reset(mServiceHandler);
assertNotNull(mServiceHandler.chan);
return manager;
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 1c7ac44..2c73ccd 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -557,13 +557,13 @@
super(base);
mInternalResources = spy(base.getResources());
- when(mInternalResources.getStringArray(com.android.internal.R.array.networkAttributes))
- .thenReturn(new String[] {
- "wifi,1,1,1,-1,true",
- "mobile,0,0,0,-1,true",
- "mobile_mms,2,0,2,60000,true",
- "mobile_supl,3,0,2,60000,true",
- });
+ doReturn(new String[] {
+ "wifi,1,1,1,-1,true",
+ "mobile,0,0,0,-1,true",
+ "mobile_mms,2,0,2,60000,true",
+ "mobile_supl,3,0,2,60000,true",
+ }).when(mInternalResources)
+ .getStringArray(com.android.internal.R.array.networkAttributes);
mContentResolver = new MockContentResolver();
mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
@@ -1661,21 +1661,21 @@
MockitoAnnotations.initMocks(this);
- when(mUserManager.getAliveUsers()).thenReturn(asList(PRIMARY_USER_INFO));
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(asList(PRIMARY_USER_HANDLE));
- when(mUserManager.getUserInfo(PRIMARY_USER)).thenReturn(PRIMARY_USER_INFO);
+ doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
+ doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
+ doReturn(PRIMARY_USER_INFO).when(mUserManager).getUserInfo(PRIMARY_USER);
// canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
// it was started from, i.e., PRIMARY_USER.
- when(mUserManager.canHaveRestrictedProfile()).thenReturn(true);
- when(mUserManager.getUserInfo(RESTRICTED_USER)).thenReturn(RESTRICTED_USER_INFO);
+ doReturn(true).when(mUserManager).canHaveRestrictedProfile();
+ doReturn(RESTRICTED_USER_INFO).when(mUserManager).getUserInfo(RESTRICTED_USER);
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
- when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
- .thenReturn(applicationInfo);
- when(mPackageManager.getTargetSdkVersion(anyString()))
- .thenReturn(applicationInfo.targetSdkVersion);
- when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]);
+ doReturn(applicationInfo).when(mPackageManager)
+ .getApplicationInfoAsUser(anyString(), anyInt(), any());
+ doReturn(applicationInfo.targetSdkVersion).when(mPackageManager)
+ .getTargetSdkVersion(anyString());
+ doReturn(new int[0]).when(mSystemConfigManager).getSystemPermissionUids(anyString());
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
@@ -1874,36 +1874,34 @@
final String myPackageName = mContext.getPackageName();
final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
myPackageName, PackageManager.GET_PERMISSIONS);
- when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
- new String[] {myPackageName});
- when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(),
- eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo);
+ doReturn(new String[] {myPackageName}).when(mPackageManager)
+ .getPackagesForUid(Binder.getCallingUid());
+ doReturn(myPackageInfo).when(mPackageManager).getPackageInfoAsUser(
+ eq(myPackageName), anyInt(), eq(UserHandle.getCallingUserId()));
- when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- asList(new PackageInfo[] {
- buildPackageInfo(/* SYSTEM */ false, APP1_UID),
- buildPackageInfo(/* SYSTEM */ false, APP2_UID),
- buildPackageInfo(/* SYSTEM */ false, VPN_UID)
- }));
+ doReturn(asList(new PackageInfo[] {
+ buildPackageInfo(/* SYSTEM */ false, APP1_UID),
+ buildPackageInfo(/* SYSTEM */ false, APP2_UID),
+ buildPackageInfo(/* SYSTEM */ false, VPN_UID)
+ })).when(mPackageManager).getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER));
// Create a fake always-on VPN package.
final int userId = UserHandle.getCallingUserId();
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; // Always-on supported in N+.
- when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(),
- eq(userId))).thenReturn(applicationInfo);
+ doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
+ eq(ALWAYS_ON_PACKAGE), anyInt(), eq(userId));
// Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
ResolveInfo rInfo = new ResolveInfo();
rInfo.serviceInfo = new ServiceInfo();
rInfo.serviceInfo.metaData = new Bundle();
final List<ResolveInfo> services = asList(new ResolveInfo[]{rInfo});
- when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA),
- eq(userId))).thenReturn(services);
- when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId))
- .thenReturn(Process.myUid());
- when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId))
- .thenReturn(VPN_UID);
+ doReturn(services).when(mPackageManager).queryIntentServicesAsUser(
+ any(), eq(PackageManager.GET_META_DATA), eq(userId));
+ doReturn(Process.myUid()).when(mPackageManager).getPackageUidAsUser(
+ TEST_PACKAGE_NAME, userId);
+ doReturn(VPN_UID).when(mPackageManager).getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId);
}
private void verifyActiveNetwork(int transport) {
@@ -3179,9 +3177,8 @@
private void grantUsingBackgroundNetworksPermissionForUid(
final int uid, final String packageName) throws Exception {
- when(mPackageManager.getPackageInfo(
- eq(packageName), eq(GET_PERMISSIONS | MATCH_ANY_USER)))
- .thenReturn(buildPackageInfo(true /* hasSystemPermission */, uid));
+ doReturn(buildPackageInfo(true /* hasSystemPermission */, uid)).when(mPackageManager)
+ .getPackageInfo(eq(packageName), eq(GET_PERMISSIONS | MATCH_ANY_USER));
mService.mPermissionMonitor.onPackageAdded(packageName, uid);
}
@@ -7904,8 +7901,8 @@
callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps)
-> caps.hasCapability(NET_CAPABILITY_VALIDATED));
- when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER))
- .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
+ doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
+ .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
final Intent addedIntent = new Intent(ACTION_USER_ADDED);
addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
@@ -7989,10 +7986,10 @@
assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
// Start the restricted profile, and check that the UID within it loses network access.
- when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER))
- .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
- when(mUserManager.getAliveUsers()).thenReturn(asList(PRIMARY_USER_INFO,
- RESTRICTED_USER_INFO));
+ doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
+ .getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
+ doReturn(asList(PRIMARY_USER_INFO, RESTRICTED_USER_INFO)).when(mUserManager)
+ .getAliveUsers();
// TODO: check that VPN app within restricted profile still has access, etc.
final Intent addedIntent = new Intent(ACTION_USER_ADDED);
addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER));
@@ -8002,7 +7999,7 @@
assertNull(mCm.getActiveNetworkForUid(restrictedUid));
// Stop the restricted profile, and check that the UID within it has network access again.
- when(mUserManager.getAliveUsers()).thenReturn(asList(PRIMARY_USER_INFO));
+ doReturn(asList(PRIMARY_USER_INFO)).when(mUserManager).getAliveUsers();
// Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
@@ -8703,7 +8700,7 @@
private void setupLegacyLockdownVpn() {
final String profileName = "testVpnProfile";
final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8);
- when(mVpnProfileStore.get(Credentials.LOCKDOWN_VPN)).thenReturn(profileTag);
+ doReturn(profileTag).when(mVpnProfileStore).get(Credentials.LOCKDOWN_VPN);
final VpnProfile profile = new VpnProfile(profileName);
profile.name = "My VPN";
@@ -8711,7 +8708,7 @@
profile.dnsServers = "8.8.8.8";
profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK;
final byte[] encodedProfile = profile.encode();
- when(mVpnProfileStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile);
+ doReturn(encodedProfile).when(mVpnProfileStore).get(Credentials.VPN + profileName);
}
private void establishLegacyLockdownVpn(Network underlying) throws Exception {
@@ -9126,8 +9123,8 @@
verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockNetd);
reset(mMockDnsResolver);
- when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
- .thenReturn(getClatInterfaceConfigParcel(myIpv4));
+ doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
+ .interfaceGetCfg(CLAT_MOBILE_IFNAME);
// Remove IPv4 address. Expect prefix discovery to be started again.
cellLp.removeLinkAddress(myIpv4);
@@ -9177,8 +9174,8 @@
new int[] { TRANSPORT_CELLULAR });
}
reset(mMockNetd);
- when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
- .thenReturn(getClatInterfaceConfigParcel(myIpv4));
+ doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
+ .interfaceGetCfg(CLAT_MOBILE_IFNAME);
// Change the NAT64 prefix without first removing it.
// Expect clatd to be stopped and started with the new prefix.
mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
@@ -9226,8 +9223,8 @@
verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockNetd);
reset(mMockDnsResolver);
- when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
- .thenReturn(getClatInterfaceConfigParcel(myIpv4));
+ doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
+ .interfaceGetCfg(CLAT_MOBILE_IFNAME);
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
@@ -9281,8 +9278,8 @@
// Test disconnecting a network that is running 464xlat.
// Connect a network with a NAT64 prefix.
- when(mMockNetd.interfaceGetCfg(CLAT_MOBILE_IFNAME))
- .thenReturn(getClatInterfaceConfigParcel(myIpv4));
+ doReturn(getClatInterfaceConfigParcel(myIpv4)).when(mMockNetd)
+ .interfaceGetCfg(CLAT_MOBILE_IFNAME);
cellLp.setNat64Prefix(kNat64Prefix);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
mCellNetworkAgent.connect(false /* validated */);
@@ -9651,7 +9648,7 @@
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
- when(mService.mProxyTracker.getGlobalProxy()).thenReturn(testProxyInfo);
+ doReturn(testProxyInfo).when(mService.mProxyTracker).getGlobalProxy();
assertEquals(testProxyInfo, mService.getProxyForNetwork(wifiNetwork));
}
@@ -9914,16 +9911,16 @@
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = targetSdk;
- when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
- .thenReturn(applicationInfo);
- when(mPackageManager.getTargetSdkVersion(any())).thenReturn(targetSdk);
+ doReturn(applicationInfo).when(mPackageManager)
+ .getApplicationInfoAsUser(anyString(), anyInt(), any());
+ doReturn(targetSdk).when(mPackageManager).getTargetSdkVersion(any());
- when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
+ doReturn(locationToggle).when(mLocationManager).isLocationEnabledForUser(any());
if (op != null) {
- when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()),
- eq(mContext.getPackageName()), eq(getAttributionTag()), anyString()))
- .thenReturn(AppOpsManager.MODE_ALLOWED);
+ doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(
+ eq(op), eq(Process.myUid()), eq(mContext.getPackageName()),
+ eq(getAttributionTag()), anyString());
}
if (perm != null) {
@@ -9945,7 +9942,7 @@
int callerUid, boolean includeLocationSensitiveInfo,
boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
final TransportInfo transportInfo = mock(TransportInfo.class);
- when(transportInfo.getApplicableRedactions()).thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION);
+ doReturn(REDACT_FOR_ACCESS_FINE_LOCATION).when(transportInfo).getApplicableRedactions();
final NetworkCapabilities netCap =
new NetworkCapabilities().setTransportInfo(transportInfo);
@@ -10102,8 +10099,8 @@
mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_GRANTED);
final TransportInfo transportInfo = mock(TransportInfo.class);
- when(transportInfo.getApplicableRedactions())
- .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS);
+ doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
+ .when(transportInfo).getApplicableRedactions();
final NetworkCapabilities netCap =
new NetworkCapabilities().setTransportInfo(transportInfo);
@@ -10121,8 +10118,8 @@
mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
final TransportInfo transportInfo = mock(TransportInfo.class);
- when(transportInfo.getApplicableRedactions())
- .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS);
+ doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_LOCAL_MAC_ADDRESS)
+ .when(transportInfo).getApplicableRedactions();
final NetworkCapabilities netCap =
new NetworkCapabilities().setTransportInfo(transportInfo);
@@ -10141,8 +10138,8 @@
mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
final TransportInfo transportInfo = mock(TransportInfo.class);
- when(transportInfo.getApplicableRedactions())
- .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
+ doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
+ .when(transportInfo).getApplicableRedactions();
final NetworkCapabilities netCap =
new NetworkCapabilities().setTransportInfo(transportInfo);
@@ -10160,8 +10157,8 @@
mServiceContext.setPermission(Manifest.permission.LOCAL_MAC_ADDRESS, PERMISSION_DENIED);
final TransportInfo transportInfo = mock(TransportInfo.class);
- when(transportInfo.getApplicableRedactions())
- .thenReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS);
+ doReturn(REDACT_FOR_ACCESS_FINE_LOCATION | REDACT_FOR_NETWORK_SETTINGS)
+ .when(transportInfo).getApplicableRedactions();
final NetworkCapabilities netCap =
new NetworkCapabilities().setTransportInfo(transportInfo);
@@ -10248,7 +10245,7 @@
@NonNull TestNetworkCallback wifiNetworkCallback, int actualOwnerUid,
@NonNull TransportInfo actualTransportInfo, int expectedOwnerUid,
@NonNull TransportInfo expectedTransportInfo) throws Exception {
- when(mPackageManager.getTargetSdkVersion(anyString())).thenReturn(Build.VERSION_CODES.S);
+ doReturn(Build.VERSION_CODES.S).when(mPackageManager).getTargetSdkVersion(anyString());
final NetworkCapabilities ncTemplate =
new NetworkCapabilities()
.addTransportType(TRANSPORT_WIFI)
@@ -10478,7 +10475,7 @@
public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest wifiRequest =
new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
- when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
+ doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
@@ -10501,7 +10498,7 @@
public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest wifiRequest =
new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
- when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
+ doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
mService.registerConnectivityDiagnosticsCallback(
mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName());
@@ -10716,7 +10713,7 @@
callback.assertNoCallback();
final NetworkRequest request = new NetworkRequest.Builder().build();
- when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
+ doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
@@ -10732,7 +10729,7 @@
private void setUpConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest request = new NetworkRequest.Builder().build();
- when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
+ doReturn(mIBinder).when(mConnectivityDiagnosticsCallback).asBinder();
mServiceContext.setPermission(NETWORK_STACK, PERMISSION_GRANTED);
@@ -11241,8 +11238,8 @@
final Pair<IQosCallback, IBinder> pair = createQosCallback();
mCallback = pair.first;
- when(mFilter.getNetwork()).thenReturn(network);
- when(mFilter.validate()).thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
+ doReturn(network).when(mFilter).getNetwork();
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE).when(mFilter).validate();
mAgentWrapper = mCellNetworkAgent;
}
@@ -11264,8 +11261,8 @@
private Pair<IQosCallback, IBinder> createQosCallback() {
final IQosCallback callback = mock(IQosCallback.class);
final IBinder binder = mock(Binder.class);
- when(callback.asBinder()).thenReturn(binder);
- when(binder.isBinderAlive()).thenReturn(true);
+ doReturn(binder).when(callback).asBinder();
+ doReturn(true).when(binder).isBinderAlive();
return new Pair<>(callback, binder);
}
@@ -11275,8 +11272,8 @@
mQosCallbackMockHelper = new QosCallbackMockHelper();
final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
- when(mQosCallbackMockHelper.mFilter.validate())
- .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
+ .when(mQosCallbackMockHelper.mFilter).validate();
mQosCallbackMockHelper.registerQosCallback(
mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
@@ -11299,8 +11296,8 @@
public void testQosCallbackNoRegistrationOnValidationError() throws Exception {
mQosCallbackMockHelper = new QosCallbackMockHelper();
- when(mQosCallbackMockHelper.mFilter.validate())
- .thenReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED);
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NETWORK_RELEASED)
+ .when(mQosCallbackMockHelper.mFilter).validate();
mQosCallbackMockHelper.registerQosCallback(
mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
waitForIdle();
@@ -11314,8 +11311,8 @@
final int sessionId = 10;
final int qosCallbackId = 1;
- when(mQosCallbackMockHelper.mFilter.validate())
- .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
+ .when(mQosCallbackMockHelper.mFilter).validate();
mQosCallbackMockHelper.registerQosCallback(
mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
waitForIdle();
@@ -11344,8 +11341,8 @@
final int sessionId = 10;
final int qosCallbackId = 1;
- when(mQosCallbackMockHelper.mFilter.validate())
- .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
+ .when(mQosCallbackMockHelper.mFilter).validate();
mQosCallbackMockHelper.registerQosCallback(
mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
waitForIdle();
@@ -11372,8 +11369,8 @@
public void testQosCallbackTooManyRequests() throws Exception {
mQosCallbackMockHelper = new QosCallbackMockHelper();
- when(mQosCallbackMockHelper.mFilter.validate())
- .thenReturn(QosCallbackException.EX_TYPE_FILTER_NONE);
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
+ .when(mQosCallbackMockHelper.mFilter).validate();
for (int i = 0; i < 100; i++) {
final Pair<IQosCallback, IBinder> pair = createQosCallback();
@@ -11404,8 +11401,8 @@
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = uid;
try {
- when(mPackageManager.getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user)))
- .thenReturn(applicationInfo);
+ doReturn(applicationInfo).when(mPackageManager).getApplicationInfoAsUser(
+ eq(packageName), anyInt(), eq(user));
} catch (Exception e) {
fail(e.getMessage());
}
@@ -11414,13 +11411,12 @@
private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName,
@NonNull final UserHandle user)
throws Exception {
- when(mPackageManager.getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user)))
- .thenThrow(new PackageManager.NameNotFoundException(packageName));
+ doThrow(new PackageManager.NameNotFoundException(packageName)).when(
+ mPackageManager).getApplicationInfoAsUser(eq(packageName), anyInt(), eq(user));
}
private void mockHasSystemFeature(@NonNull final String featureName, final boolean hasFeature) {
- when(mPackageManager.hasSystemFeature(eq(featureName)))
- .thenReturn(hasFeature);
+ doReturn(hasFeature).when(mPackageManager).hasSystemFeature(eq(featureName));
}
private Range<Integer> getNriFirstUidRange(@NonNull final NetworkRequestInfo nri) {
@@ -11620,8 +11616,8 @@
// Arrange users
final int secondUserTestPackageUid = UserHandle.getUid(SECONDARY_USER, TEST_PACKAGE_UID);
final int thirdUserTestPackageUid = UserHandle.getUid(TERTIARY_USER, TEST_PACKAGE_UID);
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
- asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE));
+ doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE, TERTIARY_USER_HANDLE))
+ .when(mUserManager).getUserHandles(anyBoolean());
// Arrange PackageManager mocks testing for users who have and don't have a package.
mockGetApplicationInfoThrowsNameNotFound(TEST_PACKAGE_NAME, PRIMARY_USER_HANDLE);
@@ -12567,8 +12563,8 @@
// Arrange users
final int secondUser = 10;
final UserHandle secondUserHandle = new UserHandle(secondUser);
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
- asList(PRIMARY_USER_HANDLE, secondUserHandle));
+ doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
+ .getUserHandles(anyBoolean());
// Arrange PackageManager mocks
final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
@@ -12608,8 +12604,7 @@
// Arrange users
final int secondUser = 10;
final UserHandle secondUserHandle = new UserHandle(secondUser);
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
- asList(PRIMARY_USER_HANDLE));
+ doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
// Arrange PackageManager mocks
final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
@@ -12636,8 +12631,8 @@
false /* shouldDestroyNetwork */);
// Send a broadcast indicating a user was added.
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
- asList(PRIMARY_USER_HANDLE, secondUserHandle));
+ doReturn(asList(PRIMARY_USER_HANDLE, secondUserHandle)).when(mUserManager)
+ .getUserHandles(anyBoolean());
final Intent addedIntent = new Intent(ACTION_USER_ADDED);
addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
processBroadcast(addedIntent);
@@ -12649,8 +12644,7 @@
false /* shouldDestroyNetwork */);
// Send a broadcast indicating a user was removed.
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(
- asList(PRIMARY_USER_HANDLE));
+ doReturn(asList(PRIMARY_USER_HANDLE)).when(mUserManager).getUserHandles(anyBoolean());
final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser));
processBroadcast(removedIntent);
@@ -14242,7 +14236,7 @@
// callback.
final int[] uids2 = new int[] { TEST_WORK_PROFILE_APP_UID };
final UidRangeParcel[] uidRanges2 = toUidRangeStableParcels(uidRangesForUids(uids2));
- when(mUserManager.getUserHandles(anyBoolean())).thenReturn(Arrays.asList(testHandle));
+ doReturn(Arrays.asList(testHandle)).when(mUserManager).getUserHandles(anyBoolean());
setupSetOemNetworkPreferenceForPreferenceTest(
networkPref, uidRanges2, "com.android.test", testHandle);
mDefaultNetworkCallback.assertNoCallback();
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index e80a938..4d2970a 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -16,6 +16,9 @@
package com.android.server;
+import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
@@ -27,6 +30,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.ContentResolver;
import android.content.Context;
import android.net.nsd.NsdManager;
@@ -48,7 +52,9 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -67,6 +73,8 @@
private static final long CLEANUP_DELAY_MS = 500;
private static final long TIMEOUT_MS = 500;
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
@Mock Context mContext;
@Mock ContentResolver mResolver;
@Mock NsdService.NsdSettings mSettings;
@@ -94,6 +102,34 @@
}
@Test
+ @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
+ public void testPreSClients() {
+ when(mSettings.isEnabled()).thenReturn(true);
+ NsdService service = makeService();
+
+ // Pre S client connected, the daemon should be started.
+ NsdManager client1 = connectClient(service);
+ waitForIdle();
+ verify(mDaemon, times(1)).maybeStart();
+ verifyDaemonCommands("start-service");
+
+ NsdManager client2 = connectClient(service);
+ waitForIdle();
+ verify(mDaemon, times(1)).maybeStart();
+
+ client1.disconnect();
+ // Still 1 client remains, daemon shouldn't be stopped.
+ waitForIdle();
+ verify(mDaemon, never()).maybeStop();
+
+ client2.disconnect();
+ // All clients are disconnected, the daemon should be stopped.
+ verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
+ verifyDaemonCommands("stop-service");
+ }
+
+ @Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testNoDaemonStartedWhenClientsConnect() {
when(mSettings.isEnabled()).thenReturn(true);
@@ -110,13 +146,12 @@
waitForIdle();
verify(mDaemon, never()).execute(any());
+ // If there is no active request, try to clean up the daemon
+ // every time the client disconnects.
client1.disconnect();
- // Still 1 client remains, daemon shouldn't be stopped.
- waitForIdle();
- verify(mDaemon, never()).maybeStop();
-
+ verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
+ reset(mDaemon);
client2.disconnect();
- // All clients are disconnected, stop the daemon after CLEANUP_DELAY_MS.
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
client1.disconnect();
@@ -124,6 +159,7 @@
}
@Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testClientRequestsAreGCedAtDisconnection() {
when(mSettings.isEnabled()).thenReturn(true);
@@ -169,6 +205,7 @@
}
@Test
+ @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
public void testCleanupDelayNoRequestActive() {
when(mSettings.isEnabled()).thenReturn(true);