OSDN Git Service

Boost android.anim and wm lock sections to -10 during transition
authorJorim Jaggi <jjaggi@google.com>
Wed, 7 Jun 2017 21:33:04 +0000 (14:33 -0700)
committerandroid-build-team Robot <android-build-team-robot@google.com>
Fri, 9 Jun 2017 04:25:03 +0000 (04:25 +0000)
-4 is not enough if we have to compete against RT and main thread
from top app that have -10. Boost it more during app transitions

Test: Inspect systrace, make sure priorities are right, including
getting reset after the transition.
Test: Open Chrome 100x
Test: go/wm-smoke

Change-Id: Id6b060b8aafded67b4bae61b6e8960e37976b096
Fixes: 36631902
(cherry picked from commit 245281c056a5b880486671157b48d6c4e5815ce1)

services/core/java/com/android/server/ThreadPriorityBooster.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/wm/AppTransition.java
services/core/java/com/android/server/wm/WindowManagerService.java
services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java [new file with mode: 0644]

index 31726ad..0dfecc0 100644 (file)
 
 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 class ThreadPriorityBooster {
     }
 
     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 class ThreadPriorityBooster {
     }
 
     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);
         }
     }
 
index c958313..a2a0634 100644 (file)
@@ -453,6 +453,11 @@ import libcore.util.EmptyArray;
 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 @@ public class ActivityManagerService extends IActivityManager.Stub
                             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 @@ public class ActivityManagerService extends IActivityManager.Stub
                                 }
                             } 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
                                     }
index 9d8f124..c1c72ca 100644 (file)
@@ -313,6 +313,7 @@ public class AppTransition implements Dump {
         mNextAppTransition = transit;
         mNextAppTransitionFlags |= flags;
         setLastAppTransition(TRANSIT_UNSET, null, null);
+        updateBooster();
     }
 
     void setLastAppTransition(int transit, AppWindowToken openingApp, AppWindowToken closingApp) {
@@ -327,7 +328,7 @@ public class AppTransition implements Dump {
     }
 
     void setReady() {
-        mAppTransitionState = APP_STATE_READY;
+        setAppTransitionState(APP_STATE_READY);
         fetchAppTransitionSpecsFromFuture();
     }
 
@@ -336,7 +337,7 @@ public class AppTransition implements Dump {
     }
 
     void setIdle() {
-        mAppTransitionState = APP_STATE_IDLE;
+        setAppTransitionState(APP_STATE_IDLE);
     }
 
     boolean isTimeout() {
@@ -344,7 +345,7 @@ public class AppTransition implements Dump {
     }
 
     void setTimeout() {
-        mAppTransitionState = APP_STATE_TIMEOUT;
+        setAppTransitionState(APP_STATE_TIMEOUT);
     }
 
     GraphicBuffer getAppTransitionThumbnailHeader(int taskId) {
@@ -386,7 +387,7 @@ public class AppTransition implements Dump {
 
     private boolean prepare() {
         if (!isRunning()) {
-            mAppTransitionState = APP_STATE_IDLE;
+            setAppTransitionState(APP_STATE_IDLE);
             notifyAppTransitionPendingLocked();
             mLastHadClipReveal = false;
             mLastClipRevealMaxTranslation = 0;
@@ -405,7 +406,7 @@ public class AppTransition implements Dump {
             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 @@ public class AppTransition implements Dump {
         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);
     }
index e5af9d2..128109b 100644 (file)
@@ -870,8 +870,8 @@ public class WindowManagerService extends IWindowManager.Stub
     // 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 (file)
index 0000000..6a244a2
--- /dev/null
@@ -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;
+    }
+}