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

Commit 2ac94cb7 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Remove the FGS exemption list

Fix: 176844961
Test: Build / Boot
Change-Id: I546ceebb64e05739577ed288e9603f0636c6aaff
parent d7df1292
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -176,8 +176,6 @@ public class PowerExemptionManager {
    /** @hide */
    public static final int REASON_DEVICE_DEMO_MODE = 63;
    /** @hide */
    public static final int REASON_EXEMPTED_PACKAGE = 64;
    /** @hide */
    public static final int REASON_ALLOWLISTED_PACKAGE = 65;
    /** @hide */
    public static final int REASON_APPOP = 66;
@@ -344,7 +342,6 @@ public class PowerExemptionManager {
            REASON_INSTR_BACKGROUND_FGS_PERMISSION,
            REASON_SYSTEM_ALERT_WINDOW_PERMISSION,
            REASON_DEVICE_DEMO_MODE,
            REASON_EXEMPTED_PACKAGE,
            REASON_ALLOWLISTED_PACKAGE,
            REASON_APPOP,
            REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD,
@@ -601,8 +598,6 @@ public class PowerExemptionManager {
                return "SYSTEM_ALERT_WINDOW_PERMISSION";
            case REASON_DEVICE_DEMO_MODE:
                return "DEVICE_DEMO_MODE";
            case REASON_EXEMPTED_PACKAGE:
                return "EXEMPTED_PACKAGE";
            case REASON_ALLOWLISTED_PACKAGE:
                return "ALLOWLISTED_PACKAGE";
            case REASON_APPOP:
+0 −3
Original line number Diff line number Diff line
@@ -176,8 +176,6 @@ public class PowerWhitelistManager {
    /** @hide */
    public static final int REASON_DEVICE_DEMO_MODE = PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
    /** @hide */
    public static final int REASON_EXEMPTED_PACKAGE = PowerExemptionManager.REASON_EXEMPTED_PACKAGE;
    /** @hide */
    public static final int REASON_ALLOWLISTED_PACKAGE =
            PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
    /** @hide */
@@ -341,7 +339,6 @@ public class PowerWhitelistManager {
            REASON_INSTR_BACKGROUND_FGS_PERMISSION,
            REASON_SYSTEM_ALERT_WINDOW_PERMISSION,
            REASON_DEVICE_DEMO_MODE,
            REASON_EXEMPTED_PACKAGE,
            REASON_ALLOWLISTED_PACKAGE,
            REASON_APPOP,
            // temp and system allowlist reasons.
+0 −90
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER;
import static android.os.PowerWhitelistManager.REASON_DENIED;
import static android.os.PowerWhitelistManager.REASON_DEVICE_DEMO_MODE;
import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
import static android.os.PowerWhitelistManager.REASON_EXEMPTED_PACKAGE;
import static android.os.PowerWhitelistManager.REASON_FGS_BINDING;
import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
@@ -288,13 +287,6 @@ public final class ActiveServices {
    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
    static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L;

    /**
     * If set to false for a package, the system will *not* exempt it from FGS-BG-start,
     * even if it's in {#code ActiveServices.sFgsBgStartExemptedPackages}.
     */
    @ChangeId
    static final long FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID = 175801883;

    /**
     * If a service can not become foreground service due to BG-FGS-launch restriction or other
     * reasons, throws an IllegalStateException.
@@ -303,56 +295,6 @@ public final class ActiveServices {
    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
    static final long FGS_START_EXCEPTION_CHANGE_ID = 174041399L;

    /**
     * Special allowlist that contains packages that are allowed to start FGS even if they target S,
     * without using START_FOREGROUND_SERVICES_FROM_BACKGROUND.
     *
     * Note: we exempt FGS starts if either the "callee" or "caller" match any of the emempted
     * packages. This means:
     * - Exempted apps could call Context.startForegroundService() for services owned by any other
     *   apps.
     * - Any apps could call Context.startForegroundService() for services owned by any exempted
     *   apps.
     * And the call would succeed.
     */
    private static final ArraySet<String> sFgsBgStartExemptedPackages = new ArraySet<>();

    private static final ArrayList<String> sFgsBgStartExemptedPackagePrefixes = new ArrayList<>();

    /**
     * List of packages that are exempted from the FGS restriction *for now*.
     *
     * STOPSHIP(/b/176844961) Remove it. Also update ActiveServicesTest.java.
     */
    private static final String[] FGS_BG_START_EXEMPTED_PACKAGES = {
            "com.google.pixel.exo.bootstrapping",
    };

    /**
     * List of packages that are exempted from the FGS restriction *for now*. We also allow
     * any packages that
     *
     * STOPSHIP(/b/176844961) Remove it. Also update ActiveServicesTest.java.
     */
    private static final String[] FGS_BG_START_EXEMPTED_PACKAGES_PREFIXED_ALLOWED = {
            "com.android.webview",
            "com.google.android.webview",
            "com.android.chrome",
            "com.google.android.apps.chrome",
            "com.chrome",
    };

    static {
        for (String s : FGS_BG_START_EXEMPTED_PACKAGES) {
            sFgsBgStartExemptedPackages.add(s);
        }

        for (String s : FGS_BG_START_EXEMPTED_PACKAGES_PREFIXED_ALLOWED) {
            sFgsBgStartExemptedPackages.add(s); // Add it for an exact match.
            sFgsBgStartExemptedPackagePrefixes.add(s + "."); // Add it for an prefix match.
        }
    }

    final Runnable mLastAnrDumpClearer = new Runnable() {
        @Override public void run() {
            synchronized (mAm) {
@@ -5857,16 +5799,6 @@ public final class ActiveServices {
            }
        }

        // NOTE this should always be the last check.
        if (ret == REASON_DENIED) {
            if (isPackageExemptedFromFgsRestriction(callingPackage, callingUid)) {
                ret = REASON_EXEMPTED_PACKAGE;
            } else if (targetService != null && isPackageExemptedFromFgsRestriction(
                    targetService.appInfo.packageName, targetService.appInfo.uid)) {
                ret = REASON_EXEMPTED_PACKAGE;
            }
        }

        if (ret == REASON_DENIED) {
            final boolean isCompanionApp = mAm.mInternal.isAssociatedCompanionApp(
                    UserHandle.getUserId(callingUid), callingUid);
@@ -5889,28 +5821,6 @@ public final class ActiveServices {
        return ret;
    }

    @VisibleForTesting
    static boolean isPackageExemptedFromFgsRestriction(String packageName, int uid) {
        boolean exempted = false;
        if (sFgsBgStartExemptedPackages.contains(packageName)) {
            exempted = true;
        } else {
            for (String pkg : sFgsBgStartExemptedPackagePrefixes) {
                if (packageName.startsWith(pkg)) {
                    exempted = true;
                    break;
                }
            }
        }
        if (!exempted) {
            return false; // Package isn't exempted.
        }
        // Allow exempted packages to be subject to the restriction using this compat ID.
        // (so that, for example, the webview developer will be able to test the restriction
        // locally.)
        return CompatChanges.isChangeEnabled(FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID, uid);
    }

    private static boolean isFgsBgStart(@ReasonCode int code) {
        return code != REASON_PROC_STATE_PERSISTENT
                && code != REASON_PROC_STATE_PERSISTENT_UI
+0 −95
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 com.android.server.am;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.am.ActiveServices.FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;

import android.app.compat.CompatChanges;

import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;



@RunWith(AndroidJUnit4.class)
public class ActiveServicesTest {

    private MockitoSession mMockingSession;

    @Before
    public void setUp() {
        mMockingSession = mockitoSession()
                .initMocks(this)
                .strictness(Strictness.LENIENT)
                .mockStatic(CompatChanges.class)
                .startMocking();
    }

    @After
    public void tearDown() {
        if (mMockingSession != null) {
            mMockingSession.finishMocking();
        }
    }

    private void checkPackageExempted(String pkg, int uid, boolean expected) {
        assertEquals("Package=" + pkg + " uid=" + uid,
                expected, ActiveServices.isPackageExemptedFromFgsRestriction(pkg, uid));
    }

    @Test
    public void isPackageExemptedFromFgsRestriction() {
        // Compat changes are enabled by default.
        when(CompatChanges.isChangeEnabled(anyLong(), anyInt())).thenReturn(true);

        checkPackageExempted("", 1, false);
        checkPackageExempted("abc", 1, false);
        checkPackageExempted("com.random", 1, false);

        // This package is exempted but not its subpackages.
        checkPackageExempted("com.google.pixel.exo.bootstrapping", 1, true);
        checkPackageExempted("com.google.pixel.exo.bootstrapping.subpackage", 1, false);

        // Subpackages are also exempted.
        checkPackageExempted("com.android.webview", 1, true);
        checkPackageExempted("com.android.webview.beta", 1, true);
        checkPackageExempted("com.chrome", 1, true);
        checkPackageExempted("com.chrome.canary", 1, true);

        checkPackageExempted("com.android.webviewx", 1, false);

        // Now toggle the compat ID for a specific UID.
        when(CompatChanges.isChangeEnabled(FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID, 10))
                .thenReturn(false);
        // Exempted package, but compat id is disabled for the UID.
        checkPackageExempted("com.android.webview", 10, false);

        // Exempted package, but compat id is still enabled for the UID.
        checkPackageExempted("com.android.webview", 11, true);
    }
}