Merge "PermissionMonitor: Limit preinstalled apps network permissions"
This commit is contained in:
@@ -24,6 +24,7 @@ import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
|||||||
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -34,6 +35,7 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -155,9 +157,8 @@ public class PermissionMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean isPreinstalledSystemApp(PackageInfo app) {
|
static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
|
||||||
int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
|
return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
|
||||||
return (flags & (FLAG_SYSTEM | FLAG_UPDATED_SYSTEM_APP)) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -177,7 +178,13 @@ public class PermissionMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasRestrictedNetworkPermission(PackageInfo app) {
|
private boolean hasRestrictedNetworkPermission(PackageInfo app) {
|
||||||
if (isPreinstalledSystemApp(app)) return true;
|
// TODO : remove this check in the future(b/31479477). All apps should just
|
||||||
|
// request the appropriate permission for their use case since android Q.
|
||||||
|
if (app.applicationInfo != null
|
||||||
|
&& app.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q
|
||||||
|
&& isVendorApp(app.applicationInfo)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return hasPermission(app, CONNECTIVITY_INTERNAL)
|
return hasPermission(app, CONNECTIVITY_INTERNAL)
|
||||||
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
|
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
|
||||||
}
|
}
|
||||||
@@ -186,13 +193,8 @@ public class PermissionMonitor {
|
|||||||
// This function defines what it means to hold the permission to use
|
// This function defines what it means to hold the permission to use
|
||||||
// background networks.
|
// background networks.
|
||||||
return hasPermission(app, CHANGE_NETWORK_STATE)
|
return hasPermission(app, CHANGE_NETWORK_STATE)
|
||||||
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)
|
|
||||||
|| hasPermission(app, CONNECTIVITY_INTERNAL)
|
|
||||||
|| hasPermission(app, NETWORK_STACK)
|
|| hasPermission(app, NETWORK_STACK)
|
||||||
// TODO : remove this check (b/31479477). Not all preinstalled apps should
|
|| hasRestrictedNetworkPermission(app);
|
||||||
// have access to background networks, they should just request the appropriate
|
|
||||||
// permission for their use case from the list above.
|
|
||||||
|| isPreinstalledSystemApp(app);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasUseBackgroundNetworksPermission(int uid) {
|
public boolean hasUseBackgroundNetworksPermission(int uid) {
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ import static android.Manifest.permission.CHANGE_WIFI_STATE;
|
|||||||
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
||||||
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
|
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
|
||||||
import static android.Manifest.permission.NETWORK_STACK;
|
import static android.Manifest.permission.NETWORK_STACK;
|
||||||
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM;
|
||||||
|
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT;
|
||||||
|
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR;
|
||||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -34,6 +36,7 @@ import android.content.Context;
|
|||||||
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.os.Build;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -48,6 +51,10 @@ import org.mockito.MockitoAnnotations;
|
|||||||
public class PermissionMonitorTest {
|
public class PermissionMonitorTest {
|
||||||
private static final int MOCK_UID = 10001;
|
private static final int MOCK_UID = 10001;
|
||||||
private static final String[] MOCK_PACKAGE_NAMES = new String[] { "com.foo.bar" };
|
private static final String[] MOCK_PACKAGE_NAMES = new String[] { "com.foo.bar" };
|
||||||
|
private static final String PARTITION_SYSTEM = "system";
|
||||||
|
private static final String PARTITION_OEM = "oem";
|
||||||
|
private static final String PARTITION_PRODUCT = "product";
|
||||||
|
private static final String PARTITION_VENDOR = "vendor";
|
||||||
|
|
||||||
@Mock private Context mContext;
|
@Mock private Context mContext;
|
||||||
@Mock private PackageManager mPackageManager;
|
@Mock private PackageManager mPackageManager;
|
||||||
@@ -62,23 +69,37 @@ public class PermissionMonitorTest {
|
|||||||
mPermissionMonitor = new PermissionMonitor(mContext, null);
|
mPermissionMonitor = new PermissionMonitor(mContext, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectPermission(String[] permissions, boolean preinstalled) throws Exception {
|
private void expectPermission(String[] permissions, String partition,
|
||||||
final PackageInfo packageInfo = packageInfoWithPermissions(permissions, preinstalled);
|
int targetSdkVersion) throws Exception {
|
||||||
|
final PackageInfo packageInfo = packageInfoWithPermissions(permissions, partition);
|
||||||
|
packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
|
||||||
when(mPackageManager.getPackageInfoAsUser(
|
when(mPackageManager.getPackageInfoAsUser(
|
||||||
eq(MOCK_PACKAGE_NAMES[0]), eq(GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
|
eq(MOCK_PACKAGE_NAMES[0]), eq(GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PackageInfo packageInfoWithPermissions(String[] permissions, boolean preinstalled) {
|
private PackageInfo packageInfoWithPermissions(String[] permissions, String partition) {
|
||||||
final PackageInfo packageInfo = new PackageInfo();
|
final PackageInfo packageInfo = new PackageInfo();
|
||||||
packageInfo.requestedPermissions = permissions;
|
packageInfo.requestedPermissions = permissions;
|
||||||
packageInfo.applicationInfo = new ApplicationInfo();
|
packageInfo.applicationInfo = new ApplicationInfo();
|
||||||
packageInfo.applicationInfo.flags = preinstalled ? FLAG_SYSTEM : 0;
|
int privateFlags = 0;
|
||||||
|
switch (partition) {
|
||||||
|
case PARTITION_OEM:
|
||||||
|
privateFlags = PRIVATE_FLAG_OEM;
|
||||||
|
break;
|
||||||
|
case PARTITION_PRODUCT:
|
||||||
|
privateFlags = PRIVATE_FLAG_PRODUCT;
|
||||||
|
break;
|
||||||
|
case PARTITION_VENDOR:
|
||||||
|
privateFlags = PRIVATE_FLAG_VENDOR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
packageInfo.applicationInfo.privateFlags = privateFlags;
|
||||||
return packageInfo;
|
return packageInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHasPermission() {
|
public void testHasPermission() {
|
||||||
PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
|
PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
|
||||||
assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
||||||
assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
||||||
assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
||||||
@@ -86,7 +107,7 @@ public class PermissionMonitorTest {
|
|||||||
|
|
||||||
app = packageInfoWithPermissions(new String[] {
|
app = packageInfoWithPermissions(new String[] {
|
||||||
CHANGE_NETWORK_STATE, NETWORK_STACK
|
CHANGE_NETWORK_STATE, NETWORK_STACK
|
||||||
}, false);
|
}, PARTITION_SYSTEM);
|
||||||
assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
||||||
assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
||||||
assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
||||||
@@ -94,7 +115,7 @@ public class PermissionMonitorTest {
|
|||||||
|
|
||||||
app = packageInfoWithPermissions(new String[] {
|
app = packageInfoWithPermissions(new String[] {
|
||||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
|
CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
|
||||||
}, false);
|
}, PARTITION_SYSTEM);
|
||||||
assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
||||||
assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
||||||
assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
||||||
@@ -102,35 +123,64 @@ public class PermissionMonitorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsPreinstalledSystemApp() {
|
public void testIsVendorApp() {
|
||||||
PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
|
PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
|
||||||
assertFalse(mPermissionMonitor.isPreinstalledSystemApp(app));
|
assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||||
|
app = packageInfoWithPermissions(new String[] {}, PARTITION_OEM);
|
||||||
app = packageInfoWithPermissions(new String[] {}, true);
|
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||||
assertTrue(mPermissionMonitor.isPreinstalledSystemApp(app));
|
app = packageInfoWithPermissions(new String[] {}, PARTITION_PRODUCT);
|
||||||
|
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||||
|
app = packageInfoWithPermissions(new String[] {}, PARTITION_VENDOR);
|
||||||
|
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHasUseBackgroundNetworksPermission() throws Exception {
|
public void testHasUseBackgroundNetworksPermission() throws Exception {
|
||||||
expectPermission(new String[] { CHANGE_NETWORK_STATE }, false);
|
expectPermission(new String[] { CHANGE_NETWORK_STATE },
|
||||||
|
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { NETWORK_STACK }, PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CONNECTIVITY_INTERNAL },
|
||||||
|
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
|
||||||
|
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
|
||||||
expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, false);
|
expectPermission(new String[] { CHANGE_NETWORK_STATE },
|
||||||
|
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { NETWORK_STACK },
|
||||||
|
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CONNECTIVITY_INTERNAL },
|
||||||
|
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
|
||||||
|
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
|
||||||
// TODO : make this false when b/31479477 is fixed
|
expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||||
expectPermission(new String[] {}, true);
|
|
||||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
|
||||||
expectPermission(new String[] { CHANGE_WIFI_STATE }, true);
|
|
||||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
|
||||||
|
|
||||||
expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, true);
|
|
||||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
|
||||||
|
|
||||||
expectPermission(new String[] {}, false);
|
|
||||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||||
|
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||||
|
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] {}, PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||||
|
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||||
|
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
|
||||||
expectPermission(new String[] { CHANGE_WIFI_STATE }, false);
|
expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.Q);
|
||||||
|
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||||
|
PARTITION_SYSTEM, Build.VERSION_CODES.Q);
|
||||||
|
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] {}, PARTITION_VENDOR, Build.VERSION_CODES.Q);
|
||||||
|
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
|
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||||
|
PARTITION_VENDOR, Build.VERSION_CODES.Q);
|
||||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user