summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sudheer Shanka <sudheersai@google.com> 2024-10-27 01:17:45 +0000
committer Sudheer Shanka <sudheersai@google.com> 2024-10-27 18:44:29 +0000
commit62513b64e8b9e9c9c71b43aa9af7ec2cd0b18f88 (patch)
treed9e38f0752db6ab0c5a0c63f89118322af1c13af
parentf8ea5bcc0546b65f0e3a4d4436db2f84c772fcbe (diff)
Limit priority values used with receiver registrations.
The priority values are limited to within the range (SYSTEM_HIGH_PRIORITY, SYSTEM_LOW_PRIORITY). Bug: 371309185 Test: atest services/tests/mockingservicestests/src/com/android/server/am/BroadcastFilterTest.java Flag: com.android.server.am.restrict_priority_values Change-Id: I5e98d3f5e592be08ac2076d7860e2d171cf04a92
-rw-r--r--services/core/java/com/android/server/am/BroadcastController.java2
-rw-r--r--services/core/java/com/android/server/am/BroadcastFilter.java45
-rw-r--r--services/core/java/com/android/server/am/flags.aconfig8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastFilterTest.java220
5 files changed, 278 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java
index a00cac6aba4f..71ddf05eb692 100644
--- a/services/core/java/com/android/server/am/BroadcastController.java
+++ b/services/core/java/com/android/server/am/BroadcastController.java
@@ -554,7 +554,7 @@ class BroadcastController {
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
receiverId, permission, callingUid, userId, instantApp, visibleToInstantApps,
- exported);
+ exported, mService.mPlatformCompat);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
diff --git a/services/core/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java
index adb2392a8484..f016590b6539 100644
--- a/services/core/java/com/android/server/am/BroadcastFilter.java
+++ b/services/core/java/com/android/server/am/BroadcastFilter.java
@@ -17,16 +17,33 @@
package com.android.server.am;
import android.annotation.Nullable;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Overridable;
import android.content.IntentFilter;
+import android.os.UserHandle;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.compat.PlatformCompat;
+
import dalvik.annotation.optimization.NeverCompile;
import java.io.PrintWriter;
public final class BroadcastFilter extends IntentFilter {
+ /**
+ * Limit priority values defined by non-system apps to
+ * ({@link IntentFilter#SYSTEM_LOW_PRIORITY}, {@link IntentFilter#SYSTEM_HIGH_PRIORITY}).
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.BASE)
+ @Overridable
+ @VisibleForTesting
+ static final long CHANGE_RESTRICT_PRIORITY_VALUES = 371309185L;
+
// Back-pointer to the list this filter is in.
final ReceiverList receiverList;
final String packageName;
@@ -38,11 +55,12 @@ public final class BroadcastFilter extends IntentFilter {
final boolean instantApp;
final boolean visibleToInstantApp;
public final boolean exported;
+ final int initialPriority;
BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
String _packageName, String _featureId, String _receiverId, String _requiredPermission,
int _owningUid, int _userId, boolean _instantApp, boolean _visibleToInstantApp,
- boolean _exported) {
+ boolean _exported, PlatformCompat platformCompat) {
super(_filter);
receiverList = _receiverList;
packageName = _packageName;
@@ -54,6 +72,8 @@ public final class BroadcastFilter extends IntentFilter {
instantApp = _instantApp;
visibleToInstantApp = _visibleToInstantApp;
exported = _exported;
+ initialPriority = getPriority();
+ setPriority(calculateAdjustedPriority(owningUid, initialPriority, platformCompat));
}
public @Nullable String getReceiverClassName() {
@@ -100,6 +120,29 @@ public final class BroadcastFilter extends IntentFilter {
if (requiredPermission != null) {
pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
}
+ if (initialPriority != getPriority()) {
+ pw.print(prefix); pw.print("initialPriority="); pw.println(initialPriority);
+ }
+ }
+
+ @VisibleForTesting
+ static int calculateAdjustedPriority(int owningUid, int priority,
+ PlatformCompat platformCompat) {
+ if (!Flags.restrictPriorityValues()) {
+ return priority;
+ }
+ if (!platformCompat.isChangeEnabledByUidInternalNoLogging(
+ CHANGE_RESTRICT_PRIORITY_VALUES, owningUid)) {
+ return priority;
+ }
+ if (!UserHandle.isCore(owningUid)) {
+ if (priority >= SYSTEM_HIGH_PRIORITY) {
+ return SYSTEM_HIGH_PRIORITY - 1;
+ } else if (priority <= SYSTEM_LOW_PRIORITY) {
+ return SYSTEM_LOW_PRIORITY + 1;
+ }
+ }
+ return priority;
}
public String toString() {
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index d67fea09f945..d680712676cd 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -233,3 +233,11 @@ flag {
description: "Assign cached oom_score_adj in tiers."
bug: "369893532"
}
+
+flag {
+ name: "restrict_priority_values"
+ namespace: "backstage_power"
+ description: "Restrict priority values defined by non-system apps"
+ is_fixed_read_only: true
+ bug: "369487976"
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
index 586191702578..d602660597ff 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BaseBroadcastQueueTest.java
@@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.annotation.NonNull;
@@ -52,11 +53,11 @@ import com.android.server.AlarmManagerInternal;
import com.android.server.DropBoxManagerInternal;
import com.android.server.LocalServices;
import com.android.server.appop.AppOpsService;
+import com.android.server.compat.PlatformCompat;
import com.android.server.wm.ActivityTaskManagerService;
import org.junit.Rule;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.File;
@@ -164,7 +165,7 @@ public abstract class BaseBroadcastQueueTest {
realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal());
- realAms.mOomAdjuster.mCachedAppOptimizer = Mockito.mock(CachedAppOptimizer.class);
+ realAms.mOomAdjuster.mCachedAppOptimizer = mock(CachedAppOptimizer.class);
realAms.mOomAdjuster = spy(realAms.mOomAdjuster);
ExtendedMockito.doNothing().when(() -> ProcessList.setOomAdj(anyInt(), anyInt(), anyInt()));
realAms.mPackageManagerInt = mPackageManagerInt;
@@ -286,7 +287,8 @@ public abstract class BaseBroadcastQueueTest {
filter.setPriority(priority);
final BroadcastFilter res = new BroadcastFilter(filter, receiverList,
receiverList.app.info.packageName, null, null, null, receiverList.uid,
- receiverList.userId, false, false, true);
+ receiverList.userId, false, false, true,
+ mock(PlatformCompat.class));
receiverList.add(res);
return res;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastFilterTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastFilterTest.java
new file mode 100644
index 000000000000..e977a7d46f30
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastFilterTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2024 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 android.content.IntentFilter.SYSTEM_HIGH_PRIORITY;
+import static android.content.IntentFilter.SYSTEM_LOW_PRIORITY;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+
+import android.os.Process;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.compat.PlatformCompat;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+public class BroadcastFilterTest {
+ private static final int TEST_APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Mock
+ PlatformCompat mPlatformCompat;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RESTRICT_PRIORITY_VALUES)
+ public void testCalculateAdjustedPriority() {
+ doReturn(true).when(mPlatformCompat).isChangeEnabledByUidInternalNoLogging(
+ eq(BroadcastFilter.CHANGE_RESTRICT_PRIORITY_VALUES), anyInt());
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForSystemUid(priorityPair.first, priorityPair.second);
+ }
+ }
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY - 1),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY + 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY + 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForAppUid(priorityPair.first, priorityPair.second);
+ }
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RESTRICT_PRIORITY_VALUES)
+ public void testCalculateAdjustedPriority_withChangeIdDisabled() {
+ doReturn(false).when(mPlatformCompat).isChangeEnabledByUidInternalNoLogging(
+ eq(BroadcastFilter.CHANGE_RESTRICT_PRIORITY_VALUES), anyInt());
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForSystemUid(priorityPair.first, priorityPair.second);
+ }
+ }
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForAppUid(priorityPair.first, priorityPair.second);
+ }
+ }
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_RESTRICT_PRIORITY_VALUES)
+ public void testCalculateAdjustedPriority_withFlagDisabled() {
+ doReturn(true).when(mPlatformCompat).isChangeEnabledByUidInternalNoLogging(
+ eq(BroadcastFilter.CHANGE_RESTRICT_PRIORITY_VALUES), anyInt());
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForSystemUid(priorityPair.first, priorityPair.second);
+ }
+ }
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForAppUid(priorityPair.first, priorityPair.second);
+ }
+ }
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_RESTRICT_PRIORITY_VALUES)
+ public void testCalculateAdjustedPriority_withFlagDisabled_withChangeIdDisabled() {
+ doReturn(false).when(mPlatformCompat).isChangeEnabledByUidInternalNoLogging(
+ eq(BroadcastFilter.CHANGE_RESTRICT_PRIORITY_VALUES), anyInt());
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForSystemUid(priorityPair.first, priorityPair.second);
+ }
+ }
+
+ {
+ // Pairs of {initial-priority, expected-adjusted-priority}
+ final Pair<Integer, Integer>[] priorities = new Pair[] {
+ Pair.create(SYSTEM_HIGH_PRIORITY, SYSTEM_HIGH_PRIORITY),
+ Pair.create(SYSTEM_LOW_PRIORITY, SYSTEM_LOW_PRIORITY),
+ Pair.create(SYSTEM_HIGH_PRIORITY + 1, SYSTEM_HIGH_PRIORITY + 1),
+ Pair.create(SYSTEM_LOW_PRIORITY - 1, SYSTEM_LOW_PRIORITY - 1),
+ Pair.create(SYSTEM_HIGH_PRIORITY - 2, SYSTEM_HIGH_PRIORITY - 2),
+ Pair.create(SYSTEM_LOW_PRIORITY + 2, SYSTEM_LOW_PRIORITY + 2)
+ };
+ for (Pair<Integer, Integer> priorityPair : priorities) {
+ assertAdjustedPriorityForAppUid(priorityPair.first, priorityPair.second);
+ }
+ }
+ }
+
+ private void assertAdjustedPriorityForSystemUid(int priority, int expectedAdjustedPriority) {
+ assertAdjustedPriority(Process.SYSTEM_UID, priority, expectedAdjustedPriority);
+ }
+
+ private void assertAdjustedPriorityForAppUid(int priority, int expectedAdjustedPriority) {
+ assertAdjustedPriority(TEST_APP_UID, priority, expectedAdjustedPriority);
+ }
+
+ private void assertAdjustedPriority(int owningUid, int priority, int expectedAdjustedPriority) {
+ final String errorMsg = String.format("owner=%d; actualPriority=%d; expectedPriority=%d",
+ owningUid, priority, expectedAdjustedPriority);
+ assertWithMessage(errorMsg).that(BroadcastFilter.calculateAdjustedPriority(
+ owningUid, priority, mPlatformCompat)).isEqualTo(expectedAdjustedPriority);
+ }
+}