Register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
PermissionMonitor register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer to listen setting changed callback. Then update or revoke permission for those apps. Bug: 185149952 Test: atest FrameworksNetTests Change-Id: I4b6a21bd3f47b7bcaac36fcabf1202a5a84a4520
This commit is contained in:
@@ -24,6 +24,7 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS;
|
|||||||
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
|
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
|
||||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||||
import static android.content.pm.PackageManager.MATCH_ANY_USER;
|
import static android.content.pm.PackageManager.MATCH_ANY_USER;
|
||||||
|
import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS;
|
||||||
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
||||||
import static android.os.Process.INVALID_UID;
|
import static android.os.Process.INVALID_UID;
|
||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
@@ -39,6 +40,7 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.database.ContentObserver;
|
||||||
import android.net.ConnectivitySettingsManager;
|
import android.net.ConnectivitySettingsManager;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
import android.net.UidRange;
|
import android.net.UidRange;
|
||||||
@@ -49,6 +51,7 @@ import android.os.ServiceSpecificException;
|
|||||||
import android.os.SystemConfigManager;
|
import android.os.SystemConfigManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -68,7 +71,6 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class to inform Netd of UID permisisons.
|
* A utility class to inform Netd of UID permisisons.
|
||||||
* Does a mass update at boot and then monitors for app install/remove.
|
* Does a mass update at boot and then monitors for app install/remove.
|
||||||
@@ -145,6 +147,22 @@ public class PermissionMonitor {
|
|||||||
public int getDeviceFirstSdkInt() {
|
public int getDeviceFirstSdkInt() {
|
||||||
return Build.VERSION.FIRST_SDK_INT;
|
return Build.VERSION.FIRST_SDK_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get apps allowed to use restricted networks via ConnectivitySettingsManager.
|
||||||
|
*/
|
||||||
|
public Set<String> getAppsAllowedOnRestrictedNetworks(@NonNull Context context) {
|
||||||
|
return ConnectivitySettingsManager.getAppsAllowedOnRestrictedNetworks(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register ContentObserver for given Uri.
|
||||||
|
*/
|
||||||
|
public void registerContentObserver(@NonNull Context context, @NonNull Uri uri,
|
||||||
|
boolean notifyForDescendants, @NonNull ContentObserver observer) {
|
||||||
|
context.getContentResolver().registerContentObserver(
|
||||||
|
uri, notifyForDescendants, observer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
|
public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
|
||||||
@@ -167,18 +185,30 @@ public class PermissionMonitor {
|
|||||||
public synchronized void startMonitoring() {
|
public synchronized void startMonitoring() {
|
||||||
log("Monitoring");
|
log("Monitoring");
|
||||||
|
|
||||||
|
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
|
||||||
final IntentFilter intentFilter = new IntentFilter();
|
final IntentFilter intentFilter = new IntentFilter();
|
||||||
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||||
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||||
intentFilter.addDataScheme("package");
|
intentFilter.addDataScheme("package");
|
||||||
mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */).registerReceiver(
|
userAllContext.registerReceiver(
|
||||||
mIntentReceiver, intentFilter, null /* broadcastPermission */,
|
mIntentReceiver, intentFilter, null /* broadcastPermission */,
|
||||||
null /* scheduler */);
|
null /* scheduler */);
|
||||||
|
|
||||||
|
// Register APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
|
||||||
|
mDeps.registerContentObserver(
|
||||||
|
userAllContext,
|
||||||
|
Settings.Secure.getUriFor(APPS_ALLOWED_ON_RESTRICTED_NETWORKS),
|
||||||
|
false /* notifyForDescendants */,
|
||||||
|
new ContentObserver(null) {
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
onSettingChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Read APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update
|
// Read APPS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update
|
||||||
// mAppsAllowedOnRestrictedNetworks.
|
// mAppsAllowedOnRestrictedNetworks.
|
||||||
updateAppsAllowedOnRestrictedNetworks(
|
updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext));
|
||||||
ConnectivitySettingsManager.getAppsAllowedOnRestrictedNetworks(mContext));
|
|
||||||
|
|
||||||
List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS
|
List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS
|
||||||
| MATCH_ANY_USER);
|
| MATCH_ANY_USER);
|
||||||
@@ -435,6 +465,20 @@ public class PermissionMonitor {
|
|||||||
mAllApps.add(UserHandle.getAppId(uid));
|
mAllApps.add(UserHandle.getAppId(uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Boolean highestUidNetworkPermission(int uid) {
|
||||||
|
Boolean permission = null;
|
||||||
|
final String[] packages = mPackageManager.getPackagesForUid(uid);
|
||||||
|
if (!CollectionUtils.isEmpty(packages)) {
|
||||||
|
for (String name : packages) {
|
||||||
|
permission = highestPermissionForUid(permission, name);
|
||||||
|
if (permission == SYSTEM) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return permission;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a package is removed.
|
* Called when a package is removed.
|
||||||
*
|
*
|
||||||
@@ -465,19 +509,14 @@ public class PermissionMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<Integer, Boolean> apps = new HashMap<>();
|
Map<Integer, Boolean> apps = new HashMap<>();
|
||||||
Boolean permission = null;
|
final Boolean permission = highestUidNetworkPermission(uid);
|
||||||
String[] packages = mPackageManager.getPackagesForUid(uid);
|
if (permission == SYSTEM) {
|
||||||
if (packages != null && packages.length > 0) {
|
// An app with this UID still has the SYSTEM permission.
|
||||||
for (String name : packages) {
|
// Therefore, this UID must already have the SYSTEM permission.
|
||||||
permission = highestPermissionForUid(permission, name);
|
// Nothing to do.
|
||||||
if (permission == SYSTEM) {
|
return;
|
||||||
// An app with this UID still has the SYSTEM permission.
|
|
||||||
// Therefore, this UID must already have the SYSTEM permission.
|
|
||||||
// Nothing to do.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permission == mApps.get(uid)) {
|
if (permission == mApps.get(uid)) {
|
||||||
// The permissions of this UID have not changed. Nothing to do.
|
// The permissions of this UID have not changed. Nothing to do.
|
||||||
return;
|
return;
|
||||||
@@ -730,6 +769,38 @@ public class PermissionMonitor {
|
|||||||
return mVpnUidRanges.get(iface);
|
return mVpnUidRanges.get(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void onSettingChanged() {
|
||||||
|
// Step1. Update apps allowed to use restricted networks and compute the set of packages to
|
||||||
|
// update.
|
||||||
|
final Set<String> packagesToUpdate = new ArraySet<>(mAppsAllowedOnRestrictedNetworks);
|
||||||
|
updateAppsAllowedOnRestrictedNetworks(mDeps.getAppsAllowedOnRestrictedNetworks(mContext));
|
||||||
|
packagesToUpdate.addAll(mAppsAllowedOnRestrictedNetworks);
|
||||||
|
|
||||||
|
final Map<Integer, Boolean> updatedApps = new HashMap<>();
|
||||||
|
final Map<Integer, Boolean> removedApps = new HashMap<>();
|
||||||
|
|
||||||
|
// Step2. For each package to update, find out its new permission.
|
||||||
|
for (String app : packagesToUpdate) {
|
||||||
|
final PackageInfo info = getPackageInfo(app);
|
||||||
|
if (info == null || info.applicationInfo == null) continue;
|
||||||
|
|
||||||
|
final int uid = info.applicationInfo.uid;
|
||||||
|
final Boolean permission = highestUidNetworkPermission(uid);
|
||||||
|
|
||||||
|
if (null == permission) {
|
||||||
|
removedApps.put(uid, NETWORK); // Doesn't matter which permission is set here.
|
||||||
|
mApps.remove(uid);
|
||||||
|
} else {
|
||||||
|
updatedApps.put(uid, permission);
|
||||||
|
mApps.put(uid, permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step3. Update or revoke permission for uids with netd.
|
||||||
|
update(mUsers, updatedApps, true /* add */);
|
||||||
|
update(mUsers, removedApps, false /* add */);
|
||||||
|
}
|
||||||
|
|
||||||
/** Dump info to dumpsys */
|
/** Dump info to dumpsys */
|
||||||
public void dump(IndentingPrintWriter pw) {
|
public void dump(IndentingPrintWriter pw) {
|
||||||
pw.println("Interface filtering rules:");
|
pw.println("Interface filtering rules:");
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
|
|||||||
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED;
|
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED;
|
||||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||||
import static android.content.pm.PackageManager.MATCH_ANY_USER;
|
import static android.content.pm.PackageManager.MATCH_ANY_USER;
|
||||||
|
import static android.net.ConnectivitySettingsManager.APPS_ALLOWED_ON_RESTRICTED_NETWORKS;
|
||||||
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
|
|
||||||
@@ -44,8 +45,10 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.AdditionalMatchers.aryEq;
|
import static org.mockito.AdditionalMatchers.aryEq;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
@@ -62,6 +65,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.ContentObserver;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
import android.net.UidRange;
|
import android.net.UidRange;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -69,8 +73,6 @@ import android.os.Build;
|
|||||||
import android.os.SystemConfigManager;
|
import android.os.SystemConfigManager;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.test.mock.MockContentResolver;
|
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
@@ -78,9 +80,6 @@ import androidx.test.InstrumentationRegistry;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.internal.util.test.FakeSettingsProvider;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -127,7 +126,6 @@ public class PermissionMonitorTest {
|
|||||||
@Mock private SystemConfigManager mSystemConfigManager;
|
@Mock private SystemConfigManager mSystemConfigManager;
|
||||||
|
|
||||||
private PermissionMonitor mPermissionMonitor;
|
private PermissionMonitor mPermissionMonitor;
|
||||||
private MockContentResolver mContentResolver;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -144,11 +142,7 @@ public class PermissionMonitorTest {
|
|||||||
final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
|
final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
|
||||||
doReturn(UserHandle.ALL).when(asUserCtx).getUser();
|
doReturn(UserHandle.ALL).when(asUserCtx).getUser();
|
||||||
when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
|
when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
|
||||||
FakeSettingsProvider.clearSettingsProvider();
|
|
||||||
mContentResolver = new MockContentResolver();
|
|
||||||
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
|
||||||
when(mContext.getContentResolver()).thenReturn(mContentResolver);
|
|
||||||
|
|
||||||
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
|
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
|
||||||
|
|
||||||
@@ -156,11 +150,6 @@ public class PermissionMonitorTest {
|
|||||||
mPermissionMonitor.startMonitoring();
|
mPermissionMonitor.startMonitoring();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
FakeSettingsProvider.clearSettingsProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid,
|
private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid,
|
||||||
String... permissions) {
|
String... permissions) {
|
||||||
return hasRestrictedNetworkPermission(
|
return hasRestrictedNetworkPermission(
|
||||||
@@ -911,4 +900,102 @@ public class PermissionMonitorTest {
|
|||||||
mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 });
|
mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Test
|
||||||
|
public void testAppsAllowedOnRestrictedNetworksChanged() throws Exception {
|
||||||
|
final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService);
|
||||||
|
final ArgumentCaptor<ContentObserver> captor =
|
||||||
|
ArgumentCaptor.forClass(ContentObserver.class);
|
||||||
|
verify(mDeps, times(1)).registerContentObserver(any(),
|
||||||
|
argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)),
|
||||||
|
anyBoolean(), captor.capture());
|
||||||
|
final ContentObserver contentObserver = captor.getValue();
|
||||||
|
|
||||||
|
mPermissionMonitor.onUserAdded(MOCK_USER1);
|
||||||
|
// Prepare PackageInfo for MOCK_PACKAGE1
|
||||||
|
final PackageInfo packageInfo = buildPackageInfo(
|
||||||
|
false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1);
|
||||||
|
packageInfo.packageName = MOCK_PACKAGE1;
|
||||||
|
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo);
|
||||||
|
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE1});
|
||||||
|
// Prepare PackageInfo for MOCK_PACKAGE2
|
||||||
|
final PackageInfo packageInfo2 = buildPackageInfo(
|
||||||
|
false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1);
|
||||||
|
packageInfo2.packageName = MOCK_PACKAGE2;
|
||||||
|
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
|
||||||
|
when(mPackageManager.getPackagesForUid(MOCK_UID2)).thenReturn(new String[]{MOCK_PACKAGE2});
|
||||||
|
|
||||||
|
// MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1
|
||||||
|
// should have SYSTEM permission.
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
|
||||||
|
new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
|
||||||
|
contentObserver.onChange(true /* selfChange */);
|
||||||
|
mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
|
||||||
|
|
||||||
|
// MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID2
|
||||||
|
// should have SYSTEM permission but MOCK_UID1 should revoke permission.
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
|
||||||
|
new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
|
||||||
|
contentObserver.onChange(true /* selfChange */);
|
||||||
|
mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
|
||||||
|
mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
|
||||||
|
// No app lists in setting, should revoke permission from all uids.
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
|
||||||
|
contentObserver.onChange(true /* selfChange */);
|
||||||
|
mNetdMonitor.expectNoPermission(
|
||||||
|
new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAppsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception {
|
||||||
|
final NetdMonitor mNetdMonitor = new NetdMonitor(mNetdService);
|
||||||
|
final ArgumentCaptor<ContentObserver> captor =
|
||||||
|
ArgumentCaptor.forClass(ContentObserver.class);
|
||||||
|
verify(mDeps, times(1)).registerContentObserver(any(),
|
||||||
|
argThat(uri -> uri.getEncodedPath().contains(APPS_ALLOWED_ON_RESTRICTED_NETWORKS)),
|
||||||
|
anyBoolean(), captor.capture());
|
||||||
|
final ContentObserver contentObserver = captor.getValue();
|
||||||
|
|
||||||
|
mPermissionMonitor.onUserAdded(MOCK_USER1);
|
||||||
|
// Prepare PackageInfo for MOCK_PACKAGE1 and MOCK_PACKAGE2 with shared uid MOCK_UID1.
|
||||||
|
final PackageInfo packageInfo = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE);
|
||||||
|
packageInfo.applicationInfo.uid = MOCK_USER1.getUid(MOCK_UID1);
|
||||||
|
packageInfo.packageName = MOCK_PACKAGE1;
|
||||||
|
final PackageInfo packageInfo2 = buildPackageInfo(
|
||||||
|
false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1);
|
||||||
|
packageInfo2.packageName = MOCK_PACKAGE2;
|
||||||
|
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), anyInt())).thenReturn(packageInfo);
|
||||||
|
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
|
||||||
|
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.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
|
||||||
|
// MOCK_PACKAGE2 is listed in setting that allow to use restricted networks, MOCK_UID1
|
||||||
|
// should upgrade to SYSTEM permission.
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
|
||||||
|
new ArraySet<>(new String[] { MOCK_PACKAGE2 }));
|
||||||
|
contentObserver.onChange(true /* selfChange */);
|
||||||
|
mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
|
||||||
|
// MOCK_PACKAGE1 is listed in setting that allow to use restricted networks, MOCK_UID1
|
||||||
|
// should still have SYSTEM permission.
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(
|
||||||
|
new ArraySet<>(new String[] { MOCK_PACKAGE1 }));
|
||||||
|
contentObserver.onChange(true /* selfChange */);
|
||||||
|
mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
|
||||||
|
// No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission.
|
||||||
|
when(mDeps.getAppsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
|
||||||
|
contentObserver.onChange(true /* selfChange */);
|
||||||
|
mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
|
||||||
|
// 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.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user