Merge "Remove ForceAllNetworkTypes from test"
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index eecd12c..7294ec9 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -2369,7 +2369,7 @@
throw new IllegalArgumentException("Listener was not registered.");
}
try {
- mService.registerNetworkActivityListener(rl);
+ mService.unregisterNetworkActivityListener(rl);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 447f626..17fc3b4 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -852,7 +852,7 @@
// SubIds are only allowed for Test Networks that only declare TRANSPORT_TEST.
setSubscriptionIds(originalSubIds);
} else {
- // If the test transport is restricted, then it may declare any transport.
+ // If the test network is restricted, then it may declare any transport.
mTransportTypes = (originalTransportTypes | (1 << TRANSPORT_TEST));
}
mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 1d5d8af..9f63191 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -2311,9 +2311,7 @@
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- // TODO: Consider include SUSPENDED networks, which should be considered as
- // temporary shortage of connectivity of a connected network.
- if (nai != null && nai.networkInfo.isConnected()) {
+ if (nai != null && nai.everConnected) {
// TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
// NetworkCapabilities, which may contain UIDs of apps to which the
// network applies. Should the UIDs be cleared so as not to leak or
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index 7c0fb91..f596c4a 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -74,11 +74,10 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
/**
- * A utility class to inform Netd of UID permisisons.
+ * A utility class to inform Netd of UID permissions.
* Does a mass update at boot and then monitors for app install/remove.
*
* @hide
@@ -86,8 +85,6 @@
public class PermissionMonitor {
private static final String TAG = "PermissionMonitor";
private static final boolean DBG = true;
- protected static final Boolean SYSTEM = Boolean.TRUE;
- protected static final Boolean NETWORK = Boolean.FALSE;
private static final int VERSION_Q = Build.VERSION_CODES.Q;
private final PackageManager mPackageManager;
@@ -100,9 +97,9 @@
@GuardedBy("this")
private final Set<UserHandle> mUsers = new HashSet<>();
- // Keys are app uids. Values are true for SYSTEM permission and false for NETWORK permission.
+ // Keys are appIds. Values are true for SYSTEM permission and false for NETWORK permission.
@GuardedBy("this")
- private final Map<Integer, Boolean> mApps = new HashMap<>();
+ private final SparseIntArray mApps = new SparseIntArray();
// Keys are active non-bypassable and fully-routed VPN's interface name, Values are uid ranges
// for apps under the VPN
@@ -194,6 +191,23 @@
mContext = context;
}
+ private int getPackageNetdNetworkPermission(@NonNull final PackageInfo app) {
+ if (hasRestrictedNetworkPermission(app)) {
+ return PERMISSION_SYSTEM;
+ }
+ if (hasNetworkPermission(app)) {
+ return PERMISSION_NETWORK;
+ }
+ return PERMISSION_NONE;
+ }
+
+ static boolean isHigherNetworkPermission(final int targetPermission,
+ final int currentPermission) {
+ // This is relied on strict order of network permissions (SYSTEM > NETWORK > NONE), and it
+ // is enforced in tests.
+ return targetPermission > currentPermission;
+ }
+
// Intended to be called only once at startup, after the system is ready. Installs a broadcast
// receiver to monitor ongoing UID changes, so this shouldn't/needn't be called again.
public synchronized void startMonitoring() {
@@ -237,31 +251,25 @@
return;
}
- SparseIntArray netdPermsUids = new SparseIntArray();
+ final SparseIntArray netdPermsAppIds = new SparseIntArray();
for (PackageInfo app : apps) {
int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID;
if (uid < 0) {
continue;
}
- mAllApps.add(UserHandle.getAppId(uid));
+ final int appId = UserHandle.getAppId(uid);
+ mAllApps.add(appId);
- boolean isNetwork = hasNetworkPermission(app);
- boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
-
- if (isNetwork || hasRestrictedPermission) {
- Boolean permission = mApps.get(UserHandle.getAppId(uid));
- // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
- // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
- if (permission == null || permission == NETWORK) {
- mApps.put(UserHandle.getAppId(uid), hasRestrictedPermission);
- }
+ final int permission = getPackageNetdNetworkPermission(app);
+ if (isHigherNetworkPermission(permission, mApps.get(appId, PERMISSION_NONE))) {
+ mApps.put(appId, permission);
}
//TODO: unify the management of the permissions into one codepath.
int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions,
app.requestedPermissionsFlags);
- netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
+ netdPermsAppIds.put(appId, netdPermsAppIds.get(appId) | otherNetdPerms);
}
mUsers.addAll(mUserManager.getUserHandles(true /* excludeDying */));
@@ -275,13 +283,13 @@
final int[] hasPermissionUids =
mSystemConfigManager.getSystemPermissionUids(systemPermission);
for (int j = 0; j < hasPermissionUids.length; j++) {
- final int uid = hasPermissionUids[j];
- netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission);
+ final int appId = UserHandle.getAppId(hasPermissionUids[j]);
+ netdPermsAppIds.put(appId, netdPermsAppIds.get(appId) | netdPermission);
}
}
log("Users: " + mUsers.size() + ", Apps: " + mApps.size());
update(mUsers, mApps, true);
- sendPackagePermissionsToNetd(netdPermsUids);
+ sendPackagePermissionsToNetd(netdPermsAppIds);
}
@VisibleForTesting
@@ -352,25 +360,29 @@
// networks. mApps contains the result of checks for both hasNetworkPermission and
// hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of
// permissions at least.
- return mApps.containsKey(UserHandle.getAppId(uid));
+ return mApps.get(UserHandle.getAppId(uid), PERMISSION_NONE) != PERMISSION_NONE;
}
/**
* Returns whether the given uid has permission to use restricted networks.
*/
public synchronized boolean hasRestrictedNetworksPermission(int uid) {
- return Boolean.TRUE.equals(mApps.get(UserHandle.getAppId(uid)));
+ return PERMISSION_SYSTEM == mApps.get(UserHandle.getAppId(uid), PERMISSION_NONE);
}
- private void update(Set<UserHandle> users, Map<Integer, Boolean> apps, boolean add) {
+ private void update(Set<UserHandle> users, SparseIntArray apps, boolean add) {
List<Integer> network = new ArrayList<>();
List<Integer> system = new ArrayList<>();
- for (Entry<Integer, Boolean> app : apps.entrySet()) {
- List<Integer> list = app.getValue() ? system : network;
+ for (int i = 0; i < apps.size(); i++) {
+ final int permission = apps.valueAt(i);
+ if (PERMISSION_NONE == permission) {
+ continue; // Normally NONE is not stored in this map, but just in case
+ }
+ List<Integer> list = (PERMISSION_SYSTEM == permission) ? system : network;
for (UserHandle user : users) {
if (user == null) continue;
- list.add(user.getUid(app.getKey()));
+ list.add(user.getUid(apps.keyAt(i)));
}
}
try {
@@ -395,10 +407,7 @@
*/
public synchronized void onUserAdded(@NonNull UserHandle user) {
mUsers.add(user);
-
- Set<UserHandle> users = new HashSet<>();
- users.add(user);
- update(users, mApps, true);
+ update(Set.of(user), mApps, true);
}
/**
@@ -410,10 +419,7 @@
*/
public synchronized void onUserRemoved(@NonNull UserHandle user) {
mUsers.remove(user);
-
- Set<UserHandle> users = new HashSet<>();
- users.add(user);
- update(users, mApps, false);
+ update(Set.of(user), mApps, false);
}
/**
@@ -425,17 +431,16 @@
* permission.
*/
@VisibleForTesting
- protected Boolean highestPermissionForUid(Boolean currentPermission, String name) {
- if (currentPermission == SYSTEM) {
+ protected int highestPermissionForUid(int currentPermission, String name) {
+ if (currentPermission == PERMISSION_SYSTEM) {
return currentPermission;
}
try {
final PackageInfo app = mPackageManager.getPackageInfo(name,
GET_PERMISSIONS | MATCH_ANY_USER);
- final boolean isNetwork = hasNetworkPermission(app);
- final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
- if (isNetwork || hasRestrictedPermission) {
- currentPermission = hasRestrictedPermission;
+ final int permission = getPackageNetdNetworkPermission(app);
+ if (isHigherNetworkPermission(permission, currentPermission)) {
+ return permission;
}
} catch (NameNotFoundException e) {
// App not found.
@@ -464,6 +469,17 @@
return permission;
}
+ private synchronized void updateVpnUid(int uid, boolean add) {
+ for (Map.Entry<String, Set<UidRange>> vpn : mVpnUidRanges.entrySet()) {
+ if (UidRange.containsUid(vpn.getValue(), uid)) {
+ final Set<Integer> changedUids = new HashSet<>();
+ changedUids.add(uid);
+ removeBypassingUids(changedUids, -1 /* vpnAppUid */);
+ updateVpnUidsInterfaceRules(vpn.getKey(), changedUids, add);
+ }
+ }
+ }
+
/**
* Called when a package is added.
*
@@ -473,45 +489,37 @@
* @hide
*/
public synchronized void onPackageAdded(@NonNull final String packageName, final int uid) {
- // TODO: Netd is using appId for checking traffic permission. Correct the methods that are
- // using appId instead of uid actually
- sendPackagePermissionsForUid(UserHandle.getAppId(uid), getPermissionForUid(uid));
+ final int appId = UserHandle.getAppId(uid);
+ sendPackagePermissionsForAppId(appId, getPermissionForUid(uid));
// If multiple packages share a UID (cf: android:sharedUserId) and ask for different
// permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
- final int appId = UserHandle.getAppId(uid);
- final Boolean permission = highestPermissionForUid(mApps.get(appId), packageName);
- if (permission != mApps.get(appId)) {
+ final int currentPermission = mApps.get(appId, PERMISSION_NONE);
+ final int permission = highestPermissionForUid(currentPermission, packageName);
+ if (permission != currentPermission) {
mApps.put(appId, permission);
- Map<Integer, Boolean> apps = new HashMap<>();
+ SparseIntArray apps = new SparseIntArray();
apps.put(appId, permission);
update(mUsers, apps, true);
}
// If the newly-installed package falls within some VPN's uid range, update Netd with it.
- // This needs to happen after the mApps update above, since removeBypassingUids() depends
- // on mApps to check if the package can bypass VPN.
- for (Map.Entry<String, Set<UidRange>> vpn : mVpnUidRanges.entrySet()) {
- if (UidRange.containsUid(vpn.getValue(), uid)) {
- final Set<Integer> changedUids = new HashSet<>();
- changedUids.add(uid);
- removeBypassingUids(changedUids, /* vpnAppUid */ -1);
- updateVpnUids(vpn.getKey(), changedUids, true);
- }
- }
+ // This needs to happen after the mApps update above, since removeBypassingUids() in
+ // updateVpnUid() depends on mApps to check if the package can bypass VPN.
+ updateVpnUid(uid, true /* add */);
mAllApps.add(appId);
}
- private Boolean highestUidNetworkPermission(int uid) {
- Boolean permission = null;
+ private int highestUidNetworkPermission(int uid) {
+ int permission = PERMISSION_NONE;
final String[] packages = mPackageManager.getPackagesForUid(uid);
if (!CollectionUtils.isEmpty(packages)) {
for (String name : packages) {
// If multiple packages have the same UID, give the UID all permissions that
// any package in that UID has.
permission = highestPermissionForUid(permission, name);
- if (permission == SYSTEM) {
+ if (permission == PERMISSION_SYSTEM) {
break;
}
}
@@ -528,46 +536,36 @@
* @hide
*/
public synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) {
- // TODO: Netd is using appId for checking traffic permission. Correct the methods that are
- // using appId instead of uid actually
- sendPackagePermissionsForUid(UserHandle.getAppId(uid), getPermissionForUid(uid));
+ final int appId = UserHandle.getAppId(uid);
+ sendPackagePermissionsForAppId(appId, getPermissionForUid(uid));
// If the newly-removed package falls within some VPN's uid range, update Netd with it.
- // This needs to happen before the mApps update below, since removeBypassingUids() depends
- // on mApps to check if the package can bypass VPN.
- for (Map.Entry<String, Set<UidRange>> vpn : mVpnUidRanges.entrySet()) {
- if (UidRange.containsUid(vpn.getValue(), uid)) {
- final Set<Integer> changedUids = new HashSet<>();
- changedUids.add(uid);
- removeBypassingUids(changedUids, /* vpnAppUid */ -1);
- updateVpnUids(vpn.getKey(), changedUids, false);
- }
- }
+ // This needs to happen before the mApps update below, since removeBypassingUids() in
+ // updateVpnUid() depends on mApps to check if the package can bypass VPN.
+ updateVpnUid(uid, false /* add */);
// If the package has been removed from all users on the device, clear it form mAllApps.
if (mPackageManager.getNameForUid(uid) == null) {
- mAllApps.remove(UserHandle.getAppId(uid));
+ mAllApps.remove(appId);
}
- Map<Integer, Boolean> apps = new HashMap<>();
- final Boolean permission = highestUidNetworkPermission(uid);
- if (permission == SYSTEM) {
+ final int permission = highestUidNetworkPermission(uid);
+ if (permission == PERMISSION_SYSTEM) {
// An app with this UID still has the SYSTEM permission.
// Therefore, this UID must already have the SYSTEM permission.
// Nothing to do.
return;
}
+ // If the permissions of this UID have not changed, do nothing.
+ if (permission == mApps.get(appId, PERMISSION_NONE)) return;
- final int appId = UserHandle.getAppId(uid);
- if (permission == mApps.get(appId)) {
- // The permissions of this UID have not changed. Nothing to do.
- return;
- } else if (permission != null) {
+ final SparseIntArray apps = new SparseIntArray();
+ if (permission != PERMISSION_NONE) {
mApps.put(appId, permission);
apps.put(appId, permission);
update(mUsers, apps, true);
} else {
- mApps.remove(appId);
- apps.put(appId, NETWORK); // doesn't matter which permission we pick here
+ mApps.delete(appId);
+ apps.put(appId, PERMISSION_NETWORK); // doesn't matter which permission we pick here
update(mUsers, apps, false);
}
}
@@ -614,7 +612,7 @@
// but that's safe.
final Set<Integer> changedUids = intersectUids(rangesToAdd, mAllApps);
removeBypassingUids(changedUids, vpnAppUid);
- updateVpnUids(iface, changedUids, true);
+ updateVpnUidsInterfaceRules(iface, changedUids, true /* add */);
if (mVpnUidRanges.containsKey(iface)) {
mVpnUidRanges.get(iface).addAll(rangesToAdd);
} else {
@@ -635,7 +633,7 @@
// ranges and update Netd about them.
final Set<Integer> changedUids = intersectUids(rangesToRemove, mAllApps);
removeBypassingUids(changedUids, vpnAppUid);
- updateVpnUids(iface, changedUids, false);
+ updateVpnUidsInterfaceRules(iface, changedUids, false /* add */);
Set<UidRange> existingRanges = mVpnUidRanges.getOrDefault(iface, null);
if (existingRanges == null) {
loge("Attempt to remove unknown vpn uid Range iface = " + iface);
@@ -674,7 +672,7 @@
/**
* Remove all apps which can elect to bypass the VPN from the list of uids
*
- * An app can elect to bypass the VPN if it hold SYSTEM permission, or if its the active VPN
+ * An app can elect to bypass the VPN if it holds SYSTEM permission, or if it's the active VPN
* app itself.
*
* @param uids The list of uids to operate on
@@ -682,7 +680,8 @@
*/
private void removeBypassingUids(Set<Integer> uids, int vpnAppUid) {
uids.remove(vpnAppUid);
- uids.removeIf(uid -> mApps.getOrDefault(UserHandle.getAppId(uid), NETWORK) == SYSTEM);
+ uids.removeIf(uid ->
+ mApps.get(UserHandle.getAppId(uid), PERMISSION_NONE) == PERMISSION_SYSTEM);
}
/**
@@ -696,7 +695,7 @@
* @param add {@code true} if the uids are to be added to the interface, {@code false} if they
* are to be removed from the interface.
*/
- private void updateVpnUids(String iface, Set<Integer> uids, boolean add) {
+ private void updateVpnUidsInterfaceRules(String iface, Set<Integer> uids, boolean add) {
if (uids.size() == 0) {
return;
}
@@ -718,27 +717,25 @@
}
/**
- * Called by PackageListObserver when a package is installed/uninstalled. Send the updated
- * permission information to netd.
+ * Send the updated permission information to netd. Called upon package install/uninstall.
*
- * @param uid the app uid of the package installed
+ * @param appId the appId of the package installed
* @param permissions the permissions the app requested and netd cares about.
*
* @hide
*/
@VisibleForTesting
- void sendPackagePermissionsForUid(int uid, int permissions) {
+ void sendPackagePermissionsForAppId(int appId, int permissions) {
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
- netdPermissionsAppIds.put(uid, permissions);
+ netdPermissionsAppIds.put(appId, permissions);
sendPackagePermissionsToNetd(netdPermissionsAppIds);
}
/**
- * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET
- * and/or UPDATE_DEVICE_STATS permission of the uids in array.
+ * Grant or revoke the INTERNET and/or UPDATE_DEVICE_STATS permission of the appIds in array.
*
- * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the
- * permission is 0, revoke all permissions of that uid.
+ * @param netdPermissionsAppIds integer pairs of appIds and the permission granted to it. If the
+ * permission is 0, revoke all permissions of that appId.
*
* @hide
*/
@@ -816,17 +813,18 @@
updateUidsAllowedOnRestrictedNetworks(mDeps.getUidsAllowedOnRestrictedNetworks(mContext));
uidsToUpdate.addAll(mUidsAllowedOnRestrictedNetworks);
- final Map<Integer, Boolean> updatedUids = new HashMap<>();
- final Map<Integer, Boolean> removedUids = new HashMap<>();
+ final SparseIntArray updatedUids = new SparseIntArray();
+ final SparseIntArray removedUids = new SparseIntArray();
// Step2. For each uid to update, find out its new permission.
for (Integer uid : uidsToUpdate) {
- final Boolean permission = highestUidNetworkPermission(uid);
+ final int permission = highestUidNetworkPermission(uid);
final int appId = UserHandle.getAppId(uid);
- if (null == permission) {
- removedUids.put(appId, NETWORK); // Doesn't matter which permission is set here.
- mApps.remove(appId);
+ if (PERMISSION_NONE == permission) {
+ // Doesn't matter which permission is set here.
+ removedUids.put(appId, PERMISSION_NETWORK);
+ mApps.delete(appId);
} else {
updatedUids.put(appId, permission);
mApps.put(appId, permission);
diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java
index 382fa1f..502b4f6 100644
--- a/tests/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -1170,46 +1170,104 @@
}
@Test @IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
- public void testRestrictCapabilitiesForTestNetwork() {
+ public void testRestrictCapabilitiesForTestNetworkByNotOwnerWithNonRestrictedNc() {
+ testRestrictCapabilitiesForTestNetworkWithNonRestrictedNc(false /* isOwner */);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
+ public void testRestrictCapabilitiesForTestNetworkByOwnerWithNonRestrictedNc() {
+ testRestrictCapabilitiesForTestNetworkWithNonRestrictedNc(true /* isOwner */);
+ }
+
+ private void testRestrictCapabilitiesForTestNetworkWithNonRestrictedNc(boolean isOwner) {
final int ownerUid = 1234;
+ final int signalStrength = -80;
final int[] administratorUids = {1001, ownerUid};
+ final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(TEST_SUBID1);
+ final TransportInfo transportInfo = new TransportInfo() {};
final NetworkCapabilities nonRestrictedNc = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR)
- .addTransportType(TRANSPORT_VPN)
.addCapability(NET_CAPABILITY_MMS)
.addCapability(NET_CAPABILITY_NOT_METERED)
.setAdministratorUids(administratorUids)
.setOwnerUid(ownerUid)
+ .setNetworkSpecifier(specifier)
+ .setSignalStrength(signalStrength)
+ .setTransportInfo(transportInfo)
.setSubscriptionIds(Set.of(TEST_SUBID1)).build();
+ final int creatorUid = isOwner ? ownerUid : INVALID_UID;
+ nonRestrictedNc.restrictCapabilitiesForTestNetwork(creatorUid);
- nonRestrictedNc.restrictCapabilitiesForTestNetwork(ownerUid);
- // TRANSPORT_TEST will be appended
- assertTrue(nonRestrictedNc.hasTransport(TRANSPORT_TEST));
- assertEquals(Set.of(TEST_SUBID1), nonRestrictedNc.getSubscriptionIds());
- // Non-UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS will be removed
- assertFalse(nonRestrictedNc.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(nonRestrictedNc.hasTransport(TRANSPORT_VPN));
- // Only TEST_NETWORKS_ALLOWED_CAPABILITIES will be kept
- assertFalse(nonRestrictedNc.hasCapability(NET_CAPABILITY_MMS));
- assertTrue(nonRestrictedNc.hasCapability(NET_CAPABILITY_NOT_METERED));
+ final NetworkCapabilities.Builder expectedNcBuilder = new NetworkCapabilities.Builder();
+ // Non-UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS will be removed and TRANSPORT_TEST will
+ // be appended for non-restricted net cap.
+ expectedNcBuilder.addTransportType(TRANSPORT_TEST);
+ // Only TEST_NETWORKS_ALLOWED_CAPABILITIES will be kept. SubIds are only allowed for Test
+ // Networks that only declare TRANSPORT_TEST.
+ expectedNcBuilder.addCapability(NET_CAPABILITY_NOT_METERED)
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .setSubscriptionIds(Set.of(TEST_SUBID1));
- final NetworkCapabilities restrictedNc = new NetworkCapabilities.Builder(nonRestrictedNc)
+ expectedNcBuilder.setNetworkSpecifier(specifier)
+ .setSignalStrength(signalStrength).setTransportInfo(transportInfo);
+ if (creatorUid == ownerUid) {
+ // Only retain the owner and administrator UIDs if they match the app registering the
+ // remote caller that registered the network.
+ expectedNcBuilder.setAdministratorUids(new int[]{ownerUid}).setOwnerUid(ownerUid);
+ }
+
+ assertEquals(expectedNcBuilder.build(), nonRestrictedNc);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
+ public void testRestrictCapabilitiesForTestNetworkByNotOwnerWithRestrictedNc() {
+ testRestrictCapabilitiesForTestNetworkWithRestrictedNc(false /* isOwner */);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
+ public void testRestrictCapabilitiesForTestNetworkByOwnerWithRestrictedNc() {
+ testRestrictCapabilitiesForTestNetworkWithRestrictedNc(true /* isOwner */);
+ }
+
+ private void testRestrictCapabilitiesForTestNetworkWithRestrictedNc(boolean isOwner) {
+ final int ownerUid = 1234;
+ final int signalStrength = -80;
+ final int[] administratorUids = {1001, ownerUid};
+ final TransportInfo transportInfo = new TransportInfo() {};
+ // No NetworkSpecifier is set because after performing restrictCapabilitiesForTestNetwork
+ // the networkCapabilities will contain more than one transport type. However,
+ // networkCapabilities must have a single transport specified to use NetworkSpecifier. Thus,
+ // do not verify this part since it's verified in other tests.
+ final NetworkCapabilities restrictedNc = new NetworkCapabilities.Builder()
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
.addTransportType(TRANSPORT_CELLULAR)
- .addCapability(NET_CAPABILITY_MMS).build();
- restrictedNc.restrictCapabilitiesForTestNetwork(ownerUid);
- // It may declare any transport if the net cap is restricted
- assertTrue(restrictedNc.hasTransport(TRANSPORT_CELLULAR));
- // SubIds will be cleared.
- assertEquals(new ArraySet<>(), restrictedNc.getSubscriptionIds());
- // Only retain the owner and administrator UIDs if they match the app registering the remote
- // caller that registered the network.
- assertEquals(ownerUid, restrictedNc.getOwnerUid());
- assertArrayEquals(new int[] {ownerUid}, restrictedNc.getAdministratorUids());
- // The creator UID does not match the owner and administrator UIDs will clear the owner and
- // administrator UIDs.
- restrictedNc.restrictCapabilitiesForTestNetwork(5678);
- assertEquals(INVALID_UID, restrictedNc.getOwnerUid());
- assertArrayEquals(new int[0], restrictedNc.getAdministratorUids());
+ .addCapability(NET_CAPABILITY_MMS)
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .setAdministratorUids(administratorUids)
+ .setOwnerUid(ownerUid)
+ .setSignalStrength(signalStrength)
+ .setTransportInfo(transportInfo)
+ .setSubscriptionIds(Set.of(TEST_SUBID1)).build();
+ final int creatorUid = isOwner ? ownerUid : INVALID_UID;
+ restrictedNc.restrictCapabilitiesForTestNetwork(creatorUid);
+
+ final NetworkCapabilities.Builder expectedNcBuilder = new NetworkCapabilities.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+ // If the test network is restricted, then the network may declare any transport, and
+ // appended with TRANSPORT_TEST.
+ expectedNcBuilder.addTransportType(TRANSPORT_CELLULAR);
+ expectedNcBuilder.addTransportType(TRANSPORT_TEST);
+ // Only TEST_NETWORKS_ALLOWED_CAPABILITIES will be kept.
+ expectedNcBuilder.addCapability(NET_CAPABILITY_NOT_METERED);
+ expectedNcBuilder.removeCapability(NET_CAPABILITY_TRUSTED);
+
+ expectedNcBuilder.setSignalStrength(signalStrength).setTransportInfo(transportInfo);
+ if (creatorUid == ownerUid) {
+ // Only retain the owner and administrator UIDs if they match the app registering the
+ // remote caller that registered the network.
+ expectedNcBuilder.setAdministratorUids(new int[]{ownerUid}).setOwnerUid(ownerUid);
+ }
+
+ assertEquals(expectedNcBuilder.build(), restrictedNc);
}
}
diff --git a/tests/cts/net/src/android/net/cts/AirplaneModeTest.java b/tests/cts/net/src/android/net/cts/AirplaneModeTest.java
deleted file mode 100644
index 524e549..0000000
--- a/tests/cts/net/src/android/net/cts/AirplaneModeTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.cts;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.platform.test.annotations.AppModeFull;
-import android.provider.Settings;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.lang.Thread;
-
-@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
-public class AirplaneModeTest extends AndroidTestCase {
- private static final String TAG = "AirplaneModeTest";
- private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
- private static final String FEATURE_WIFI = "android.hardware.wifi";
- private static final int TIMEOUT_MS = 10 * 1000;
- private boolean mHasFeature;
- private Context mContext;
- private ContentResolver resolver;
-
- public void setup() {
- mContext= getContext();
- resolver = mContext.getContentResolver();
- mHasFeature = (mContext.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH)
- || mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI));
- }
-
- public void testAirplaneMode() {
- setup();
- if (!mHasFeature) {
- Log.i(TAG, "The device doesn't support network bluetooth or wifi feature");
- return;
- }
-
- for (int testCount = 0; testCount < 2; testCount++) {
- if (!doOneTest()) {
- fail("Airplane mode failed to change in " + TIMEOUT_MS + "msec");
- return;
- }
- }
- }
-
- private boolean doOneTest() {
- boolean airplaneModeOn = isAirplaneModeOn();
- setAirplaneModeOn(!airplaneModeOn);
-
- try {
- Thread.sleep(TIMEOUT_MS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Sleep time interrupted.", e);
- }
-
- if (airplaneModeOn == isAirplaneModeOn()) {
- return false;
- }
- return true;
- }
-
- private void setAirplaneModeOn(boolean enabling) {
- // Change the system setting for airplane mode
- Settings.Global.putInt(resolver, Settings.Global.AIRPLANE_MODE_ON, enabling ? 1 : 0);
- }
-
- private boolean isAirplaneModeOn() {
- // Read the system setting for airplane mode
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
- }
-}
diff --git a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
index 9f079c4..9f98e3f 100644
--- a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
+++ b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
@@ -46,6 +46,7 @@
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
import android.text.TextUtils
+import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.AndroidJUnit4
import com.android.testutils.RecorderCallback
@@ -79,6 +80,8 @@
private const val WIFI_CONNECT_TIMEOUT_MS = 120_000L
private const val TEST_TIMEOUT_MS = 10_000L
+private const val TAG = "CaptivePortalTest"
+
private fun <T> CompletableFuture<T>.assertGet(timeoutMs: Long, message: String): T {
try {
return get(timeoutMs, TimeUnit.MILLISECONDS)
@@ -155,6 +158,7 @@
server.addResponse(Request(TEST_HTTP_URL_PATH), Status.REDIRECT, headers)
setHttpsUrlDeviceConfig(makeUrl(TEST_HTTPS_URL_PATH))
setHttpUrlDeviceConfig(makeUrl(TEST_HTTP_URL_PATH))
+ Log.d(TAG, "Set portal URLs to $TEST_HTTPS_URL_PATH and $TEST_HTTP_URL_PATH")
// URL expiration needs to be in the next 10 minutes
assertTrue(WIFI_CONNECT_TIMEOUT_MS < TimeUnit.MINUTES.toMillis(10))
setUrlExpirationDeviceConfig(System.currentTimeMillis() + WIFI_CONNECT_TIMEOUT_MS)
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 65dffbd..f5c43d6 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -119,10 +119,8 @@
import android.net.NetworkInfo.State;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
-import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStateSnapshot;
-import android.net.NetworkUtils;
import android.net.OemNetworkPreferences;
import android.net.ProxyInfo;
import android.net.SocketKeepalive;
@@ -260,6 +258,7 @@
"config_allowedUnprivilegedKeepalivePerUid";
private static final String KEEPALIVE_RESERVED_PER_SLOT_RES_NAME =
"config_reservedPrivilegedKeepaliveSlots";
+ private static final String TEST_RESTRICTED_NW_IFACE_NAME = "test-restricted-nw";
private static final LinkAddress TEST_LINKADDR = new LinkAddress(
InetAddresses.parseNumericAddress("2001:db8::8"), 64);
@@ -1082,7 +1081,8 @@
}
private Network waitForActiveNetworkMetered(final int targetTransportType,
- final boolean requestedMeteredness, final boolean useSystemDefault)
+ final boolean requestedMeteredness, final boolean waitForValidation,
+ final boolean useSystemDefault)
throws Exception {
final CompletableFuture<Network> networkFuture = new CompletableFuture<>();
final NetworkCallback networkCallback = new NetworkCallback() {
@@ -1091,7 +1091,8 @@
if (!nc.hasTransport(targetTransportType)) return;
final boolean metered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
- if (metered == requestedMeteredness) {
+ final boolean validated = nc.hasCapability(NET_CAPABILITY_VALIDATED);
+ if (metered == requestedMeteredness && (!waitForValidation || validated)) {
networkFuture.complete(network);
}
}
@@ -1120,11 +1121,13 @@
}
}
- private Network setWifiMeteredStatusAndWait(String ssid, boolean isMetered) throws Exception {
+ private Network setWifiMeteredStatusAndWait(String ssid, boolean isMetered,
+ boolean waitForValidation) throws Exception {
setWifiMeteredStatus(ssid, Boolean.toString(isMetered) /* metered */);
mCtsNetUtils.ensureWifiConnected();
return waitForActiveNetworkMetered(TRANSPORT_WIFI,
isMetered /* requestedMeteredness */,
+ waitForValidation,
true /* useSystemDefault */);
}
@@ -1187,9 +1190,10 @@
int newMeteredPreference = findNextPrefValue(resolver);
Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE,
Integer.toString(newMeteredPreference));
- // Wifi meterness changes from unmetered to metered will disconnect and reconnect since
- // R.
- final Network network = setWifiMeteredStatusAndWait(ssid, true);
+ // Wifi meteredness changes from unmetered to metered will disconnect and reconnect
+ // since R.
+ final Network network = setWifiMeteredStatusAndWait(ssid, true /* isMetered */,
+ false /* waitForValidation */);
assertEquals(ssid, unquoteSSID(mWifiManager.getConnectionInfo().getSSID()));
assertEquals(mCm.getNetworkCapabilities(network).hasCapability(
NET_CAPABILITY_NOT_METERED), false);
@@ -1206,7 +1210,7 @@
oldMeteredPreference, newMeteredPreference);
// No disconnect from unmetered to metered.
- setWifiMeteredStatusAndWait(ssid, false);
+ setWifiMeteredStatusAndWait(ssid, false /* isMetered */, false /* waitForValidation */);
assertEquals(mCm.getNetworkCapabilities(network).hasCapability(
NET_CAPABILITY_NOT_METERED), true);
assertMultipathPreferenceIsEventually(network, newMeteredPreference,
@@ -1748,6 +1752,40 @@
greater >= lesser);
}
+ private void verifyBindSocketToRestrictedNetworkDisallowed() throws Exception {
+ final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback();
+ final NetworkRequest testRequest = new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(
+ TEST_RESTRICTED_NW_IFACE_NAME))
+ .build();
+ runWithShellPermissionIdentity(() -> requestNetwork(testRequest, testNetworkCb),
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS,
+ // CONNECTIVITY_INTERNAL is for requesting restricted network because shell does not
+ // have CONNECTIVITY_USE_RESTRICTED_NETWORKS on R.
+ CONNECTIVITY_INTERNAL);
+
+ // Create a restricted network and ensure this package cannot bind to that network either.
+ final NetworkAgent agent = createRestrictedNetworkAgent(mContext);
+ final Network network = agent.getNetwork();
+
+ try (Socket socket = new Socket()) {
+ // Verify that the network is restricted.
+ testNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> network.equals(entry.getNetwork())
+ && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
+ // CtsNetTestCases package doesn't hold CONNECTIVITY_USE_RESTRICTED_NETWORKS, so it
+ // does not allow to bind socket to restricted network.
+ assertThrows(IOException.class, () -> network.bindSocket(socket));
+ } finally {
+ agent.unregister();
+ }
+ }
+
/**
* Verifies that apps are not allowed to access restricted networks even if they declare the
* CONNECTIVITY_USE_RESTRICTED_NETWORKS permission in their manifests.
@@ -1764,23 +1802,33 @@
assertTrue(index >= 0);
assertTrue(app.requestedPermissionsFlags[index] != PERMISSION_GRANTED);
- // Ensure that NetworkUtils.queryUserAccess always returns false since this package should
- // not have netd system permission to call this function.
- final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
- assertFalse(NetworkUtils.queryUserAccess(Binder.getCallingUid(), wifiNetwork.netId));
+ if (mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+ // Expect binding to the wifi network to succeed.
+ final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
+ try (Socket socket = new Socket()) {
+ wifiNetwork.bindSocket(socket);
+ }
+ }
// Ensure that this package cannot bind to any restricted network that's currently
// connected.
Network[] networks = mCm.getAllNetworks();
for (Network network : networks) {
- NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
- if (nc != null && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
- try {
- network.bindSocket(new Socket());
- fail("Bind to restricted network " + network + " unexpectedly succeeded");
- } catch (IOException expected) {}
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
+ if (nc == null) {
+ continue;
+ }
+
+ try (Socket socket = new Socket()) {
+ if (nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
+ network.bindSocket(socket); // binding should succeed
+ } else {
+ assertThrows(IOException.class, () -> network.bindSocket(socket));
+ }
}
}
+
+ verifyBindSocketToRestrictedNetworkDisallowed();
}
/**
@@ -2322,8 +2370,10 @@
final boolean oldMeteredValue = wifiNetworkCapabilities.isMetered();
try {
- // This network will be used for unmetered.
- setWifiMeteredStatusAndWait(ssid, false /* isMetered */);
+ // This network will be used for unmetered. Wait for it to be validated because
+ // OEM_NETWORK_PREFERENCE_TEST only prefers NOT_METERED&VALIDATED to a network with
+ // TRANSPORT_TEST, like OEM_NETWORK_PREFERENCE_OEM_PAID.
+ setWifiMeteredStatusAndWait(ssid, false /* isMetered */, true /* waitForValidation */);
setOemNetworkPreferenceForMyPackage(OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST);
registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
@@ -2332,9 +2382,10 @@
waitForAvailable(defaultCallback, wifiNetwork);
waitForAvailable(systemDefaultCallback, wifiNetwork);
- // Validate when setting unmetered to metered, unmetered is lost and replaced by the
- // network with the TEST transport.
- setWifiMeteredStatusAndWait(ssid, true /* isMetered */);
+ // Validate that when setting unmetered to metered, unmetered is lost and replaced by
+ // the network with the TEST transport. Also wait for validation here, in case there
+ // is a bug that's only visible when the network is validated.
+ setWifiMeteredStatusAndWait(ssid, true /* isMetered */, true /* waitForValidation */);
defaultCallback.expectCallback(CallbackEntry.LOST, wifiNetwork,
NETWORK_CALLBACK_TIMEOUT_MS);
waitForAvailable(defaultCallback, tnt.getNetwork());
@@ -2350,7 +2401,7 @@
NETWORK_CALLBACK_TIMEOUT_MS);
waitForAvailable(defaultCallback);
- setWifiMeteredStatusAndWait(ssid, oldMeteredValue);
+ setWifiMeteredStatusAndWait(ssid, oldMeteredValue, false /* waitForValidation */);
// Cleanup any prior test state from setOemNetworkPreference
clearOemNetworkPreference();
@@ -2832,6 +2883,24 @@
}
}
+ private static NetworkAgent createRestrictedNetworkAgent(final Context context) {
+ // Create test network agent with restricted network.
+ final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(
+ TEST_RESTRICTED_NW_IFACE_NAME))
+ .build();
+ final NetworkAgent agent = new NetworkAgent(context, Looper.getMainLooper(), TAG, nc,
+ new LinkProperties(), 10 /* score */, new NetworkAgentConfig.Builder().build(),
+ new NetworkProvider(context, Looper.getMainLooper(), TAG)) {};
+ runWithShellPermissionIdentity(() -> agent.register(),
+ android.Manifest.permission.MANAGE_TEST_NETWORKS);
+ agent.markConnected();
+
+ return agent;
+ }
+
@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
@Test
public void testUidsAllowedOnRestrictedNetworks() throws Exception {
@@ -2852,42 +2921,27 @@
ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
- final Handler h = new Handler(Looper.getMainLooper());
final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback();
- registerBestMatchingNetworkCallback(new NetworkRequest.Builder().clearCapabilities()
- .addTransportType(NetworkCapabilities.TRANSPORT_TEST).build(), testNetworkCb, h);
-
- // Create test network agent with restricted network.
- final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ final NetworkRequest testRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_TEST)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(
+ TEST_RESTRICTED_NW_IFACE_NAME))
.build();
- final NetworkScore score = new NetworkScore.Builder()
- .setExiting(false)
- .setTransportPrimary(false)
- .setKeepConnectedReason(NetworkScore.KEEP_CONNECTED_FOR_HANDOVER)
- .build();
- final NetworkAgent agent = new NetworkAgent(mContext, Looper.getMainLooper(),
- TAG, nc, new LinkProperties(), score, new NetworkAgentConfig.Builder().build(),
- new NetworkProvider(mContext, Looper.getMainLooper(), TAG)) {};
- runWithShellPermissionIdentity(() -> agent.register(),
- android.Manifest.permission.MANAGE_TEST_NETWORKS);
- agent.markConnected();
+ runWithShellPermissionIdentity(() -> requestNetwork(testRequest, testNetworkCb),
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS);
+ final NetworkAgent agent = createRestrictedNetworkAgent(mContext);
final Network network = agent.getNetwork();
try (Socket socket = new Socket()) {
- testNetworkCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
- entry -> network.equals(entry.getNetwork()));
// Verify that the network is restricted.
- final NetworkCapabilities testNetworkNc = mCm.getNetworkCapabilities(network);
- assertNotNull(testNetworkNc);
- assertFalse(testNetworkNc.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED));
+ testNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> network.equals(entry.getNetwork())
+ && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
// CtsNetTestCases package doesn't hold CONNECTIVITY_USE_RESTRICTED_NETWORKS, so it
// does not allow to bind socket to restricted network.
assertThrows(IOException.class, () -> network.bindSocket(socket));
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 7c380e3..1a131d8 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -1072,6 +1072,7 @@
Executors.newSingleThreadExecutor().let { executor ->
try {
val info = QosSocketInfo(agent.network!!, socket)
+ assertEquals(agent.network, info.getNetwork())
mCM.registerQosCallback(info, executor, qosCallback)
val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index 49c7271..9ff594a 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -39,6 +39,8 @@
import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT
import android.net.NetworkTemplate.WIFI_NETWORKID_ALL
import android.net.NetworkTemplate.buildTemplateCarrierMetered
+import android.net.NetworkTemplate.buildTemplateMobileAll
+import android.net.NetworkTemplate.buildTemplateMobileWildcard
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
import android.net.NetworkTemplate.buildTemplateWifi
import android.net.NetworkTemplate.buildTemplateWifiWildcard
@@ -171,6 +173,57 @@
}
@Test
+ fun testMobileMatches() {
+ val templateMobileImsi1 = buildTemplateMobileAll(TEST_IMSI1)
+ val templateMobileImsi2WithRatType = buildTemplateMobileWithRatType(TEST_IMSI2,
+ TelephonyManager.NETWORK_TYPE_UMTS)
+
+ val mobileImsi1 = buildNetworkState(TYPE_MOBILE, TEST_IMSI1, null /* ssid */,
+ OEM_NONE, true /* metered */)
+ val identMobile1 = buildNetworkIdentity(mockContext, mobileImsi1,
+ false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+ val mobileImsi2 = buildMobileNetworkState(TEST_IMSI2)
+ val identMobile2Umts = buildNetworkIdentity(mockContext, mobileImsi2,
+ false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+
+ val identWifiImsi1Ssid1 = buildNetworkIdentity(
+ mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
+
+ // Verify that the template matches type and the subscriberId.
+ templateMobileImsi1.assertMatches(identMobile1)
+ templateMobileImsi2WithRatType.assertMatches(identMobile2Umts)
+
+ // Verify that the template does not match the different subscriberId.
+ templateMobileImsi1.assertDoesNotMatch(identMobile2Umts)
+ templateMobileImsi2WithRatType.assertDoesNotMatch(identMobile1)
+
+ // Verify that the different type does not match.
+ templateMobileImsi1.assertDoesNotMatch(identWifiImsi1Ssid1)
+ }
+
+ @Test
+ fun testMobileWildcardMatches() {
+ val templateMobileWildcard = buildTemplateMobileWildcard()
+ val templateMobileNullImsiWithRatType = buildTemplateMobileWithRatType(null,
+ TelephonyManager.NETWORK_TYPE_UMTS)
+
+ val mobileImsi1 = buildMobileNetworkState(TEST_IMSI1)
+ val identMobile1 = buildNetworkIdentity(mockContext, mobileImsi1,
+ false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS)
+
+ // Verify that the template matches any subscriberId.
+ templateMobileWildcard.assertMatches(identMobile1)
+ templateMobileNullImsiWithRatType.assertMatches(identMobile1)
+
+ val identWifiImsi1Ssid1 = buildNetworkIdentity(
+ mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_SSID1), true, 0)
+
+ // Verify that the different type does not match.
+ templateMobileWildcard.assertDoesNotMatch(identWifiImsi1Ssid1)
+ templateMobileNullImsiWithRatType.assertDoesNotMatch(identWifiImsi1Ssid1)
+ }
+
+ @Test
fun testCarrierMeteredMatches() {
val templateCarrierImsi1Metered = buildTemplateCarrierMetered(TEST_IMSI1)
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 814d799..2aba0b4 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -350,8 +350,11 @@
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.MockingDetails;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.exceptions.misusing.UnfinishedStubbingException;
import org.mockito.stubbing.Answer;
import java.io.FileDescriptor;
@@ -1734,7 +1737,15 @@
}
private void returnRealCallingUid() {
- doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid();
+ try {
+ doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid();
+ } catch (UnfinishedStubbingException e) {
+ final MockingDetails details = Mockito.mockingDetails(mDeps);
+ Log.e("ConnectivityServiceTest", "UnfinishedStubbingException,"
+ + " Stubbings: " + TextUtils.join(", ", details.getStubbings())
+ + " Invocations: " + details.printInvocations(), e);
+ throw e;
+ }
}
private ConnectivityService.Dependencies makeDependencies() {
@@ -4848,7 +4859,6 @@
final TestableNetworkOfferCallback wifiCallback = new TestableNetworkOfferCallback(
TIMEOUT_MS /* timeout */, TEST_CALLBACK_TIMEOUT_MS /* noCallbackTimeout */);
- Log.e("ConnectivityService", "test registering " + cellProvider);
// Offer callbacks will run on the CS handler thread in this test.
cellProvider.registerNetworkOffer(cellScore, cellCaps, r -> r.run(), cellCallback);
wifiProvider.registerNetworkOffer(wifiScore, wifiCaps, r -> r.run(), wifiCallback);
@@ -6238,16 +6248,16 @@
mCm.unregisterNetworkCallback(networkCallback);
}
- private void expectNotifyNetworkStatus(List<Network> networks, String defaultIface,
+ private void expectNotifyNetworkStatus(List<Network> defaultNetworks, String defaultIface,
Integer vpnUid, String vpnIfname, List<String> underlyingIfaces) throws Exception {
- ArgumentCaptor<List<Network>> networksCaptor = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<List<Network>> defaultNetworksCaptor = ArgumentCaptor.forClass(List.class);
ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor =
ArgumentCaptor.forClass(List.class);
- verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(),
+ verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(defaultNetworksCaptor.capture(),
any(List.class), eq(defaultIface), vpnInfosCaptor.capture());
- assertSameElements(networks, networksCaptor.getValue());
+ assertSameElements(defaultNetworks, defaultNetworksCaptor.getValue());
List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
if (vpnUid != null) {
@@ -6263,8 +6273,8 @@
}
private void expectNotifyNetworkStatus(
- List<Network> networks, String defaultIface) throws Exception {
- expectNotifyNetworkStatus(networks, defaultIface, null, null, List.of());
+ List<Network> defaultNetworks, String defaultIface) throws Exception {
+ expectNotifyNetworkStatus(defaultNetworks, defaultIface, null, null, List.of());
}
@Test
@@ -12972,21 +12982,26 @@
assertLength(2, snapshots);
assertContainsAll(snapshots, cellSnapshot, wifiSnapshot);
- // Set cellular as suspended, verify the snapshots will not contain suspended networks.
- // TODO: Consider include SUSPENDED networks, which should be considered as
- // temporary shortage of connectivity of a connected network.
+ // Set cellular as suspended, verify the snapshots will contain suspended networks.
mCellNetworkAgent.suspend();
waitForIdle();
+ final NetworkCapabilities cellSuspendedNc =
+ mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork());
+ assertFalse(cellSuspendedNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ final NetworkStateSnapshot cellSuspendedSnapshot = new NetworkStateSnapshot(
+ mCellNetworkAgent.getNetwork(), cellSuspendedNc, cellLp,
+ null, ConnectivityManager.TYPE_MOBILE);
snapshots = mCm.getAllNetworkStateSnapshots();
- assertLength(1, snapshots);
- assertEquals(wifiSnapshot, snapshots.get(0));
+ assertLength(2, snapshots);
+ assertContainsAll(snapshots, cellSuspendedSnapshot, wifiSnapshot);
- // Disconnect wifi, verify the snapshots contain nothing.
+ // Disconnect wifi, verify the snapshots contain only cellular.
mWiFiNetworkAgent.disconnect();
waitForIdle();
snapshots = mCm.getAllNetworkStateSnapshots();
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- assertLength(0, snapshots);
+ assertLength(1, snapshots);
+ assertEquals(cellSuspendedSnapshot, snapshots.get(0));
mCellNetworkAgent.resume();
waitForIdle();
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index a9749c4..ecda338 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -32,6 +32,7 @@
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.net.ConnectivitySettingsManager.UIDS_ALLOWED_ON_RESTRICTED_NETWORKS;
import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_NETWORK;
import static android.net.INetd.PERMISSION_NONE;
import static android.net.INetd.PERMISSION_SYSTEM;
import static android.net.INetd.PERMISSION_UNINSTALLED;
@@ -39,8 +40,7 @@
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.SYSTEM_UID;
-import static com.android.server.connectivity.PermissionMonitor.NETWORK;
-import static com.android.server.connectivity.PermissionMonitor.SYSTEM;
+import static com.android.server.connectivity.PermissionMonitor.isHigherNetworkPermission;
import static junit.framework.Assert.fail;
@@ -55,12 +55,12 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.intThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -80,12 +80,14 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.util.ArraySet;
import android.util.SparseIntArray;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.net.module.util.CollectionUtils;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -98,11 +100,8 @@
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
-import java.util.ArrayList;
+import java.lang.reflect.Array;
import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -110,13 +109,19 @@
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class PermissionMonitorTest {
- private static final UserHandle MOCK_USER1 = UserHandle.of(0);
- private static final UserHandle MOCK_USER2 = UserHandle.of(1);
- private static final int MOCK_UID1 = 10001;
- private static final int MOCK_UID2 = 10086;
- private static final int SYSTEM_UID1 = 1000;
- private static final int SYSTEM_UID2 = 1008;
- private static final int VPN_UID = 10002;
+ private static final int MOCK_USER_ID1 = 0;
+ private static final int MOCK_USER_ID2 = 1;
+ private static final UserHandle MOCK_USER1 = UserHandle.of(MOCK_USER_ID1);
+ private static final UserHandle MOCK_USER2 = UserHandle.of(MOCK_USER_ID2);
+ private static final int MOCK_APPID1 = 10001;
+ private static final int MOCK_APPID2 = 10086;
+ private static final int SYSTEM_APPID1 = 1100;
+ private static final int SYSTEM_APPID2 = 1108;
+ private static final int VPN_APPID = 10002;
+ private static final int MOCK_UID1 = MOCK_USER1.getUid(MOCK_APPID1);
+ private static final int MOCK_UID2 = MOCK_USER1.getUid(MOCK_APPID2);
+ private static final int SYSTEM_APP_UID1 = MOCK_USER1.getUid(SYSTEM_APPID1);
+ private static final int VPN_UID = MOCK_USER1.getUid(VPN_APPID);
private static final String REAL_SYSTEM_PACKAGE_NAME = "android";
private static final String MOCK_PACKAGE1 = "appName1";
private static final String MOCK_PACKAGE2 = "appName2";
@@ -146,8 +151,7 @@
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
- when(mUserManager.getUserHandles(eq(true))).thenReturn(
- Arrays.asList(new UserHandle[] { MOCK_USER1, MOCK_USER2 }));
+ doReturn(List.of(MOCK_USER1)).when(mUserManager).getUserHandles(eq(true));
when(mContext.getSystemServiceName(SystemConfigManager.class))
.thenReturn(Context.SYSTEM_CONFIG_SERVICE);
when(mContext.getSystemService(Context.SYSTEM_CONFIG_SERVICE))
@@ -160,19 +164,15 @@
final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
doReturn(UserHandle.ALL).when(asUserCtx).getUser();
when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of());
+ // Set DEVICE_INITIAL_SDK_INT to Q that SYSTEM_UID won't have restricted network permission
+ // by default.
+ doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
- mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
+ mPermissionMonitor = new PermissionMonitor(mContext, mNetdService, mDeps);
mNetdMonitor = new NetdMonitor(mNetdService);
- when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(/* empty app list */ null);
- mPermissionMonitor.startMonitoring();
- }
-
- private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid,
- String... permissions) {
- return hasRestrictedNetworkPermission(
- partition, targetSdkVersion, "" /* packageName */, uid, permissions);
+ doReturn(List.of()).when(mPackageManager).getInstalledPackages(anyInt());
}
private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion,
@@ -223,13 +223,44 @@
private static PackageInfo buildPackageInfo(String packageName, int uid,
String... permissions) {
- final PackageInfo pkgInfo;
- pkgInfo = systemPackageInfoWithPermissions(permissions);
+ final PackageInfo pkgInfo = systemPackageInfoWithPermissions(permissions);
pkgInfo.packageName = packageName;
pkgInfo.applicationInfo.uid = uid;
return pkgInfo;
}
+ // TODO: Move this method to static lib.
+ private static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
+ final T[] result;
+ if (array != null) {
+ result = Arrays.copyOf(array, array.length + 1);
+ } else {
+ result = (T[]) Array.newInstance(kind, 1);
+ }
+ result[result.length - 1] = element;
+ return result;
+ }
+
+ private void buildAndMockPackageInfoWithPermissions(String packageName, int uid,
+ String... permissions) throws Exception {
+ final PackageInfo packageInfo = buildPackageInfo(packageName, uid, permissions);
+ // This will return the wrong UID for the package when queried with other users.
+ doReturn(packageInfo).when(mPackageManager)
+ .getPackageInfo(eq(packageName), anyInt() /* flag */);
+ final String[] oldPackages = mPackageManager.getPackagesForUid(uid);
+ // If it's duplicated package, no need to set it again.
+ if (CollectionUtils.contains(oldPackages, packageName)) return;
+
+ // Combine the package if this uid is shared with other packages.
+ final String[] newPackages = appendElement(String.class, oldPackages, packageName);
+ doReturn(newPackages).when(mPackageManager).getPackagesForUid(eq(uid));
+ }
+
+ private void addPackage(String packageName, int uid, String... permissions) throws Exception {
+ buildAndMockPackageInfoWithPermissions(packageName, uid, permissions);
+ mPermissionMonitor.onPackageAdded(packageName, uid);
+ }
+
@Test
public void testHasPermission() {
PackageInfo app = systemPackageInfoWithPermissions();
@@ -298,67 +329,77 @@
@Test
public void testHasRestrictedNetworkPermission() {
- assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK));
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL));
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, NETWORK_STACK));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE));
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK));
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, CHANGE_WIFI_STATE));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_P, MOCK_PACKAGE1, MOCK_UID1,
+ PERMISSION_MAINLINE_NETWORK_STACK));
- assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL));
+ PARTITION_SYSTEM, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL));
}
@Test
public void testHasRestrictedNetworkPermissionSystemUid() {
doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt();
- assertTrue(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_INTERNAL));
+ PARTITION_SYSTEM, VERSION_P, SYSTEM_PACKAGE1, SYSTEM_UID));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ PARTITION_SYSTEM, VERSION_P, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_P, SYSTEM_PACKAGE1, SYSTEM_UID,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS));
doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
- assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_INTERNAL));
+ PARTITION_SYSTEM, VERSION_Q, SYSTEM_PACKAGE1, SYSTEM_UID));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_SYSTEM, VERSION_Q, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ PARTITION_SYSTEM, VERSION_Q, SYSTEM_PACKAGE1, SYSTEM_UID,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS));
}
@Test
public void testHasRestrictedNetworkPermissionVendorApp() {
- assertTrue(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE));
+ PARTITION_VENDOR, VERSION_P, MOCK_PACKAGE1, MOCK_UID1));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, NETWORK_STACK));
+ PARTITION_VENDOR, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL));
+ PARTITION_VENDOR, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, NETWORK_STACK));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ PARTITION_VENDOR, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL));
assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE));
+ PARTITION_VENDOR, VERSION_P, MOCK_PACKAGE1, MOCK_UID1,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertTrue(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_P, MOCK_PACKAGE1, MOCK_UID1, CHANGE_WIFI_STATE));
- assertFalse(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL));
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1));
assertFalse(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE));
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CONNECTIVITY_INTERNAL));
+ assertFalse(hasRestrictedNetworkPermission(
+ PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE));
}
@Test
public void testHasRestrictedNetworkPermissionUidAllowedOnRestrictedNetworks() {
- mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(
- new ArraySet<>(new Integer[] { MOCK_UID1 }));
+ mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(Set.of(MOCK_UID1));
assertTrue(hasRestrictedNetworkPermission(
PARTITION_VENDOR, VERSION_Q, MOCK_PACKAGE1, MOCK_UID1));
assertTrue(hasRestrictedNetworkPermission(
@@ -419,32 +460,26 @@
@Test
public void testIsAppAllowedOnRestrictedNetworks() {
- mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(new ArraySet<>());
+ mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(Set.of());
assertFalse(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID1));
assertFalse(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID2));
- mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(
- new ArraySet<>(new Integer[] { MOCK_UID1 }));
+ mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(Set.of(MOCK_UID1));
assertTrue(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID1));
assertFalse(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID2));
- mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(
- new ArraySet<>(new Integer[] { MOCK_UID2 }));
+ mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(Set.of(MOCK_UID2));
assertFalse(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID1));
assertTrue(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID2));
- mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(
- new ArraySet<>(new Integer[] { 123 }));
+ mPermissionMonitor.updateUidsAllowedOnRestrictedNetworks(Set.of(123));
assertFalse(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID1));
assertFalse(wouldBeUidAllowedOnRestrictedNetworks(MOCK_UID2));
}
private void assertBackgroundPermission(boolean hasPermission, String name, int uid,
String... permissions) throws Exception {
- when(mPackageManager.getPackageInfo(eq(name), anyInt()))
- .thenReturn(packageInfoWithPermissions(
- REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM));
- mPermissionMonitor.onPackageAdded(name, uid);
+ addPackage(name, uid, permissions);
assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid));
}
@@ -469,21 +504,22 @@
}
private class NetdMonitor {
- private final HashMap<Integer, Boolean> mUidsNetworkPermission = new HashMap<>();
- private final HashMap<Integer, Integer> mAppIdsTrafficPermission = new HashMap<>();
+ private final SparseIntArray mUidsNetworkPermission = new SparseIntArray();
+ private final SparseIntArray mAppIdsTrafficPermission = new SparseIntArray();
+ private static final int DOES_NOT_EXIST = -2;
NetdMonitor(INetd mockNetd) throws Exception {
// Add hook to verify and track result of networkSetPermission.
doAnswer((InvocationOnMock invocation) -> {
final Object[] args = invocation.getArguments();
- final Boolean isSystem = args[0].equals(PERMISSION_SYSTEM);
+ final int permission = (int) args[0];
for (final int uid : (int[]) args[1]) {
// TODO: Currently, permission monitor will send duplicate commands for each uid
// corresponding to each user. Need to fix that and uncomment below test.
// if (mApps.containsKey(uid) && mApps.get(uid) == isSystem) {
// fail("uid " + uid + " is already set to " + isSystem);
// }
- mUidsNetworkPermission.put(uid, isSystem);
+ mUidsNetworkPermission.put(uid, permission);
}
return null;
}).when(mockNetd).networkSetPermissionForUser(anyInt(), any(int[].class));
@@ -497,7 +533,7 @@
// if (!mApps.containsKey(uid)) {
// fail("uid " + uid + " does not exist.");
// }
- mUidsNetworkPermission.remove(uid);
+ mUidsNetworkPermission.delete(uid);
}
return null;
}).when(mockNetd).networkClearPermissionForUser(any(int[].class));
@@ -513,11 +549,11 @@
}).when(mockNetd).trafficSetNetPermForUids(anyInt(), any(int[].class));
}
- public void expectNetworkPerm(Boolean permission, UserHandle[] users, int... appIds) {
+ public void expectNetworkPerm(int permission, UserHandle[] users, int... appIds) {
for (final UserHandle user : users) {
for (final int appId : appIds) {
final int uid = user.getUid(appId);
- if (!mUidsNetworkPermission.containsKey(uid)) {
+ if (mUidsNetworkPermission.get(uid, DOES_NOT_EXIST) == DOES_NOT_EXIST) {
fail("uid " + uid + " does not exist.");
}
if (mUidsNetworkPermission.get(uid) != permission) {
@@ -531,7 +567,7 @@
for (final UserHandle user : users) {
for (final int appId : appIds) {
final int uid = user.getUid(appId);
- if (mUidsNetworkPermission.containsKey(uid)) {
+ if (mUidsNetworkPermission.get(uid, DOES_NOT_EXIST) != DOES_NOT_EXIST) {
fail("uid " + uid + " has listed permissions, expected none.");
}
}
@@ -540,7 +576,7 @@
public void expectTrafficPerm(int permission, int... appIds) {
for (final int appId : appIds) {
- if (!mAppIdsTrafficPermission.containsKey(appId)) {
+ if (mAppIdsTrafficPermission.get(appId, DOES_NOT_EXIST) == DOES_NOT_EXIST) {
fail("appId " + appId + " does not exist.");
}
if (mAppIdsTrafficPermission.get(appId) != permission) {
@@ -554,85 +590,92 @@
@Test
public void testUserAndPackageAddRemove() throws Exception {
// MOCK_UID1: MOCK_PACKAGE1 only has network permission.
- // SYSTEM_UID: SYSTEM_PACKAGE1 has system permission.
- // SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission.
- doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(),
- eq(SYSTEM_PACKAGE1));
- doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(),
- eq(SYSTEM_PACKAGE2));
- doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(),
- eq(MOCK_PACKAGE1));
- doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString());
+ // SYSTEM_APP_UID1: SYSTEM_PACKAGE1 has system permission.
+ // SYSTEM_APP_UID1: SYSTEM_PACKAGE2 only has network permission.
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE);
+ buildAndMockPackageInfoWithPermissions(SYSTEM_PACKAGE1, SYSTEM_APP_UID1,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS);
+ buildAndMockPackageInfoWithPermissions(SYSTEM_PACKAGE2, SYSTEM_APP_UID1,
+ CHANGE_NETWORK_STATE);
- // Add SYSTEM_PACKAGE2, expect only have network permission.
+ // Add user MOCK_USER1.
mPermissionMonitor.onUserAdded(MOCK_USER1);
- addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, SYSTEM_UID);
+ // Add SYSTEM_PACKAGE2, expect only have network permission.
+ addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ SYSTEM_APPID1);
- // Add SYSTEM_PACKAGE1, expect permission escalate.
- addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, SYSTEM_UID);
+ // Add SYSTEM_PACKAGE1, expect permission upgrade.
+ addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ SYSTEM_APPID1);
+ // Add user MOCK_USER2.
mPermissionMonitor.onUserAdded(MOCK_USER2);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_UID);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_APPID1);
// Remove SYSTEM_PACKAGE2, expect keep system permission.
- when(mPackageManager.getPackagesForUid(MOCK_USER1.getUid(SYSTEM_UID)))
+ when(mPackageManager.getPackagesForUid(SYSTEM_APP_UID1))
.thenReturn(new String[]{SYSTEM_PACKAGE1});
- when(mPackageManager.getPackagesForUid(MOCK_USER2.getUid(SYSTEM_UID)))
+ when(mPackageManager.getPackagesForUid(MOCK_USER2.getUid(SYSTEM_APPID1)))
.thenReturn(new String[]{SYSTEM_PACKAGE1});
removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_PACKAGE2, SYSTEM_UID);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_UID);
+ SYSTEM_PACKAGE2, SYSTEM_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_APPID1);
// Add SYSTEM_PACKAGE2, expect keep system permission.
- addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_UID);
+ addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_PACKAGE2,
+ SYSTEM_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_APPID1);
- addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_UID);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- MOCK_UID1);
+ addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ MOCK_APPID1);
- // Remove MOCK_UID1, expect no permission left for all user.
- when(mPackageManager.getPackagesForUid(MOCK_USER1.getUid(MOCK_UID1)))
+ // Remove MOCK_PACKAGE1, expect no permission left for all user.
+ when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
+ when(mPackageManager.getPackagesForUid(MOCK_USER2.getUid(MOCK_APPID1)))
.thenReturn(new String[]{});
- when(mPackageManager.getPackagesForUid(MOCK_USER2.getUid(MOCK_UID1)))
- .thenReturn(new String[]{});
- mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID1);
+ removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_APPID1);
// Remove SYSTEM_PACKAGE1, expect permission downgrade.
- when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{SYSTEM_PACKAGE2});
+ when(mPackageManager.getPackagesForUid(
+ intThat(uid -> UserHandle.getAppId(uid) == SYSTEM_APPID1)))
+ .thenReturn(new String[]{SYSTEM_PACKAGE2});
removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_PACKAGE1, SYSTEM_UID);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- SYSTEM_UID);
+ SYSTEM_PACKAGE1, SYSTEM_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_APPID1);
mPermissionMonitor.onUserRemoved(MOCK_USER1);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER2}, SYSTEM_UID);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER2},
+ SYSTEM_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, SYSTEM_APPID1);
// Remove all packages, expect no permission left.
- when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{});
- removePackageForUsers(new UserHandle[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
- mNetdMonitor.expectNoNetworkPerm(
- new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_UID, MOCK_UID1);
+ when(mPackageManager.getPackagesForUid(
+ intThat(uid -> UserHandle.getAppId(uid) == SYSTEM_APPID1)))
+ .thenReturn(new String[]{});
+ removePackageForUsers(new UserHandle[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_APPID1,
+ MOCK_APPID1);
- // Remove last user, expect no redundant clearPermission is invoked.
+ // Remove last user, expect no permission change.
mPermissionMonitor.onUserRemoved(MOCK_USER2);
- mNetdMonitor.expectNoNetworkPerm(
- new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_UID, MOCK_UID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_APPID1,
+ MOCK_APPID1);
}
@Test
public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_UID1, CHANGE_NETWORK_STATE,
+ List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID1, CHANGE_NETWORK_STATE,
CONNECTIVITY_USE_RESTRICTED_NETWORKS),
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID2),
@@ -640,25 +683,22 @@
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1);
mPermissionMonitor.startMonitoring();
// Every app on user 0 except MOCK_UID2 are under VPN.
- final Set<UidRange> vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] {
+ final Set<UidRange> vpnRange1 = Set.of(
new UidRange(0, MOCK_UID2 - 1),
- new UidRange(MOCK_UID2 + 1, UserHandle.PER_USER_RANGE - 1)}));
- final Set<UidRange> vpnRange2 = Collections.singleton(new UidRange(MOCK_UID2, MOCK_UID2));
+ new UidRange(MOCK_UID2 + 1, UserHandle.PER_USER_RANGE - 1));
+ final Set<UidRange> vpnRange2 = Set.of(new UidRange(MOCK_UID2, MOCK_UID2));
// When VPN is connected, expect a rule to be set up for user app MOCK_UID1
mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange1, VPN_UID);
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"),
- aryEq(new int[] {MOCK_UID1}));
+ verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID1}));
reset(mNetdService);
// When MOCK_UID1 package is uninstalled and reinstalled, expect Netd to be updated
- mPermissionMonitor.onPackageRemoved(
- MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
- verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1}));
- mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"),
- aryEq(new int[] {MOCK_UID1}));
+ mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
+ verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[]{MOCK_UID1}));
+ mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_UID1);
+ verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID1}));
reset(mNetdService);
@@ -667,8 +707,7 @@
mPermissionMonitor.onVpnUidRangesRemoved("tun0", vpnRange1, VPN_UID);
verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1}));
mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange2, VPN_UID);
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"),
- aryEq(new int[] {MOCK_UID2}));
+ verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID2}));
reset(mNetdService);
@@ -681,23 +720,21 @@
@Test
public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_UID1, CHANGE_NETWORK_STATE,
+ List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID1, CHANGE_NETWORK_STATE,
NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS),
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)));
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1);
mPermissionMonitor.startMonitoring();
- final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1));
+ final Set<UidRange> vpnRange = Set.of(UidRange.createForUser(MOCK_USER1));
mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange, VPN_UID);
// Newly-installed package should have uid rules added
- mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"),
- aryEq(new int[] {MOCK_UID1}));
+ mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_UID1);
+ verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID1}));
// Removed package should have its uid rules removed
- mPermissionMonitor.onPackageRemoved(
- MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
+ mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1}));
}
@@ -705,138 +742,118 @@
// Normal package add/remove operations will trigger multiple intent for uids corresponding to
// each user. To simulate generic package operations, the onPackageAdded/Removed will need to be
// called multiple times with the uid corresponding to each user.
- private void addPackageForUsers(UserHandle[] users, String packageName, int uid) {
+ private void addPackageForUsers(UserHandle[] users, String packageName, int appId) {
for (final UserHandle user : users) {
- mPermissionMonitor.onPackageAdded(packageName, user.getUid(uid));
+ mPermissionMonitor.onPackageAdded(packageName, user.getUid(appId));
}
}
- private void removePackageForUsers(UserHandle[] users, String packageName, int uid) {
+ private void removePackageForUsers(UserHandle[] users, String packageName, int appId) {
for (final UserHandle user : users) {
- mPermissionMonitor.onPackageRemoved(packageName, user.getUid(uid));
+ mPermissionMonitor.onPackageRemoved(packageName, user.getUid(appId));
}
}
@Test
public void testPackagePermissionUpdate() throws Exception {
- // MOCK_UID1: MOCK_PACKAGE1 only has internet permission.
- // MOCK_UID2: MOCK_PACKAGE2 does not have any permission.
- // SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission.
- // SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission.
+ // MOCK_APPID1: MOCK_PACKAGE1 only has internet permission.
+ // MOCK_APPID2: MOCK_PACKAGE2 does not have any permission.
+ // SYSTEM_APPID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission
+ // SYSTEM_APPID2: SYSTEM_PACKAGE2 has only update device stats permission.
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
- netdPermissionsAppIds.put(MOCK_UID1, PERMISSION_INTERNET);
- netdPermissionsAppIds.put(MOCK_UID2, PERMISSION_NONE);
- netdPermissionsAppIds.put(SYSTEM_UID1, PERMISSION_TRAFFIC_ALL);
- netdPermissionsAppIds.put(SYSTEM_UID2, PERMISSION_UPDATE_DEVICE_STATS);
+ netdPermissionsAppIds.put(MOCK_APPID1, PERMISSION_INTERNET);
+ netdPermissionsAppIds.put(MOCK_APPID2, PERMISSION_NONE);
+ netdPermissionsAppIds.put(SYSTEM_APPID1, PERMISSION_TRAFFIC_ALL);
+ netdPermissionsAppIds.put(SYSTEM_APPID2, PERMISSION_UPDATE_DEVICE_STATS);
// Send the permission information to netd, expect permission updated.
mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, SYSTEM_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, SYSTEM_UID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, SYSTEM_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, SYSTEM_APPID2);
- // Update permission of MOCK_UID1, expect new permission show up.
- mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, PERMISSION_TRAFFIC_ALL);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ // Update permission of MOCK_APPID1, expect new permission show up.
+ mPermissionMonitor.sendPackagePermissionsForAppId(MOCK_APPID1, PERMISSION_TRAFFIC_ALL);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
- // Change permissions of SYSTEM_UID2, expect new permission show up and old permission
+ // Change permissions of SYSTEM_APPID2, expect new permission show up and old permission
// revoked.
- mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, PERMISSION_INTERNET);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, SYSTEM_UID2);
+ mPermissionMonitor.sendPackagePermissionsForAppId(SYSTEM_APPID2, PERMISSION_INTERNET);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, SYSTEM_APPID2);
- // Revoke permission from SYSTEM_UID1, expect no permission stored.
- mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, PERMISSION_NONE);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, SYSTEM_UID1);
- }
-
- private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions)
- throws Exception {
- PackageInfo packageInfo = packageInfoWithPermissions(
- REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM);
- when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo);
- when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName});
- return packageInfo;
- }
-
- private PackageInfo addPackage(String packageName, int uid, String[] permissions)
- throws Exception {
- PackageInfo packageInfo = setPackagePermissions(packageName, uid, permissions);
- mPermissionMonitor.onPackageAdded(packageName, uid);
- return packageInfo;
+ // Revoke permission from SYSTEM_APPID1, expect no permission stored.
+ mPermissionMonitor.sendPackagePermissionsForAppId(SYSTEM_APPID1, PERMISSION_NONE);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, SYSTEM_APPID1);
}
@Test
public void testPackageInstall() throws Exception {
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET, UPDATE_DEVICE_STATS);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
- addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET});
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID2);
+ addPackage(MOCK_PACKAGE2, MOCK_UID2, INTERNET);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID2);
}
@Test
public void testPackageInstallSharedUid() throws Exception {
- PackageInfo packageInfo1 = addPackage(MOCK_PACKAGE1, MOCK_UID1,
- new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET, UPDATE_DEVICE_STATS);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
- // Install another package with the same uid and no permissions should not cause the UID to
- // lose permissions.
- PackageInfo packageInfo2 = systemPackageInfoWithPermissions();
- when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
- when(mPackageManager.getPackagesForUid(MOCK_UID1))
- .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
- mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ // Install another package with the same uid and no permissions should not cause the app id
+ // to lose permissions.
+ addPackage(MOCK_PACKAGE2, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
}
@Test
public void testPackageUninstallBasic() throws Exception {
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET, UPDATE_DEVICE_STATS);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
}
@Test
public void testPackageRemoveThenAdd() throws Exception {
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET, UPDATE_DEVICE_STATS);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET});
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
}
@Test
public void testPackageUpdate() throws Exception {
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {});
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET});
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
}
@Test
public void testPackageUninstallWithMultiplePackages() throws Exception {
- addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
+ addPackage(MOCK_PACKAGE1, MOCK_UID1, INTERNET, UPDATE_DEVICE_STATS);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+
+ // Install another package with the same uid but different permissions.
+ addPackage(MOCK_PACKAGE2, MOCK_UID1, INTERNET);
mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
- // Mock another package with the same uid but different permissions.
- PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET);
- when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
- when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{
- MOCK_PACKAGE2});
-
+ // Uninstall MOCK_PACKAGE1 and expect only INTERNET permission left.
+ when(mPackageManager.getPackagesForUid(eq(MOCK_UID1)))
+ .thenReturn(new String[]{MOCK_PACKAGE2});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
}
@Test
@@ -853,15 +870,14 @@
@Test
public void testUpdateUidPermissionsFromSystemConfig() throws Exception {
- when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(new ArrayList<>());
when(mSystemConfigManager.getSystemPermissionUids(eq(INTERNET)))
.thenReturn(new int[]{ MOCK_UID1, MOCK_UID2 });
when(mSystemConfigManager.getSystemPermissionUids(eq(UPDATE_DEVICE_STATS)))
.thenReturn(new int[]{ MOCK_UID2 });
mPermissionMonitor.startMonitoring();
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID2);
}
private BroadcastReceiver expectBroadcastReceiver(String... actions) {
@@ -881,6 +897,7 @@
@Test
public void testIntentReceiver() throws Exception {
+ mPermissionMonitor.startMonitoring();
final BroadcastReceiver receiver = expectBroadcastReceiver(
Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED);
@@ -888,18 +905,18 @@
final Intent addedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED,
Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */));
addedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1);
- setPackagePermissions(MOCK_PACKAGE1, MOCK_UID1,
- new String[] { INTERNET, UPDATE_DEVICE_STATS });
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1, INTERNET,
+ UPDATE_DEVICE_STATS);
receiver.onReceive(mContext, addedIntent);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
// Verify receiving PACKAGE_REMOVED intent.
- when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(null);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
final Intent removedIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */));
removedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1);
receiver.onReceive(mContext, removedIntent);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
}
private ContentObserver expectRegisterContentObserver(Uri expectedUri) {
@@ -910,138 +927,132 @@
return captor.getValue();
}
- private void buildAndMockPackageInfoWithPermissions(String packageName, int uid,
- String... permissions) throws Exception {
- final PackageInfo packageInfo = setPackagePermissions(packageName, uid, permissions);
- packageInfo.packageName = packageName;
- packageInfo.applicationInfo.uid = uid;
- }
-
@Test
public void testUidsAllowedOnRestrictedNetworksChanged() throws Exception {
+ mPermissionMonitor.startMonitoring();
final ContentObserver contentObserver = expectRegisterContentObserver(
Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS));
- mPermissionMonitor.onUserAdded(MOCK_USER1);
// Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1);
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID2);
// MOCK_UID1 is listed in setting that allow to use restricted networks, MOCK_UID1
// should have SYSTEM permission.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
- new ArraySet<>(new Integer[] { MOCK_UID1 }));
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of(MOCK_UID1));
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID2);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID2);
// MOCK_UID2 is listed in setting that allow to use restricted networks, MOCK_UID2
// should have SYSTEM permission but MOCK_UID1 should revoke permission.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
- new ArraySet<>(new Integer[] { MOCK_UID2 }));
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of(MOCK_UID2));
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID2);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1);
// No uid lists in setting, should revoke permission from all uids.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of());
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1, MOCK_UID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1, MOCK_APPID2);
}
@Test
public void testUidsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception {
+ mPermissionMonitor.startMonitoring();
final ContentObserver contentObserver = expectRegisterContentObserver(
Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS));
- mPermissionMonitor.onUserAdded(MOCK_USER1);
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE);
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID1);
- when(mPackageManager.getPackagesForUid(MOCK_UID1))
- .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
// MOCK_PACKAGE1 have CHANGE_NETWORK_STATE, MOCK_UID1 should have NETWORK permission.
- addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
// MOCK_UID1 is listed in setting that allow to use restricted networks, MOCK_UID1
// should upgrade to SYSTEM permission.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
- new ArraySet<>(new Integer[] { MOCK_UID1 }));
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of(MOCK_UID1));
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
// No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of());
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
// MOCK_PACKAGE1 removed, should revoke permission from MOCK_UID1.
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE2});
- removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1);
}
@Test
public void testUidsAllowedOnRestrictedNetworksChangedWithMultipleUsers() throws Exception {
+ mPermissionMonitor.startMonitoring();
final ContentObserver contentObserver = expectRegisterContentObserver(
Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS));
- // One user MOCK_USER1
- mPermissionMonitor.onUserAdded(MOCK_USER1);
// Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2.
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1);
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID2);
// MOCK_UID1 is listed in setting that allow to use restricted networks, MOCK_UID1
- // in MOCK_USER1 should have SYSTEM permission and MOCK_UID2 has no permissions.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
- new ArraySet<>(new Integer[] { MOCK_UID1 }));
+ // should have SYSTEM permission and MOCK_UID2 has no permissions.
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of(MOCK_UID1));
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID2);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID2);
// Add user MOCK_USER2.
mPermissionMonitor.onUserAdded(MOCK_USER2);
- // MOCK_UID1 in both users should all have SYSTEM permission and MOCK_UID2 has no
+ // MOCK_APPID1 in both users should all have SYSTEM permission and MOCK_APPID2 has no
// permissions in either user.
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID1);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID2);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ MOCK_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_APPID2);
- // MOCK_UID2 is listed in setting that allow to use restricted networks, MOCK_UID2
- // in both users should have SYSTEM permission and MOCK_UID1 has no permissions.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
- new ArraySet<>(new Integer[] { MOCK_UID2 }));
+ // MOCK_UID2 is listed in setting that allow to use restricted networks, MOCK_APPID2
+ // in both users should have SYSTEM permission and MOCK_APPID1 has no permissions in either
+ // user.
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of(MOCK_UID2));
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID2);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ MOCK_APPID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_APPID1);
// Remove user MOCK_USER1
mPermissionMonitor.onUserRemoved(MOCK_USER1);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER2}, MOCK_UID2);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER2}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER2},
+ MOCK_APPID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER2}, MOCK_APPID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID2);
// No uid lists in setting, should revoke permission from all uids.
- when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
+ when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(Set.of());
contentObserver.onChange(true /* selfChange */);
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER2}, MOCK_UID1, MOCK_UID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER2}, MOCK_APPID1, MOCK_APPID2);
}
@Test
public void testOnExternalApplicationsAvailable() throws Exception {
- final BroadcastReceiver receiver = expectBroadcastReceiver(
- Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-
// Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
// and have different uids. There has no permission for both uids.
- when(mUserManager.getUserHandles(eq(true))).thenReturn(List.of(MOCK_USER1));
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID2)));
mPermissionMonitor.startMonitoring();
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1, MOCK_UID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID1, MOCK_UID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1, MOCK_APPID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1, MOCK_APPID2);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST,
@@ -1051,21 +1062,21 @@
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID2, CHANGE_NETWORK_STATE,
UPDATE_DEVICE_STATS);
receiver.onReceive(mContext, externalIntent);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_UID2);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID2);
}
@Test
public void testOnExternalApplicationsAvailable_AppsNotRegisteredOnStartMonitoring()
throws Exception {
+ mPermissionMonitor.startMonitoring();
final BroadcastReceiver receiver = expectBroadcastReceiver(
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- // One user MOCK_USER1
- mPermissionMonitor.onUserAdded(MOCK_USER1);
-
// Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
// and have different uids. There has no permission for both uids.
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1,
@@ -1078,58 +1089,56 @@
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST,
new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
receiver.onReceive(mContext, externalIntent);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_UID2);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID2);
}
@Test
public void testOnExternalApplicationsAvailableWithSharedUid()
throws Exception {
- final BroadcastReceiver receiver = expectBroadcastReceiver(
- Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-
// Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
// storage and shared on MOCK_UID1. There has no permission for MOCK_UID1.
- when(mUserManager.getUserHandles(eq(true))).thenReturn(List.of(MOCK_USER1));
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID1)));
mPermissionMonitor.startMonitoring();
- mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[] {MOCK_PACKAGE1});
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE);
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID1, UPDATE_DEVICE_STATS);
- when(mPackageManager.getPackagesForUid(MOCK_UID1))
- .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
receiver.onReceive(mContext, externalIntent);
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID1);
}
@Test
public void testOnExternalApplicationsAvailableWithSharedUid_DifferentStorage()
throws Exception {
- final BroadcastReceiver receiver = expectBroadcastReceiver(
- Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-
// Initial the permission state. MOCK_PACKAGE1 is installed on external storage and
// MOCK_PACKAGE2 is installed on device. These two packages are shared on MOCK_UID1.
// MOCK_UID1 has NETWORK and INTERNET permissions.
- when(mUserManager.getUserHandles(eq(true))).thenReturn(List.of(MOCK_USER1));
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE,
INTERNET)));
mPermissionMonitor.startMonitoring();
- mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[] {MOCK_PACKAGE1});
@@ -1137,10 +1146,22 @@
CONNECTIVITY_USE_RESTRICTED_NETWORKS, UPDATE_DEVICE_STATS);
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE,
INTERNET);
- when(mPackageManager.getPackagesForUid(MOCK_UID1))
- .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
receiver.onReceive(mContext, externalIntent);
- mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
+ MOCK_APPID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ }
+
+ @Test
+ public void testIsHigherNetworkPermission() {
+ assertFalse(isHigherNetworkPermission(PERMISSION_NONE, PERMISSION_NONE));
+ assertFalse(isHigherNetworkPermission(PERMISSION_NONE, PERMISSION_NETWORK));
+ assertFalse(isHigherNetworkPermission(PERMISSION_NONE, PERMISSION_SYSTEM));
+ assertTrue(isHigherNetworkPermission(PERMISSION_NETWORK, PERMISSION_NONE));
+ assertFalse(isHigherNetworkPermission(PERMISSION_NETWORK, PERMISSION_NETWORK));
+ assertFalse(isHigherNetworkPermission(PERMISSION_NETWORK, PERMISSION_SYSTEM));
+ assertTrue(isHigherNetworkPermission(PERMISSION_SYSTEM, PERMISSION_NONE));
+ assertTrue(isHigherNetworkPermission(PERMISSION_SYSTEM, PERMISSION_NETWORK));
+ assertFalse(isHigherNetworkPermission(PERMISSION_SYSTEM, PERMISSION_SYSTEM));
}
}