Merge "Boost android.anim and wm lock sections to -10 during transition" into oc-dev
diff --git a/services/core/java/com/android/server/ThreadPriorityBooster.java b/services/core/java/com/android/server/ThreadPriorityBooster.java
index 31726ad..0dfecc0 100644
--- a/services/core/java/com/android/server/ThreadPriorityBooster.java
+++ b/services/core/java/com/android/server/ThreadPriorityBooster.java
@@ -16,14 +16,16 @@
package com.android.server;
-import android.os.Process;
+import static android.os.Process.getThreadPriority;
+import static android.os.Process.myTid;
+import static android.os.Process.setThreadPriority;
/**
* Utility class to boost threads in sections where important locks are held.
*/
public class ThreadPriorityBooster {
- private final int mBoostToPriority;
+ private volatile int mBoostToPriority;
private final int mLockGuardIndex;
private final ThreadLocal<PriorityState> mThreadState = new ThreadLocal<PriorityState>() {
@@ -38,12 +40,12 @@
}
public void boost() {
- final int tid = Process.myTid();
- final int prevPriority = Process.getThreadPriority(tid);
- PriorityState state = mThreadState.get();
+ final int tid = myTid();
+ final int prevPriority = getThreadPriority(tid);
+ final PriorityState state = mThreadState.get();
state.prevPriority = prevPriority;
if (state.regionCounter == 0 && prevPriority > mBoostToPriority) {
- Process.setThreadPriority(tid, mBoostToPriority);
+ setThreadPriority(tid, mBoostToPriority);
}
state.regionCounter++;
if (LockGuard.ENABLED) {
@@ -52,10 +54,28 @@
}
public void reset() {
- PriorityState state = mThreadState.get();
+ final PriorityState state = mThreadState.get();
state.regionCounter--;
- if (state.regionCounter == 0 && state.prevPriority > mBoostToPriority) {
- Process.setThreadPriority(Process.myTid(), state.prevPriority);
+ final int currentPriority = getThreadPriority(myTid());
+ if (state.regionCounter == 0 && state.prevPriority != currentPriority) {
+ setThreadPriority(myTid(), state.prevPriority);
+ }
+ }
+
+ /**
+ * Updates the priority we boost the threads to, and updates the current thread's priority if
+ * necessary.
+ */
+ protected void setBoostToPriority(int priority) {
+
+ // We don't care about the other threads here, as long as they see the update of this
+ // variable immediately.
+ mBoostToPriority = priority;
+ final PriorityState state = mThreadState.get();
+ final int tid = myTid();
+ final int prevPriority = getThreadPriority(tid);
+ if (state.regionCounter != 0 && prevPriority != priority) {
+ setThreadPriority(tid, priority);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c958313..a2a0634 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -453,6 +453,11 @@
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
+ /**
+ * Priority we boost main thread and RT of top app to.
+ */
+ public static final int TOP_APP_PRIORITY_BOOST = -10;
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
private static final String TAG_BACKUP = TAG + POSTFIX_BACKUP;
private static final String TAG_BROADCAST = TAG + POSTFIX_BROADCAST;
@@ -13426,7 +13431,7 @@
setThreadScheduler(proc.renderThreadTid,
SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
} else {
- setThreadPriority(proc.renderThreadTid, -10);
+ setThreadPriority(proc.renderThreadTid, TOP_APP_PRIORITY_BOOST);
}
}
} else {
@@ -21886,10 +21891,11 @@
}
} else {
// Boost priority for top app UI and render threads
- setThreadPriority(app.pid, -10);
+ setThreadPriority(app.pid, TOP_APP_PRIORITY_BOOST);
if (app.renderThreadTid != 0) {
try {
- setThreadPriority(app.renderThreadTid, -10);
+ setThreadPriority(app.renderThreadTid,
+ TOP_APP_PRIORITY_BOOST);
} catch (IllegalArgumentException e) {
// thread died, ignore
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9d8f124..c1c72ca 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -313,6 +313,7 @@
mNextAppTransition = transit;
mNextAppTransitionFlags |= flags;
setLastAppTransition(TRANSIT_UNSET, null, null);
+ updateBooster();
}
void setLastAppTransition(int transit, AppWindowToken openingApp, AppWindowToken closingApp) {
@@ -327,7 +328,7 @@
}
void setReady() {
- mAppTransitionState = APP_STATE_READY;
+ setAppTransitionState(APP_STATE_READY);
fetchAppTransitionSpecsFromFuture();
}
@@ -336,7 +337,7 @@
}
void setIdle() {
- mAppTransitionState = APP_STATE_IDLE;
+ setAppTransitionState(APP_STATE_IDLE);
}
boolean isTimeout() {
@@ -344,7 +345,7 @@
}
void setTimeout() {
- mAppTransitionState = APP_STATE_TIMEOUT;
+ setAppTransitionState(APP_STATE_TIMEOUT);
}
GraphicBuffer getAppTransitionThumbnailHeader(int taskId) {
@@ -386,7 +387,7 @@
private boolean prepare() {
if (!isRunning()) {
- mAppTransitionState = APP_STATE_IDLE;
+ setAppTransitionState(APP_STATE_IDLE);
notifyAppTransitionPendingLocked();
mLastHadClipReveal = false;
mLastClipRevealMaxTranslation = 0;
@@ -405,7 +406,7 @@
ArraySet<AppWindowToken> closingApps) {
mNextAppTransition = TRANSIT_UNSET;
mNextAppTransitionFlags = 0;
- mAppTransitionState = APP_STATE_RUNNING;
+ setAppTransitionState(APP_STATE_RUNNING);
int redoLayout = notifyAppTransitionStartingLocked(transit,
topOpeningAppAnimator != null ? topOpeningAppAnimator.mAppToken.token : null,
topClosingAppAnimator != null ? topClosingAppAnimator.mAppToken.token : null,
@@ -450,6 +451,22 @@
notifyAppTransitionCancelledLocked(transit);
}
+ private void setAppTransitionState(int state) {
+ mAppTransitionState = state;
+ updateBooster();
+ }
+
+ /**
+ * Updates whether we currently boost wm locked sections and the animation thread. We want to
+ * boost the priorities to a more important value whenever an app transition is going to happen
+ * soon or an app transition is running.
+ */
+ private void updateBooster() {
+ WindowManagerService.sThreadPriorityBooster.setAppTransitionRunning(
+ mNextAppTransition != TRANSIT_UNSET || mAppTransitionState == APP_STATE_READY
+ || mAppTransitionState == APP_STATE_RUNNING);
+ }
+
void registerListenerLocked(AppTransitionListener listener) {
mListeners.add(listener);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e5af9d2..128109b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -870,8 +870,8 @@
// since they won't be notified through the app window animator.
final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
- private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
- THREAD_PRIORITY_DISPLAY, INDEX_WINDOW);
+ static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
+ new WindowManagerThreadPriorityBooster();
static void boostPriorityForLockedSection() {
sThreadPriorityBooster.boost();
diff --git a/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java b/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java
new file mode 100644
index 0000000..6a244a2
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 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.wm;
+
+import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+import static android.os.Process.myTid;
+import static android.os.Process.setThreadPriority;
+
+import static com.android.server.LockGuard.INDEX_WINDOW;
+import static com.android.server.am.ActivityManagerService.TOP_APP_PRIORITY_BOOST;
+
+import com.android.server.AnimationThread;
+import com.android.server.ThreadPriorityBooster;
+
+/**
+ * Window manager version of {@link ThreadPriorityBooster} that boosts even more during app
+ * transitions.
+ */
+class WindowManagerThreadPriorityBooster extends ThreadPriorityBooster {
+
+ private final AnimationThread mAnimationThread;
+ private boolean mAppTransitionRunning;
+
+ WindowManagerThreadPriorityBooster() {
+ super(THREAD_PRIORITY_DISPLAY, INDEX_WINDOW);
+ mAnimationThread = AnimationThread.get();
+ }
+
+ @Override
+ public void boost() {
+
+ // Do not boost the animation thread. As the animation thread is changing priorities,
+ // boosting it might mess up the priority because we reset it the the previous priority.
+ if (myTid() == mAnimationThread.getThreadId()) {
+ return;
+ }
+ super.boost();
+ }
+
+ @Override
+ public void reset() {
+
+ // See comment in boost().
+ if (myTid() == mAnimationThread.getThreadId()) {
+ return;
+ }
+ super.reset();
+ }
+
+ void setAppTransitionRunning(boolean running) {
+ if (mAppTransitionRunning == running) {
+ return;
+ }
+
+ final int priority = calculatePriority(running);
+ setBoostToPriority(priority);
+ setThreadPriority(mAnimationThread.getThreadId(), priority);
+ mAppTransitionRunning = running;
+ }
+
+ private int calculatePriority(boolean appTransitionRunning) {
+ return appTransitionRunning ? TOP_APP_PRIORITY_BOOST : THREAD_PRIORITY_DISPLAY;
+ }
+}