Loading services/core/java/com/android/server/am/ActiveServices.java +55 −11 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import android.app.admin.DevicePolicyEventLogger; import android.app.compat.CompatChanges; import android.appwidget.AppWidgetManagerInternal; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.ComponentName.WithComponentName; Loading Loading @@ -108,6 +107,7 @@ import android.webkit.WebViewZygote; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.procstats.ServiceState; import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.notification.SystemNotificationChannels; Loading Loading @@ -275,7 +275,7 @@ public final class ActiveServices { * is higher than R. */ @ChangeId @Disabled @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L; /** Loading Loading @@ -307,9 +307,40 @@ public final class ActiveServices { */ 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 { sFgsBgStartExemptedPackages.add("com.google.pixel.exo.bootstrapping"); //STOPSHIP Remove it. sFgsBgStartExemptedPackages.add("com.android.chrome"); // STOPSHIP Remove it. 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() { Loading Loading @@ -5365,10 +5396,25 @@ public final class ActiveServices { return ret; } private boolean isPackageExemptedFromFgsRestriction(String packageName, int uid) { if (!sFgsBgStartExemptedPackages.contains(packageName)) { return false; @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); } Loading Loading @@ -5451,9 +5497,7 @@ public final class ActiveServices { } private boolean isBgFgsRestrictionEnabled(ServiceRecord r) { if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) { return true; } return CompatChanges.isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r.appInfo.uid); return mAm.mConstants.mFlagFgsStartRestrictionEnabled && CompatChanges.isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r.appInfo.uid); } } services/core/java/com/android/server/am/ActivityManagerConstants.java +4 −3 Original line number Diff line number Diff line Loading @@ -360,10 +360,11 @@ final class ActivityManagerConstants extends ContentObserver { // started, the restriction is on while-in-use permissions.) volatile boolean mFlagBackgroundFgsStartRestrictionEnabled = true; // Indicates whether the foreground service background start restriction is enabled. // Indicates whether the foreground service background start restriction is enabled for // apps targeting S+. // When the restriction is enabled, service is not allowed to startForeground from background // at all. volatile boolean mFlagFgsStartRestrictionEnabled = false; volatile boolean mFlagFgsStartRestrictionEnabled = true; // Whether we defer FGS notifications a few seconds following their transition to // the foreground state. Applies only to S+ apps; enabled by default. Loading Loading @@ -792,7 +793,7 @@ final class ActivityManagerConstants extends ContentObserver { mFlagFgsStartRestrictionEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED, /*defaultValue*/ false); /*defaultValue*/ true); } private void updateFgsNotificationDeferralEnable() { Loading services/tests/mockingservicestests/src/com/android/server/am/ActiveServicesTest.java 0 → 100644 +95 −0 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); } } Loading
services/core/java/com/android/server/am/ActiveServices.java +55 −11 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import android.app.admin.DevicePolicyEventLogger; import android.app.compat.CompatChanges; import android.appwidget.AppWidgetManagerInternal; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.EnabledSince; import android.content.ComponentName; import android.content.ComponentName.WithComponentName; Loading Loading @@ -108,6 +107,7 @@ import android.webkit.WebViewZygote; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.procstats.ServiceState; import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.notification.SystemNotificationChannels; Loading Loading @@ -275,7 +275,7 @@ public final class ActiveServices { * is higher than R. */ @ChangeId @Disabled @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L; /** Loading Loading @@ -307,9 +307,40 @@ public final class ActiveServices { */ 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 { sFgsBgStartExemptedPackages.add("com.google.pixel.exo.bootstrapping"); //STOPSHIP Remove it. sFgsBgStartExemptedPackages.add("com.android.chrome"); // STOPSHIP Remove it. 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() { Loading Loading @@ -5365,10 +5396,25 @@ public final class ActiveServices { return ret; } private boolean isPackageExemptedFromFgsRestriction(String packageName, int uid) { if (!sFgsBgStartExemptedPackages.contains(packageName)) { return false; @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); } Loading Loading @@ -5451,9 +5497,7 @@ public final class ActiveServices { } private boolean isBgFgsRestrictionEnabled(ServiceRecord r) { if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) { return true; } return CompatChanges.isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r.appInfo.uid); return mAm.mConstants.mFlagFgsStartRestrictionEnabled && CompatChanges.isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r.appInfo.uid); } }
services/core/java/com/android/server/am/ActivityManagerConstants.java +4 −3 Original line number Diff line number Diff line Loading @@ -360,10 +360,11 @@ final class ActivityManagerConstants extends ContentObserver { // started, the restriction is on while-in-use permissions.) volatile boolean mFlagBackgroundFgsStartRestrictionEnabled = true; // Indicates whether the foreground service background start restriction is enabled. // Indicates whether the foreground service background start restriction is enabled for // apps targeting S+. // When the restriction is enabled, service is not allowed to startForeground from background // at all. volatile boolean mFlagFgsStartRestrictionEnabled = false; volatile boolean mFlagFgsStartRestrictionEnabled = true; // Whether we defer FGS notifications a few seconds following their transition to // the foreground state. Applies only to S+ apps; enabled by default. Loading Loading @@ -792,7 +793,7 @@ final class ActivityManagerConstants extends ContentObserver { mFlagFgsStartRestrictionEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED, /*defaultValue*/ false); /*defaultValue*/ true); } private void updateFgsNotificationDeferralEnable() { Loading
services/tests/mockingservicestests/src/com/android/server/am/ActiveServicesTest.java 0 → 100644 +95 −0 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); } }