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

Commit ebcc875f authored by Filip Gruszczynski's avatar Filip Gruszczynski
Browse files

Move Configuration creation from Window Manager to Activity Manager.

Currently the construction of configuration is split between thease
two entities. This poses two problems: it's harder to follow the
construction logic and more importantly we can't determine if
configuration changes significantly before delegating work to the
Window Manager. This CL moves the configuration override logic to
the Activity Manager, since it both detects configuration changes and
informs clients about them. Window Manager becomes purely a recipient
of the information.

Change-Id: I075570ee055cce9c5665772fa8d4fe8ccb5c6313
parent e9acfd59
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -97,21 +97,21 @@ interface IWindowManager
     * @param launchTaskBehind True if the token is been launched from behind.
     * @param taskBounds Bounds to use when creating a new Task with the input task Id if
     *                   the task doesn't exist yet.
     * @return The configuration of the task if it was newly created. null otherwise.
     * @param configuration Configuration that is being used with this task.
     */
    Configuration addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
    void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
            int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
            int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
            in Rect taskBounds);
            in Rect taskBounds, in Configuration configuration);
    /**
     *
     * @param token The token we are adding to the input task Id.
     * @param taskId The Id of the task we are adding the token to.
     * @param taskBounds Bounds to use when creating a new Task with the input task Id if
     *                   the task doesn't exist yet.
     * @return The configuration of the task if it was newly created. null otherwise.
     * @param config Configuration that is being used with this task.
     */
    Configuration setAppTask(IBinder token, int taskId, in Rect taskBounds);
    void setAppTask(IBinder token, int taskId, in Rect taskBounds, in Configuration config);
    void setAppOrientation(IApplicationToken token, int requestedOrientation);
    int getAppOrientation(IApplicationToken token);
    void setFocusedApp(IBinder token, boolean moveFocusNow);
+9 −16
Original line number Diff line number Diff line
@@ -3975,8 +3975,7 @@ final class ActivityStack {
     * for whatever reason.  Ensures the HistoryRecord is updated with the
     * correct configuration and all other bookkeeping is handled.
     */
    final boolean ensureActivityConfigurationLocked(ActivityRecord r,
            int globalChanges) {
    final boolean ensureActivityConfigurationLocked(ActivityRecord r, int globalChanges) {
        if (mConfigWillChange) {
            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Skipping config check (will change): " + r);
@@ -4589,25 +4588,19 @@ final class ActivityStack {

    void addConfigOverride(ActivityRecord r, TaskRecord task) {
        final Rect bounds = task.getLaunchBounds();
        final Configuration config =
        final Configuration config = task.updateOverrideConfiguration(mStackId, bounds);
        mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
                r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind,
                        bounds);
        if (config != null) {
            task.updateOverrideConfiguration(config, bounds);
        }
                bounds, config);
        r.taskConfigOverride = task.mOverrideConfig;
    }

    private void setAppTask(ActivityRecord r, TaskRecord task) {
        final Rect bounds = task.getLaunchBounds();
        final Configuration config =
                mWindowManager.setAppTask(r.appToken, task.taskId, task.getLaunchBounds());
        if (config != null) {
            task.updateOverrideConfiguration(config, bounds);
        }
        final Configuration config = task.updateOverrideConfiguration(mStackId, bounds);
        mWindowManager.setAppTask(r.appToken, task.taskId, task.getLaunchBounds(), config);
        r.taskConfigOverride = task.mOverrideConfig;
    }

+25 −21
Original line number Diff line number Diff line
@@ -97,7 +97,6 @@ import android.service.voice.IVoiceInteractionSession;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;

@@ -334,6 +333,9 @@ public final class ActivityStackSupervisor implements DisplayListener {
    // temp. rect used during resize calculation so we don't need to create a new object each time.
    private final Rect tempRect = new Rect();

    private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
    private final SparseArray<Rect> mTmpBounds = new SparseArray<>();

    /**
     * Description of a request to start a new activity, which has been held
     * due to app switches being disabled.
@@ -2917,19 +2919,19 @@ public final class ActivityStackSupervisor implements DisplayListener {
        ActivityRecord r = stack.topRunningActivityLocked(null);
        final boolean resizeTasks = r != null && r.task.mResizeable;

        final IntArray changedTaskIds = new IntArray(stack.numTasks());
        final List<Configuration> newTaskConfigs = new ArrayList<>(stack.numTasks());
        stack.mFullscreen = mWindowManager.resizeStack(
                stackId, bounds, resizeTasks, changedTaskIds, newTaskConfigs);
        for (int i = changedTaskIds.size() - 1; i >= 0; i--) {
            final TaskRecord task = anyTaskForIdLocked(changedTaskIds.get(i), false);
            if (task == null) {
                Slog.wtf(TAG, "Task in WindowManager, but not in ActivityManager???");
                continue;
        mTmpBounds.clear();
        mTmpConfigs.clear();
        if (resizeTasks) {
            ArrayList<TaskRecord> tasks = stack.getAllTasks();
            for (int i = tasks.size() - 1; i >= 0; i--) {
                TaskRecord task = tasks.get(i);
                task.updateOverrideConfiguration(stackId, bounds);
                mTmpConfigs.put(task.taskId, task.mOverrideConfig);
                mTmpBounds.put(task.taskId, task.mBounds);
            }
            task.updateOverrideConfiguration(newTaskConfigs.get(i), bounds);
        }

        stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, resizeTasks, mTmpConfigs,
                mTmpBounds);
        if (stack.mStackId == DOCKED_STACK_ID) {
            // Dock stack funness...Yay!
            if (stack.mFullscreen) {
@@ -3024,25 +3026,27 @@ public final class ActivityStackSupervisor implements DisplayListener {
            stackId = FREEFORM_WORKSPACE_STACK_ID;
        }
        if (stackId != task.stack.mStackId) {
            final String reason = "resizeTask";
            final ActivityStack stack =
                    moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
            moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, "resizeTask");
        }

        final Configuration overrideConfig = mWindowManager.resizeTask(task.taskId, bounds);
        if (task.updateOverrideConfiguration(overrideConfig, bounds)) {
        final Configuration overrideConfig =  task.updateOverrideConfiguration(stackId, bounds);
        // This variable holds information whether the configuration didn't change in a signficant
        // way and the activity was kept the way it was. If it's false, it means the activity had
        // to be relaunched due to configuration change.
        boolean kept = true;
        if (overrideConfig != null) {
            ActivityRecord r = task.topRunningActivityLocked(null);
            if (r != null) {
                final ActivityStack stack = task.stack;
                final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
                // And we need to make sure at this point that all other activities
                // are made visible with the correct configuration.
                kept = stack.ensureActivityConfigurationLocked(r, 0);
                // All other activities must be made visible with their correct configuration.
                ensureActivitiesVisibleLocked(r, 0);
                if (!updated) {
                if (!kept) {
                    resumeTopActivitiesLocked(stack, null, null);
                }
            }
        }
        mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept);
    }

    ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
+2 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.am;

import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

@@ -234,7 +235,7 @@ class LaunchingTaskPositioner {
                break;
            }
        }
        task.setInitialBounds(proposal);
        task.updateOverrideConfiguration(FREEFORM_WORKSPACE_STACK_ID, proposal);
    }

    private boolean shiftedToFar(Rect start, int shiftPolicy) {
+81 −17
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
import static android.app.ActivityManager.INVALID_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
@@ -52,6 +53,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.DisplayMetrics;
import android.util.Slog;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.util.XmlUtils;
@@ -63,6 +65,7 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;

final class TaskRecord {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
@@ -106,6 +109,13 @@ final class TaskRecord {

    static final int INVALID_TASK_ID = -1;

    // The height/width divide used when fitting a task within a bounds with method
    // {@link #fitWithinBounds}.
    // We always want the task to to be visible in the bounds without affecting its size when
    // fitting. To make sure this is the case, we don't adjust the task left or top side pass
    // the input bounds right or bottom side minus the width or height divided by this value.
    private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;

    final int taskId;       // Unique identifier for this task.
    String affinity;        // The affinity name for this task, or null; may change identity.
    String rootAffinity;    // Initial base affinity, or null; does not change from initial root.
@@ -218,6 +228,8 @@ final class TaskRecord {

    Configuration mOverrideConfig = Configuration.EMPTY;

    private Rect mTmpRect = new Rect();

    TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
            IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
        mService = service;
@@ -271,8 +283,7 @@ final class TaskRecord {
            long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
            boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
            int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
            int callingUid, String callingPackage, boolean resizeable, boolean privileged,
            Rect bounds) {
            int callingUid, String callingPackage, boolean resizeable, boolean privileged) {
        mService = service;
        mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
                TaskPersister.IMAGE_EXTENSION;
@@ -309,7 +320,6 @@ final class TaskRecord {
        mCallingPackage = callingPackage;
        mResizeable = resizeable;
        mPrivileged = privileged;
        mBounds = mLastNonFullscreenBounds = bounds;
    }

    void touchActiveTime() {
@@ -1163,7 +1173,8 @@ final class TaskRecord {
                autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
                activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
                callingUid, callingPackage, resizeable, privileged, bounds);
                callingUid, callingPackage, resizeable, privileged);
        task.updateOverrideConfiguration(INVALID_STACK_ID, bounds);

        for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
            activities.get(activityNdx).task = task;
@@ -1173,25 +1184,51 @@ final class TaskRecord {
        return task;
    }

    boolean updateOverrideConfiguration(Configuration newConfig, Rect bounds) {
    /**
     * Update task's override configuration based on the bounds.
     * @return Update configuration or null if there is no change.
     */
    Configuration updateOverrideConfiguration(int stackId, Rect bounds) {
        if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
            // For freeform stack we don't adjust the size of the tasks to match that of the
            // stack, but we do try to make sure the tasks are still contained with the
            // bounds of the stack.
            bounds = fitWithinBounds(bounds);
        }
        if (Objects.equals(mBounds, bounds)) {
            return null;
        }
        Configuration oldConfig = mOverrideConfig;
        mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig;
        // We override the configuration only when the task's dimensions are different from the
        // display. In this manner, we know that if the override configuration is empty, the task
        // is necessarily fullscreen.
        mFullscreen = Configuration.EMPTY.equals(mOverrideConfig);

        mFullscreen = bounds == null;
        if (mFullscreen) {
            if (mBounds != null && stack.mStackId != DOCKED_STACK_ID) {
                mLastNonFullscreenBounds = mBounds;
            }
            mBounds = null;
            mOverrideConfig = Configuration.EMPTY;
        } else {
            mBounds = new Rect(bounds);
            if (stack.mStackId != DOCKED_STACK_ID) {
                mLastNonFullscreenBounds = mBounds;
            }

            final Configuration serviceConfig = mService.mConfiguration;
            mOverrideConfig = new Configuration(serviceConfig);
            // TODO(multidisplay): Update Dp to that of display stack is on.
            final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
            mOverrideConfig.screenWidthDp =
                    Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp);
            mOverrideConfig.screenHeightDp =
                    Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp);
            mOverrideConfig.smallestScreenWidthDp =
                    Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp);
            mOverrideConfig.orientation =
                    (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp)
                            ? Configuration.ORIENTATION_PORTRAIT
                            : Configuration.ORIENTATION_LANDSCAPE;
        }
        return !mOverrideConfig.equals(oldConfig);
        return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
    }

    /** Returns the stack that should be used to launch this task. */
@@ -1225,12 +1262,39 @@ final class TaskRecord {
        return mLastNonFullscreenBounds;
    }

    void setInitialBounds(Rect rect) {
        if (mBounds == null) {
            mBounds = new Rect();
    /** Fits the tasks within the input bounds adjusting the task bounds as needed.
     *  @param bounds Bounds to fit the task within. Nothing is done if null.
     *  @return Returns final configuration after updating with the adjusted bounds.
     *  */
    Rect fitWithinBounds(Rect bounds) {
        if (bounds == null || mBounds == null || bounds.contains(mBounds)) {
            return bounds;
        }
        mBounds.set(rect);
        mLastNonFullscreenBounds = mBounds;
        mTmpRect.set(mBounds);

        if (mBounds.left < bounds.left || mBounds.right > bounds.right) {
            final int maxRight = bounds.right - (bounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
            int horizontalDiff = bounds.left - mBounds.left;
            if ((horizontalDiff < 0 && mBounds.left >= maxRight)
                    || (mBounds.left + horizontalDiff >= maxRight)) {
                horizontalDiff = maxRight - mBounds.left;
            }
            mTmpRect.left += horizontalDiff;
            mTmpRect.right += horizontalDiff;
        }

        if (mBounds.top < bounds.top || mBounds.bottom > bounds.bottom) {
            final int maxBottom = bounds.bottom - (bounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
            int verticalDiff = bounds.top - mBounds.top;
            if ((verticalDiff < 0 && mBounds.top >= maxBottom)
                    || (mBounds.top + verticalDiff >= maxBottom)) {
                verticalDiff = maxBottom - mBounds.top;
            }
            mTmpRect.top += verticalDiff;
            mTmpRect.bottom += verticalDiff;
        }

        return mTmpRect;
    }

    void dump(PrintWriter pw, String prefix) {
Loading