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

Commit 4f26be3a authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Demote top-app when notification shade is expanded

If the top app is busy, it may cause potential jank when expanding
notification shade because CPU contention.

If there is top app switch, the demote will be canceled. Because it
is usually an app launch which needs top priority for startup latency.

Bug: 362467878
Flag: com.android.window.flags.scheduling_for_notification_shade
Test: Expand/collapse notification shade and check
      adb shell dumpsys activity o | grep -e "A.*top-activity"
      Expanded: intermediate-top-activity
      Collapsed: top-activity

Change-Id: Ic82cb3235f93f01db382d355c98f7aef2f1ef783
parent 7ad12f9f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -722,6 +722,9 @@ interface IWindowManager
     */
    void setDisplayImePolicy(int displayId, int imePolicy);

    /** Called when the expanded state of notification shade is changed. */
    void onNotificationShadeExpanded(IBinder token, boolean expanded);

    /**
     * Waits until input information has been sent from WindowManager to native InputManager,
     * optionally waiting for animations to complete.
+11 −0
Original line number Diff line number Diff line
@@ -264,6 +264,17 @@ flag {
  }
}

flag {
  name: "scheduling_for_notification_shade"
  namespace: "windowing_frontend"
  description: "Demote top-app when notification shade is expanded"
  bug: "362467878"
  is_fixed_read_only: true
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
    name: "release_snapshot_aggressively"
    namespace: "windowing_frontend"
+14 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
@@ -252,6 +253,19 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
        if (mCurrentState.shadeOrQsExpanded != isExpanded) {
            mCurrentState.shadeOrQsExpanded = isExpanded;
            apply(mCurrentState);

            final IBinder token;
            if (com.android.window.flags.Flags.schedulingForNotificationShade()
                    && (token = mWindowRootView.getWindowToken()) != null) {
                mBackgroundExecutor.execute(() -> {
                    try {
                        WindowManagerGlobal.getWindowManagerService()
                                .onNotificationShadeExpanded(token, isExpanded);
                    } catch (RemoteException e) {
                        Log.e(TAG, "Failed to call onNotificationShadeExpanded", e);
                    }
                });
            }
        }
    }

+9 −0
Original line number Diff line number Diff line
@@ -437,10 +437,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {

    /** It is set from keyguard-going-away to set-keyguard-shown. */
    static final int DEMOTE_TOP_REASON_DURING_UNLOCKING = 1;
    /** It is set when notification shade occludes the foreground app. */
    static final int DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE = 1 << 1;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            DEMOTE_TOP_REASON_DURING_UNLOCKING,
            DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE,
    })
    @interface DemoteTopReason {}

@@ -5239,6 +5242,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                : mRootWindowContainer.getTopResumedActivity();
        mTopApp = top != null ? top.app : null;
        if (mTopApp == mPreviousProcess) mPreviousProcess = null;

        final int demoteReasons = mDemoteTopAppReasons;
        if ((demoteReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) != 0) {
            Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancel-demote-top-for-ns-switch");
            mDemoteTopAppReasons = demoteReasons & ~DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
        }
    }

    /**
+32 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
import static com.android.server.policy.PhoneWindowManager.TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerService.DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
@@ -7778,6 +7779,37 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    @Override
    public void onNotificationShadeExpanded(IBinder token, boolean expanded) {
        synchronized (mGlobalLock) {
            final WindowState w = mWindowMap.get(token);
            if (w == null || w != w.mDisplayContent.getDisplayPolicy().getNotificationShade()) {
                return;
            }
            final WindowProcessController topApp = mAtmService.mTopApp;
            // Demotes the priority of top app if notification shade is expanded to occlude the app.
            // So the notification shade may have more capacity to draw and animate.
            final int demoteTopAppReasons = mAtmService.mDemoteTopAppReasons;
            if (expanded && mAtmService.mTopProcessState == ActivityManager.PROCESS_STATE_TOP
                    && (demoteTopAppReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) == 0) {
                mAtmService.mDemoteTopAppReasons =
                        demoteTopAppReasons | DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
                Trace.instant(TRACE_TAG_WINDOW_MANAGER, "demote-top-for-ns");
                if (topApp != null) {
                    topApp.scheduleUpdateOomAdj();
                }
            } else if (!expanded
                    && (demoteTopAppReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) != 0) {
                mAtmService.mDemoteTopAppReasons =
                        demoteTopAppReasons & ~DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
                Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancel-demote-top-for-ns");
                if (topApp != null) {
                    topApp.scheduleUpdateOomAdj();
                }
            }
        }
    }

    @Override
    public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
            throws RemoteException {