summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jorim Jaggi <jjaggi@google.com> 2020-05-27 14:05:07 +0200
committer Jorim Jaggi <jjaggi@google.com> 2020-06-11 16:06:23 +0200
commitf1347d33e141c5e8e90df2ec4b9322a4a5d9c6cc (patch)
treeea5a00f32f428d24dd1e580d615526c3b962d467
parent88e86e641afcd71c736172e90e260c91b2fac904 (diff)
Only promote remote animator to top sched group during animation
When running remote animation or SystemUI has requested top priority (for example. when notifacition shade is open on top of application), make sure to let it have exclusive top sched group access. This reduces contention between app and entity running remote animation as remote animator process gets exclusive access to certain CPUs. Test: Manual inspection of trace Test: asit/perf/appstartup_non_hermetic_cyclic_dropcache_test Bug: 157407136 Change-Id: I1bc495a1c536656f277a8e4aefc72f88d596c97a
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java23
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java29
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java10
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java17
4 files changed, 74 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index caaa8371af53..6ac34a688179 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1710,6 +1710,12 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
@Nullable ContentCaptureManagerInternal mContentCaptureService;
+ /**
+ * Set of {@link ProcessRecord} that have either {@link ProcessRecord#hasTopUi()} or
+ * {@link ProcessRecord#runningRemoteAnimation} set to {@code true}.
+ */
+ final ArraySet<ProcessRecord> mTopUiOrRunningRemoteAnimApps = new ArraySet<>();
+
final class UiHandler extends Handler {
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -14738,6 +14744,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mProcessesToGc.remove(app);
mPendingPssProcesses.remove(app);
+ mTopUiOrRunningRemoteAnimApps.remove(app);
ProcessList.abortNextPssTime(app.procStateMemTracker);
// Dismiss any open dialogs.
@@ -18526,6 +18533,22 @@ public class ActivityManagerService extends IActivityManager.Stub
return proc;
}
+ /**
+ * @return {@code true} if {@link #mTopUiOrRunningRemoteAnimApps} set contains {@code app} or when there are no apps
+ * in this list, an false otherwise.
+ */
+ boolean containsTopUiOrRunningRemoteAnimOrEmptyLocked(ProcessRecord app) {
+ return mTopUiOrRunningRemoteAnimApps.isEmpty() || mTopUiOrRunningRemoteAnimApps.contains(app);
+ }
+
+ void addTopUiOrRunningRemoteAnim(ProcessRecord app) {
+ mTopUiOrRunningRemoteAnimApps.add(app);
+ }
+
+ void removeTopUiOrRunningRemoteAnim(ProcessRecord app) {
+ mTopUiOrRunningRemoteAnimApps.remove(app);
+ }
+
@Override
public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
boolean runGc, String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 14c5b2cb12b2..d92144f3fd7f 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1151,8 +1151,17 @@ public final class OomAdjuster {
// is currently showing UI.
app.systemNoUi = true;
if (app == topApp) {
+ // If specific system app has set ProcessRecord.mHasTopUi or is running a remote
+ // animation (ProcessRecord.runningRemoteAnimation), this will prevent topApp
+ // to use SCHED_GROUP_TOP_APP to ensure process with mHasTopUi will have exclusive
+ // access to configured cores.
+ if (mService.containsTopUiOrRunningRemoteAnimOrEmptyLocked(app)) {
+ app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
+ } else {
+ app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
+ }
app.systemNoUi = false;
- app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
+
app.adjType = "pers-top-activity";
} else if (app.hasTopUi()) {
// sched group/proc state adjustment is below
@@ -1193,10 +1202,20 @@ public final class OomAdjuster {
boolean foregroundActivities = false;
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
- // The last app on the list is the foreground app.
- adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
- app.adjType = "top-activity";
+
+ // If specific system app has set ProcessRecord.mHasTopUi or is running a remote
+ // animation (ProcessRecord.runningRemoteAnimation), this will prevent topApp
+ // to use SCHED_GROUP_TOP_APP to ensure process with mHasTopUi will have exclusive
+ // access to configured cores.
+ if (mService.containsTopUiOrRunningRemoteAnimOrEmptyLocked(app)) {
+ adj = ProcessList.FOREGROUND_APP_ADJ;
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
+ app.adjType = "top-activity";
+ } else {
+ adj = ProcessList.FOREGROUND_APP_ADJ;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ app.adjType = "top-activity-behind-topui";
+ }
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index c5152c081e70..4c75ab21d6f2 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1268,6 +1268,7 @@ class ProcessRecord implements WindowProcessListener {
void setHasTopUi(boolean hasTopUi) {
mHasTopUi = hasTopUi;
mWindowProcessController.setHasTopUi(hasTopUi);
+ updateTopUiOrRunningRemoteAnim();
}
boolean hasTopUi() {
@@ -1518,10 +1519,19 @@ class ProcessRecord implements WindowProcessListener {
Slog.i(TAG, "Setting runningRemoteAnimation=" + runningRemoteAnimation
+ " for pid=" + pid);
}
+ updateTopUiOrRunningRemoteAnim();
mService.updateOomAdjLocked(this, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
}
}
+ void updateTopUiOrRunningRemoteAnim() {
+ if (runningRemoteAnimation || hasTopUi()) {
+ mService.addTopUiOrRunningRemoteAnim(this);
+ } else {
+ mService.removeTopUiOrRunningRemoteAnim(this);
+ }
+ }
+
public long getInputDispatchingTimeout() {
return mWindowProcessController.getInputDispatchingTimeout();
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index fde40aa77a0e..cdafd32cbbb5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -63,6 +63,7 @@ import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
@@ -170,6 +171,7 @@ public class MockingOomAdjusterTests {
mock(OomAdjProfiler.class));
doReturn(new ActivityManagerService.ProcessChangeItem()).when(sService)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
+ doReturn(true).when(sService).containsTopUiOrRunningRemoteAnimOrEmptyLocked(any());
sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
mock(ActiveUids.class));
sService.mOomAdjuster.mAdjSeq = 10000;
@@ -266,6 +268,21 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_TopApp_PreemptedByTopUi() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+ doReturn(PROCESS_STATE_TOP).when(sService.mAtmInternal).getTopProcessState();
+ doReturn(app).when(sService).getTopAppLocked();
+ doReturn(false).when(sService).containsTopUiOrRunningRemoteAnimOrEmptyLocked(eq(app));
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(null).when(sService).getTopAppLocked();
+
+ assertProcStates(app, PROCESS_STATE_TOP, FOREGROUND_APP_ADJ, SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_DoOne_RunningInstrumentation() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));