Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b93f9455 authored by Paul Hu's avatar Paul Hu Committed by android-build-merger
Browse files

Merge "PermissionMonitor: Limit preinstalled apps network permissions" am: e227eeef

am: 3e35cfe2

Change-Id: I1478c932bf612fd4546c4178fc8f4a0bededf127
parents e408299b 3e35cfe2
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -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.PackageManager.GET_PERMISSIONS;

import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +35,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Build;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -155,9 +157,8 @@ public class PermissionMonitor {
    }

    @VisibleForTesting
    boolean isPreinstalledSystemApp(PackageInfo app) {
        int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
        return (flags & (FLAG_SYSTEM | FLAG_UPDATED_SYSTEM_APP)) != 0;
    static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
        return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
    }

    @VisibleForTesting
@@ -177,7 +178,13 @@ public class PermissionMonitor {
    }

    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)
                || 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
        // background networks.
        return hasPermission(app, CHANGE_NETWORK_STATE)
                || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)
                || hasPermission(app, CONNECTIVITY_INTERNAL)
                || hasPermission(app, NETWORK_STACK)
                // TODO : remove this check (b/31479477). Not all preinstalled apps should
                // have access to background networks, they should just request the appropriate
                // permission for their use case from the list above.
                || isPreinstalledSystemApp(app);
                || hasRestrictedNetworkPermission(app);
    }

    public boolean hasUseBackgroundNetworksPermission(int uid) {
+76 −26
Original line number Diff line number Diff line
@@ -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_USE_RESTRICTED_NETWORKS;
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 org.junit.Assert.assertFalse;
@@ -34,6 +36,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

@@ -48,6 +51,10 @@ import org.mockito.MockitoAnnotations;
public class PermissionMonitorTest {
    private static final int MOCK_UID = 10001;
    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 PackageManager mPackageManager;
@@ -62,23 +69,37 @@ public class PermissionMonitorTest {
        mPermissionMonitor = new PermissionMonitor(mContext, null);
    }

    private void expectPermission(String[] permissions, boolean preinstalled) throws Exception {
        final PackageInfo packageInfo = packageInfoWithPermissions(permissions, preinstalled);
    private void expectPermission(String[] permissions, String partition,
            int targetSdkVersion) throws Exception {
        final PackageInfo packageInfo = packageInfoWithPermissions(permissions, partition);
        packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
        when(mPackageManager.getPackageInfoAsUser(
                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();
        packageInfo.requestedPermissions = permissions;
        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;
    }

    @Test
    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, NETWORK_STACK));
        assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
@@ -86,7 +107,7 @@ public class PermissionMonitorTest {

        app = packageInfoWithPermissions(new String[] {
            CHANGE_NETWORK_STATE, NETWORK_STACK
            }, false);
        }, PARTITION_SYSTEM);
        assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
        assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
        assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
@@ -94,7 +115,7 @@ public class PermissionMonitorTest {

        app = packageInfoWithPermissions(new String[] {
            CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
            }, false);
        }, PARTITION_SYSTEM);
        assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
        assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
        assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
@@ -102,35 +123,64 @@ public class PermissionMonitorTest {
    }

    @Test
    public void testIsPreinstalledSystemApp() {
        PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
        assertFalse(mPermissionMonitor.isPreinstalledSystemApp(app));

        app = packageInfoWithPermissions(new String[] {}, true);
        assertTrue(mPermissionMonitor.isPreinstalledSystemApp(app));
    public void testIsVendorApp() {
        PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
        assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo));
        app = packageInfoWithPermissions(new String[] {}, PARTITION_OEM);
        assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
        app = packageInfoWithPermissions(new String[] {}, PARTITION_PRODUCT);
        assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
        app = packageInfoWithPermissions(new String[] {}, PARTITION_VENDOR);
        assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
    }

    @Test
    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, CONNECTIVITY_INTERNAL }, false);
        expectPermission(new String[] { NETWORK_STACK }, PARTITION_SYSTEM, Build.VERSION_CODES.P);
        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));

        // TODO : make this false when b/31479477 is fixed
        expectPermission(new String[] {}, true);
        expectPermission(new String[] { CONNECTIVITY_INTERNAL },
            PARTITION_SYSTEM, Build.VERSION_CODES.P);
        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
        expectPermission(new String[] { CHANGE_WIFI_STATE }, true);
        expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
            PARTITION_SYSTEM, Build.VERSION_CODES.P);
        assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));

        expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, true);
        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));

        expectPermission(new String[] {}, false);
        expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.P);
        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));
    }
}