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

Commit 78dcebd6 authored by Graciela Wissen Putri's avatar Graciela Wissen Putri
Browse files

[1/n] Move getPreferredLaunchTaskDisplayArea to LaunchParamsUtil

Move logic of resolving launch TaskDisplayArea to common utils for reuse
in DesktopModeLaunchParamsModifier.

This is the first step to decide whether desktop is visible when
TaskDisplayArea is set to freeform with no empty tasks.

Flag: EXEMPT refactor
Bug: 401564801
Test: atest TaskLaunchParamsModifierTests
Change-Id: I8dba79e7e46c5494e1ddd81cc8ed57a75fee9127
parent c201e735
Loading
Loading
Loading
Loading
+185 −0
Original line number Diff line number Diff line
@@ -18,17 +18,24 @@ package com.android.server.wm;

import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;

import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.util.Size;
import android.view.Gravity;
import android.view.View;
import android.window.WindowContainerToken;

import java.util.function.Consumer;

/**
 * The static class that defines some utility constants and functions that are shared among launch
@@ -272,4 +279,182 @@ class LaunchParamsUtil {
        final int yOffset = (int) (fractionOfVerticalOffset * (stableBounds.height() - height));
        inOutBounds.offset(xOffset, yOffset);
    }

    @NonNull
    static TaskDisplayArea getPreferredLaunchTaskDisplayArea(
            @NonNull ActivityTaskSupervisor supervisor, @Nullable Task task,
            @Nullable ActivityOptions options, @Nullable ActivityRecord source,
            @Nullable LaunchParamsController.LaunchParams currentParams,
            @Nullable ActivityRecord activityRecord, @Nullable ActivityStarter.Request request,
            @NonNull Consumer<String> logger) {
        TaskDisplayArea taskDisplayArea = null;

        final WindowContainerToken optionLaunchTaskDisplayAreaToken = options != null
                ? options.getLaunchTaskDisplayArea() : null;
        if (optionLaunchTaskDisplayAreaToken != null) {
            taskDisplayArea = (TaskDisplayArea) WindowContainer.fromBinder(
                    optionLaunchTaskDisplayAreaToken.asBinder());
            logger.accept("display-area-token-from-option=" + taskDisplayArea);
        }

        if (taskDisplayArea == null && options != null) {
            final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId();
            if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
                final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY
                        ? DEFAULT_DISPLAY : options.getLaunchDisplayId();
                final DisplayContent dc = supervisor.mRootWindowContainer
                        .getDisplayContent(launchDisplayId);
                if (dc != null) {
                    taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda ->
                            tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null);
                    logger.accept("display-area-feature-from-option=" + taskDisplayArea);
                }
            }
        }

        // If task display area is not specified in options - try display id
        if (taskDisplayArea == null) {
            final int optionLaunchId =
                    options != null ? options.getLaunchDisplayId() : INVALID_DISPLAY;
            if (optionLaunchId != INVALID_DISPLAY) {
                final DisplayContent dc = supervisor.mRootWindowContainer
                        .getDisplayContent(optionLaunchId);
                if (dc != null) {
                    taskDisplayArea = dc.getDefaultTaskDisplayArea();
                    logger.accept("display-from-option=" + optionLaunchId);
                }
            }
        }

        // If the source activity is a no-display activity, pass on the launch display area token
        // from source activity as currently preferred.
        if (taskDisplayArea == null && source != null && source.isNoDisplay()) {
            taskDisplayArea = source.mHandoverTaskDisplayArea;
            if (taskDisplayArea != null) {
                logger.accept("display-area-from-no-display-source=" + taskDisplayArea);
            } else {
                // Try handover display id
                final int displayId = source.mHandoverLaunchDisplayId;
                final DisplayContent dc =
                        supervisor.mRootWindowContainer.getDisplayContent(displayId);
                if (dc != null) {
                    taskDisplayArea = dc.getDefaultTaskDisplayArea();
                    logger.accept("display-from-no-display-source=" + displayId);
                }
            }
        }

        if (taskDisplayArea == null && source != null) {
            final TaskDisplayArea sourceDisplayArea = source.getDisplayArea();
            logger.accept("display-area-from-source=" + sourceDisplayArea);
            taskDisplayArea = sourceDisplayArea;
        }

        final Task rootTask = (taskDisplayArea == null && task != null)
                ? task.getRootTask() : null;
        if (rootTask != null) {
            logger.accept("display-from-task=" + rootTask.getDisplayId());
            taskDisplayArea = rootTask.getDisplayArea();
        }

        if (taskDisplayArea == null && options != null) {
            final int callerDisplayId = options.getCallerDisplayId();
            final DisplayContent dc =
                    supervisor.mRootWindowContainer.getDisplayContent(callerDisplayId);
            if (dc != null) {
                taskDisplayArea = dc.getDefaultTaskDisplayArea();
                logger.accept("display-from-caller=" + callerDisplayId);
            }
        }

        if (taskDisplayArea == null && currentParams != null) {
            taskDisplayArea = currentParams.mPreferredTaskDisplayArea;
            logger.accept("display-area-from-current-params=" + taskDisplayArea);
        }

        // Re-route to default display if the device didn't declare support for multi-display
        if (taskDisplayArea != null && !supervisor.mService.mSupportsMultiDisplay
                && taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY) {
            taskDisplayArea = supervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
            logger.accept("display-area-from-no-multidisplay=" + taskDisplayArea);
        }

        // Re-route to default display if the home activity doesn't support multi-display
        if (taskDisplayArea != null && activityRecord != null && activityRecord.isActivityTypeHome()
                && !supervisor.mRootWindowContainer.canStartHomeOnDisplayArea(activityRecord.info,
                taskDisplayArea, false /* allowInstrumenting */)) {
            taskDisplayArea = supervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
            logger.accept("display-area-from-home=" + taskDisplayArea);
        }

        return (taskDisplayArea != null)
                ? taskDisplayArea
                : getFallbackDisplayAreaForActivity(activityRecord, request, supervisor, logger);
    }

    /**
     * Calculates the default {@link TaskDisplayArea} for a task. We attempt to put the activity
     * within the same display area if possible. The strategy is to find the display in the
     * following order:
     *
     * <ol>
     *     <li>The display area of the top activity from the launching process will be used</li>
     *     <li>The display area of the top activity from the real launching process will be used
     *     </li>
     *     <li>Default display area from the associated root window container.</li>
     * </ol>
     * @param activityRecord the activity being started
     * @param request optional {@link ActivityStarter.Request} made to start the activity record
     * @return {@link TaskDisplayArea} to house the task
     */
    @NonNull
    private static TaskDisplayArea getFallbackDisplayAreaForActivity(
            @Nullable ActivityRecord activityRecord, @Nullable ActivityStarter.Request request,
            @NonNull ActivityTaskSupervisor supervisor, @NonNull Consumer<String> logger) {
        if (activityRecord != null) {
            final WindowProcessController controllerFromLaunchingRecord =
                    supervisor.mService.getProcessController(
                            activityRecord.launchedFromPid, activityRecord.launchedFromUid);
            if (controllerFromLaunchingRecord != null) {
                final TaskDisplayArea taskDisplayAreaForLaunchingRecord =
                        controllerFromLaunchingRecord.getTopActivityDisplayArea();
                if (taskDisplayAreaForLaunchingRecord != null) {
                    logger.accept("display-area-for-launching-record="
                            + taskDisplayAreaForLaunchingRecord);
                    return taskDisplayAreaForLaunchingRecord;
                }
            }

            final WindowProcessController controllerFromProcess =
                    supervisor.mService.getProcessController(
                            activityRecord.getProcessName(), activityRecord.getUid());
            if (controllerFromProcess != null) {
                final TaskDisplayArea displayAreaForRecord =
                        controllerFromProcess.getTopActivityDisplayArea();
                if (displayAreaForRecord != null) {
                    logger.accept("display-area-for-record=" + displayAreaForRecord);
                    return displayAreaForRecord;
                }
            }
        }

        if (request != null) {
            final WindowProcessController controllerFromRequest =
                    supervisor.mService.getProcessController(
                            request.realCallingPid, request.realCallingUid);
            if (controllerFromRequest != null) {
                final TaskDisplayArea displayAreaFromSourceProcess =
                        controllerFromRequest.getTopActivityDisplayArea();
                if (displayAreaFromSourceProcess != null) {
                    logger.accept("display-area-source-process=" + displayAreaFromSourceProcess);
                    return displayAreaFromSourceProcess;
                }
            }
        }

        final TaskDisplayArea defaultTaskDisplayArea =
                supervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
        logger.accept("display-area-from-default-fallback=" + defaultTaskDisplayArea);
        return defaultTaskDisplayArea;
    }
}
+3 −182
Original line number Diff line number Diff line
@@ -33,13 +33,12 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;

import static com.android.server.wm.ActivityStarter.Request;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.LaunchParamsUtil.getPreferredLaunchTaskDisplayArea;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -51,7 +50,6 @@ import android.graphics.Rect;
import android.util.Size;
import android.util.Slog;
import android.view.Gravity;
import android.window.WindowContainerToken;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.LaunchParamsController.LaunchParams;
@@ -132,8 +130,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
        }

        // STEP 1: Determine the suggested display area to launch the activity/task.
        final TaskDisplayArea suggestedDisplayArea = getPreferredLaunchTaskDisplayArea(task,
                options, source, currentParams, activity, request);
        final TaskDisplayArea suggestedDisplayArea = getPreferredLaunchTaskDisplayArea(mSupervisor,
                task, options, source, currentParams, activity, request, this::appendLog);
        outParams.mPreferredTaskDisplayArea = suggestedDisplayArea;
        final DisplayContent display = suggestedDisplayArea.mDisplayContent;
        if (DEBUG) {
@@ -406,183 +404,6 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
                && launchMode != task.getRequestedOverrideWindowingMode();
    }

    private TaskDisplayArea getPreferredLaunchTaskDisplayArea(@Nullable Task task,
            @Nullable ActivityOptions options, @Nullable ActivityRecord source,
            @Nullable LaunchParams currentParams, @Nullable ActivityRecord activityRecord,
            @Nullable Request request) {
        TaskDisplayArea taskDisplayArea = null;

        final WindowContainerToken optionLaunchTaskDisplayAreaToken = options != null
                ? options.getLaunchTaskDisplayArea() : null;
        if (optionLaunchTaskDisplayAreaToken != null) {
            taskDisplayArea = (TaskDisplayArea) WindowContainer.fromBinder(
                    optionLaunchTaskDisplayAreaToken.asBinder());
            if (DEBUG) appendLog("display-area-token-from-option=" + taskDisplayArea);
        }

        if (taskDisplayArea == null && options != null) {
            final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId();
            if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
                final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY
                        ? DEFAULT_DISPLAY : options.getLaunchDisplayId();
                final DisplayContent dc = mSupervisor.mRootWindowContainer
                        .getDisplayContent(launchDisplayId);
                if (dc != null) {
                    taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda ->
                            tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null);
                    if (DEBUG) appendLog("display-area-feature-from-option=" + taskDisplayArea);
                }
            }
        }

        // If task display area is not specified in options - try display id
        if (taskDisplayArea == null) {
            final int optionLaunchId =
                    options != null ? options.getLaunchDisplayId() : INVALID_DISPLAY;
            if (optionLaunchId != INVALID_DISPLAY) {
                final DisplayContent dc = mSupervisor.mRootWindowContainer
                        .getDisplayContent(optionLaunchId);
                if (dc != null) {
                    taskDisplayArea = dc.getDefaultTaskDisplayArea();
                    if (DEBUG) appendLog("display-from-option=" + optionLaunchId);
                }
            }
        }

        // If the source activity is a no-display activity, pass on the launch display area token
        // from source activity as currently preferred.
        if (taskDisplayArea == null && source != null && source.isNoDisplay()) {
            taskDisplayArea = source.mHandoverTaskDisplayArea;
            if (taskDisplayArea != null) {
                if (DEBUG) appendLog("display-area-from-no-display-source=" + taskDisplayArea);
            } else {
                // Try handover display id
                final int displayId = source.mHandoverLaunchDisplayId;
                final DisplayContent dc =
                        mSupervisor.mRootWindowContainer.getDisplayContent(displayId);
                if (dc != null) {
                    taskDisplayArea = dc.getDefaultTaskDisplayArea();
                    if (DEBUG) appendLog("display-from-no-display-source=" + displayId);
                }
            }
        }

        if (taskDisplayArea == null && source != null) {
            final TaskDisplayArea sourceDisplayArea = source.getDisplayArea();
            if (DEBUG) appendLog("display-area-from-source=" + sourceDisplayArea);
            taskDisplayArea = sourceDisplayArea;
        }

        Task rootTask = (taskDisplayArea == null && task != null)
                ? task.getRootTask() : null;
        if (rootTask != null) {
            if (DEBUG) appendLog("display-from-task=" + rootTask.getDisplayId());
            taskDisplayArea = rootTask.getDisplayArea();
        }

        if (taskDisplayArea == null && options != null) {
            final int callerDisplayId = options.getCallerDisplayId();
            final DisplayContent dc =
                    mSupervisor.mRootWindowContainer.getDisplayContent(callerDisplayId);
            if (dc != null) {
                taskDisplayArea = dc.getDefaultTaskDisplayArea();
                if (DEBUG) appendLog("display-from-caller=" + callerDisplayId);
            }
        }

        if (taskDisplayArea == null && currentParams != null) {
            taskDisplayArea = currentParams.mPreferredTaskDisplayArea;
            if (DEBUG) appendLog("display-area-from-current-params=" + taskDisplayArea);
        }

        // Re-route to default display if the device didn't declare support for multi-display
        if (taskDisplayArea != null && !mSupervisor.mService.mSupportsMultiDisplay
                && taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY) {
            taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
            if (DEBUG) appendLog("display-area-from-no-multidisplay=" + taskDisplayArea);
        }

        // Re-route to default display if the home activity doesn't support multi-display
        if (taskDisplayArea != null && activityRecord != null && activityRecord.isActivityTypeHome()
                && !mSupervisor.mRootWindowContainer.canStartHomeOnDisplayArea(activityRecord.info,
                        taskDisplayArea, false /* allowInstrumenting */)) {
            taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
            if (DEBUG) appendLog("display-area-from-home=" + taskDisplayArea);
        }

        return (taskDisplayArea != null)
                ? taskDisplayArea
                : getFallbackDisplayAreaForActivity(activityRecord, request);
    }

    /**
     * Calculates the default {@link TaskDisplayArea} for a task. We attempt to put the activity
     * within the same display area if possible. The strategy is to find the display in the
     * following order:
     *
     * <ol>
     *     <li>The display area of the top activity from the launching process will be used</li>
     *     <li>The display area of the top activity from the real launching process will be used
     *     </li>
     *     <li>Default display area from the associated root window container.</li>
     * </ol>
     * @param activityRecord the activity being started
     * @param request optional {@link Request} made to start the activity record
     * @return {@link TaskDisplayArea} to house the task
     */
    private TaskDisplayArea getFallbackDisplayAreaForActivity(
            @Nullable ActivityRecord activityRecord, @Nullable Request request) {
        if (activityRecord != null) {
            WindowProcessController controllerFromLaunchingRecord =
                    mSupervisor.mService.getProcessController(
                            activityRecord.launchedFromPid, activityRecord.launchedFromUid);
            if (controllerFromLaunchingRecord != null) {
                final TaskDisplayArea taskDisplayAreaForLaunchingRecord =
                        controllerFromLaunchingRecord.getTopActivityDisplayArea();
                if (taskDisplayAreaForLaunchingRecord != null) {
                    if (DEBUG) {
                        appendLog("display-area-for-launching-record="
                                + taskDisplayAreaForLaunchingRecord);
                    }
                    return taskDisplayAreaForLaunchingRecord;
                }
            }

            WindowProcessController controllerFromProcess =
                    mSupervisor.mService.getProcessController(
                            activityRecord.getProcessName(), activityRecord.getUid());
            if (controllerFromProcess != null) {
                final TaskDisplayArea displayAreaForRecord =
                        controllerFromProcess.getTopActivityDisplayArea();
                if (displayAreaForRecord != null) {
                    if (DEBUG) appendLog("display-area-for-record=" + displayAreaForRecord);
                    return displayAreaForRecord;
                }
            }
        }

        if (request != null) {
            WindowProcessController controllerFromRequest =
                    mSupervisor.mService.getProcessController(
                            request.realCallingPid, request.realCallingUid);
            if (controllerFromRequest != null) {
                final TaskDisplayArea displayAreaFromSourceProcess =
                            controllerFromRequest.getTopActivityDisplayArea();
                if (displayAreaFromSourceProcess != null) {
                    if (DEBUG) {
                        appendLog("display-area-source-process=" + displayAreaFromSourceProcess);
                    }
                    return displayAreaFromSourceProcess;
                }
            }
        }

        final TaskDisplayArea defaultTaskDisplayArea =
                mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
        if (DEBUG) appendLog("display-area-from-default-fallback=" + defaultTaskDisplayArea);
        return defaultTaskDisplayArea;
    }

    private boolean canInheritWindowingModeFromSource(@NonNull DisplayContent display,
            TaskDisplayArea suggestedDisplayArea, @Nullable ActivityRecord source) {
        if (source == null) {