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

Commit e9d7d941 authored by Charles Chen's avatar Charles Chen
Browse files

Consolidate mTaskBounds logic to mConfiguration

After the horizontal layout feature, the split layout is not just
determined by task bounds, but the whole task Configuration should
be take account.

This CL removes the mTaskBounds logic and consolidate to use
TaskContainer#mConfiguration instead. This CL also introduces
ActivityClient#getTaskConfiguration to obtain task config at
TaskContainer initialization.

Bug: 240219484
Test: atest WMJetpackUnitTests

Change-Id: I5725ac92d841c53675c78b9e50e0d3fee3973f37
parent 7cf9a10a
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -227,12 +227,13 @@ public class ActivityClient {
    }

    /**
     * Returns the windowing mode of the task that hosts the activity, or {@code -1} if task is not
     * found.
     * Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
     * the task {@link Configuration} cannot be obtained.
     */
    public int getTaskWindowingMode(IBinder activityToken) {
    @Nullable
    public Configuration getTaskConfiguration(IBinder activityToken) {
        try {
            return getActivityClientController().getTaskWindowingMode(activityToken);
            return getActivityClientController().getTaskConfiguration(activityToken);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+5 −1
Original line number Diff line number Diff line
@@ -78,7 +78,11 @@ interface IActivityClientController {
    boolean willActivityBeVisible(in IBinder token);
    int getDisplayId(in IBinder activityToken);
    int getTaskForActivity(in IBinder token, in boolean onlyRoot);
    int getTaskWindowingMode(in IBinder activityToken);
    /**
     * Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
     * the task {@link Configuration} cannot be obtained.
     */
    Configuration getTaskConfiguration(in IBinder activityToken);
    IBinder getActivityTokenBelow(IBinder token);
    ComponentName getCallingActivity(in IBinder token);
    String getCallingPackage(in IBinder token);
+0 −15
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAs
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
import static androidx.window.extensions.embedding.SplitPresenter.RESULT_EXPAND_FAILED_NO_TF_INFO;
import static androidx.window.extensions.embedding.SplitPresenter.getActivityIntentMinDimensionsPair;
import static androidx.window.extensions.embedding.SplitPresenter.getNonEmbeddedActivityBounds;
import static androidx.window.extensions.embedding.SplitPresenter.shouldShowSplit;

import android.app.Activity;
@@ -464,7 +463,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            // parentInfo#isVisibleRequested is true.
            return;
        }
        onTaskContainerInfoChanged(taskContainer, parentInfo.getConfiguration());
        if (isInPictureInPicture(parentInfo.getConfiguration())) {
            // No need to update presentation in PIP until the Task exit PIP.
            return;
@@ -614,12 +612,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        }
    }

    @GuardedBy("mLock")
    private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer,
            @NonNull Configuration config) {
        taskContainer.setTaskBounds(config.windowConfiguration.getBounds());
    }

    /** Returns whether the given {@link TaskContainer} may show in split. */
    // Suppress GuardedBy warning because lint asks to mark this method as
    // @GuardedBy(mPresenter.mController.mLock), which is mLock itself
@@ -1235,13 +1227,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        final TaskContainer taskContainer = mTaskContainers.get(taskId);
        final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
                pendingAppearedIntent, taskContainer, this);
        if (!taskContainer.isTaskBoundsInitialized()) {
            // Get the initial bounds before the TaskFragment has appeared.
            final Rect taskBounds = getNonEmbeddedActivityBounds(activityInTask);
            if (!taskContainer.setTaskBounds(taskBounds)) {
                Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
            }
        }
        return container;
    }

+1 −17
Original line number Diff line number Diff line
@@ -932,11 +932,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        if (taskContainer != null) {
            return taskContainer.getTaskProperties();
        }
        // Use a copy of configuration because activity's configuration may be updated later,
        // or we may get unexpected TaskContainer's configuration if Activity's configuration is
        // updated. An example is Activity is going to be in split.
        return new TaskProperties(activity.getDisplayId(),
                new Configuration(activity.getResources().getConfiguration()));
        return TaskProperties.getTaskPropertiesFromActivity(activity);
    }

    @NonNull
@@ -950,16 +946,4 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        // TODO(b/190433398): Supply correct insets.
        return new WindowMetrics(taskBounds, WindowInsets.CONSUMED);
    }

    /** Obtains the bounds from a non-embedded Activity. */
    @NonNull
    static Rect getNonEmbeddedActivityBounds(@NonNull Activity activity) {
        final WindowConfiguration windowConfiguration =
                activity.getResources().getConfiguration().windowConfiguration;
        if (!activity.isInMultiWindowMode()) {
            // In fullscreen mode the max bounds should correspond to the task bounds.
            return windowConfiguration.getMaxBounds();
        }
        return windowConfiguration.getBounds();
    }
}
+48 −27
Original line number Diff line number Diff line
@@ -20,14 +20,17 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.inMultiWindowMode;

import android.app.Activity;
import android.app.ActivityClient;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.ArraySet;
import android.util.Log;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentParentInfo;
import android.window.WindowContainerTransaction;
@@ -41,14 +44,11 @@ import java.util.Set;

/** Represents TaskFragments and split pairs below a Task. */
class TaskContainer {
    private static final String TAG = TaskContainer.class.getSimpleName();

    /** The unique task id. */
    private final int mTaskId;

    // TODO(b/240219484): consolidate to mConfiguration
    /** Available window bounds of this Task. */
    private final Rect mTaskBounds = new Rect();

    /** Active TaskFragments in this Task. */
    @NonNull
    final List<TaskFragmentContainer> mContainers = new ArrayList<>();
@@ -86,10 +86,10 @@ class TaskContainer {
            throw new IllegalArgumentException("Invalid Task id");
        }
        mTaskId = taskId;
        // Make a copy in case the activity's config is updated, and updates the TaskContainer's
        // config unexpectedly.
        mConfiguration = new Configuration(activityInTask.getResources().getConfiguration());
        mDisplayId = activityInTask.getDisplayId();
        final TaskProperties taskProperties = TaskProperties
                .getTaskPropertiesFromActivity(activityInTask);
        mConfiguration = taskProperties.getConfiguration();
        mDisplayId = taskProperties.getDisplayId();
        // Note that it is always called when there's a new Activity is started, which implies
        // the host task is visible.
        mIsVisible = true;
@@ -107,25 +107,6 @@ class TaskContainer {
        return mIsVisible;
    }

    @NonNull
    Rect getTaskBounds() {
        return mTaskBounds;
    }

    /** Returns {@code true} if the bounds is changed. */
    boolean setTaskBounds(@NonNull Rect taskBounds) {
        if (!taskBounds.isEmpty() && !mTaskBounds.equals(taskBounds)) {
            mTaskBounds.set(taskBounds);
            return true;
        }
        return false;
    }

    /** Whether the Task bounds has been initialized. */
    boolean isTaskBoundsInitialized() {
        return !mTaskBounds.isEmpty();
    }

    @NonNull
    Configuration getConfiguration() {
        // Make a copy in case the config is updated unexpectedly.
@@ -261,5 +242,45 @@ class TaskContainer {
        Configuration getConfiguration() {
            return mConfiguration;
        }

        /**
         * Obtains the {@link TaskProperties} for the task that the provided {@link Activity} is
         * associated with.
         * <p>
         * Note that for most case, caller should use
         * {@link SplitPresenter#getTaskProperties(Activity)} instead. This method is used before
         * the {@code activity} goes into split.
         * </p><p>
         * If the {@link Activity} is in fullscreen, override
         * {@link WindowConfiguration#getBounds()} with {@link WindowConfiguration#getMaxBounds()}
         * in case the {@link Activity} is letterboxed. Otherwise, get the Task
         * {@link Configuration} from the server side or use {@link Activity}'s
         * {@link Configuration} as a fallback if the Task {@link Configuration} cannot be obtained.
         */
        @NonNull
        static TaskProperties getTaskPropertiesFromActivity(@NonNull Activity activity) {
            final int displayId = activity.getDisplayId();
            // Use a copy of configuration because activity's configuration may be updated later,
            // or we may get unexpected TaskContainer's configuration if Activity's configuration is
            // updated. An example is Activity is going to be in split.
            final Configuration activityConfig = new Configuration(
                    activity.getResources().getConfiguration());
            final WindowConfiguration windowConfiguration = activityConfig.windowConfiguration;
            final int windowingMode = windowConfiguration.getWindowingMode();
            if (!inMultiWindowMode(windowingMode)) {
                // Use the max bounds in fullscreen in case the Activity is letterboxed.
                windowConfiguration.setBounds(windowConfiguration.getMaxBounds());
                return new TaskProperties(displayId, activityConfig);
            }
            final Configuration taskConfig = ActivityClient.getInstance()
                    .getTaskConfiguration(activity.getActivityToken());
            if (taskConfig == null) {
                Log.w(TAG, "Could not obtain task configuration for activity:" + activity);
                // Still report activity config if task config cannot be obtained from the server
                // side.
                return new TaskProperties(displayId, activityConfig);
            }
            return new TaskProperties(displayId, taskConfig);
        }
    }
}
Loading