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

Commit 22e2526b authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Improved timing of when system sends multi-window change event to app

We were previously sending multi-window/PiP mode changed events to
apps once the task config is changed in activity manager.
However, the actual changing of the multi-windowing or PiP mode
might not be fully complete when the app receives the event so they
might be wrong state information they query for like currnet config.
We now schedule the events to be send once the current transaction
cycle is done.

Bug: 26877409
Change-Id: I393b56035bb4197f99b3db3d27c0599835b5f86c
parent a0fddc1e
Loading
Loading
Loading
Loading
+35 −9
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.am;

import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
@@ -409,7 +410,9 @@ final class ActivityRecord {
    }

    void scheduleConfigurationChanged(Configuration config, boolean reportToActivity) {
        if (app != null && app.thread != null) {
        if (app == null || app.thread == null) {
            return;
        }
        try {
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
                    "reportToActivity=" + reportToActivity + " and config: " + config);
@@ -419,6 +422,29 @@ final class ActivityRecord {
            // If process died, whatever.
        }
    }

    void scheduleMultiWindowChanged() {
        if (task == null || task.stack == null || app == null || app.thread == null) {
            return;
        }
        try {
            // An activity is considered to be in multi-window mode if its task isn't fullscreen.
            app.thread.scheduleMultiWindowChanged(appToken, !task.mFullscreen);
        } catch (Exception e) {
            // If process died, I don't care.
        }
    }

    void schedulePictureInPictureChanged() {
        if (task == null || task.stack == null || app == null || app.thread == null) {
            return;
        }
        try {
            app.thread.schedulePictureInPictureChanged(
                    appToken, task.stack.mStackId == PINNED_STACK_ID);
        } catch (Exception e) {
            // If process died, no one cares.
        }
    }

    boolean isFreeform() {
+2 −2
Original line number Diff line number Diff line
@@ -4827,7 +4827,7 @@ final class ActivityStack {

    private void postAddTask(TaskRecord task, ActivityStack prevStack) {
        if (prevStack != null) {
            task.reportPictureInPictureChangeIfNeeded(prevStack);
            mStackSupervisor.scheduleReportPictureInPictureChangedIfNeeded(task, prevStack);
        } else if (task.voiceSession != null) {
            try {
                task.voiceSession.taskStarted(task.intent, task.taskId);
@@ -4886,7 +4886,7 @@ final class ActivityStack {
        r.setTask(task, null);
        task.addActivityToTop(r);
        setAppTask(r, task);
        task.reportPictureInPictureChangeIfNeeded(prevStack);
        mStackSupervisor.scheduleReportPictureInPictureChangedIfNeeded(task, prevStack);
        moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, "moveActivityToStack");
        if (wasResumed) {
            prevStack.mResumedActivity = null;
+58 −0
Original line number Diff line number Diff line
@@ -203,6 +203,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
    static final int CONTAINER_CALLBACK_TASK_LIST_EMPTY = FIRST_SUPERVISOR_STACK_MSG + 11;
    static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
    static final int SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG = FIRST_SUPERVISOR_STACK_MSG + 13;
    static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14;
    static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15;

    private static final String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";

@@ -322,6 +324,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
    /** List of activities that are in the process of going to sleep. */
    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>();

    /** List of activities whose multi-window mode changed that we need to report to the
     * application */
    final ArrayList<ActivityRecord> mMultiWindowModeChangedActivities = new ArrayList<>();

    /** List of activities whose picture-in-picture mode changed that we need to report to the
     * application */
    final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();

    /** Used on user changes */
    final ArrayList<UserState> mStartingUsers = new ArrayList<>();

@@ -3390,6 +3400,38 @@ public final class ActivityStackSupervisor implements DisplayListener {
        mActivityMetricsLogger.logWindowState();
    }

    void scheduleReportMultiWindowChanged(TaskRecord task) {
        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
            final ActivityRecord r = task.mActivities.get(i);
            if (r.app != null && r.app.thread != null) {
                mMultiWindowModeChangedActivities.add(r);
            }
        }

        if (!mHandler.hasMessages(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG)) {
            mHandler.sendEmptyMessage(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG);
        }
    }

    void scheduleReportPictureInPictureChangedIfNeeded(TaskRecord task, ActivityStack prevStack) {
        final ActivityStack stack = task.stack;
        if (prevStack == null || prevStack == stack
                || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
            return;
        }

        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
            final ActivityRecord r = task.mActivities.get(i);
            if (r.app != null && r.app.thread != null) {
                mPipModeChangedActivities.add(r);
            }
        }

        if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
            mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
        }
    }

    private final class ActivityStackSupervisorHandler extends Handler {

        public ActivityStackSupervisorHandler(Looper looper) {
@@ -3405,6 +3447,22 @@ public final class ActivityStackSupervisor implements DisplayListener {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case REPORT_MULTI_WINDOW_MODE_CHANGED_MSG: {
                    synchronized (mService) {
                        for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) {
                            final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i);
                            r.scheduleMultiWindowChanged();
                        }
                    }
                } break;
                case REPORT_PIP_MODE_CHANGED_MSG: {
                    synchronized (mService) {
                        for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) {
                            final ActivityRecord r = mPipModeChangedActivities.remove(i);
                            r.schedulePictureInPictureChanged();
                        }
                    }
                } break;
                case IDLE_TIMEOUT_MSG: {
                    if (DEBUG_IDLE) Slog.d(TAG_IDLE,
                            "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
+1 −35
Original line number Diff line number Diff line
@@ -1320,7 +1320,7 @@ final class TaskRecord {
        }

        if (mFullscreen != oldFullscreen) {
            reportMultiWindowChange();
            mService.mStackSupervisor.scheduleReportMultiWindowChanged(this);
        }

        return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
@@ -1375,40 +1375,6 @@ final class TaskRecord {
        return bounds;
    }

    private void reportMultiWindowChange() {
        for (int i = mActivities.size() - 1; i >= 0; i--) {
            final ActivityRecord r = mActivities.get(i);
            if (r.app != null && r.app.thread != null) {
                try {
                    // An activity is consider to be in multi-window mode if its task isn't
                    // fullscreen.
                    r.app.thread.scheduleMultiWindowChanged(r.appToken, !mFullscreen);
                } catch (Exception e) {
                    Slog.e(TAG, "TaskRecord.reportMultiWindowChange: ", e);
                }
            }
        }
    }

    void reportPictureInPictureChangeIfNeeded(ActivityStack prevStack) {
        if (prevStack == null || prevStack == stack
                || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
            return;
        }

        for (int i = mActivities.size() - 1; i >= 0; i--) {
            final ActivityRecord r = mActivities.get(i);
            if (r.app != null && r.app.thread != null) {
                try {
                    r.app.thread.schedulePictureInPictureChanged(
                            r.appToken, stack.mStackId == PINNED_STACK_ID);
                } catch (Exception e) {
                    Slog.e(TAG, "TaskRecord.reportPictureInPictureChangeIfNeeded: ", e);
                }
            }
        }
    }

    /** Updates the task's bounds and override configuration to match what is expected for the
     * input stack. */
    void updateOverrideConfigurationForStack(ActivityStack inStack) {