Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 245281c0 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Boost android.anim and wm lock sections to -10 during transition

-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
parent 75b5199e
Loading
Loading
Loading
Loading
+29 −9
Original line number Diff line number Diff line
@@ -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 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);
        }
    }

+9 −3
Original line number Diff line number Diff line
@@ -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
                                    }
+22 −5
Original line number Diff line number Diff line
@@ -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);
    }
+2 −2
Original line number Diff line number Diff line
@@ -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();
+78 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}