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

Commit ebc3e09c authored by Massimo Carli's avatar Massimo Carli
Browse files

Handle uiMode change in CompatUI

When uiMode changes we need to recreate CompatUI components to
allow the update of the resources in case of switch between
Light/Dark more or when the device is docked/undocked.
This allows to cover the use case of a change in theme of
a docked device showing a restart dialog.

Fixes: 279170801
Test: atest WMShellUnitTests:CompatUIWindowManagerTest
      atest WMShellUnitTests:ReachabilityEduWindowManagerTest
      atest WMShellUnitTests:RestartDialogWindowManagerTest

Change-Id: I179df47bdc23f238dee9ffe6b2e579a67921eb1f
parent d27cba9d
Loading
Loading
Loading
Loading
+22 −12
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;

import dagger.Lazy;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
@@ -55,8 +57,6 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

import dagger.Lazy;

/**
 * Controller to show/update compat UI components on Tasks based on whether the foreground
 * activities are in compatibility mode.
@@ -284,6 +284,10 @@ public class CompatUIController implements OnDisplaysChangedListener,
            ShellTaskOrganizer.TaskListener taskListener) {
        CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId);
        if (layout != null) {
            if (layout.needsToBeRecreated(taskInfo, taskListener)) {
                mActiveCompatLayouts.remove(taskInfo.taskId);
                layout.release();
            } else {
                // UI already exists, update the UI layout.
                if (!layout.updateCompatInfo(taskInfo, taskListener,
                        showOnDisplay(layout.getDisplayId()))) {
@@ -292,6 +296,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
                }
                return;
            }
        }

        // Create a new UI layout.
        final Context context = getOrCreateDisplayContext(taskInfo.displayId);
@@ -433,6 +438,10 @@ public class CompatUIController implements OnDisplaysChangedListener,
    private void createOrUpdateReachabilityEduLayout(TaskInfo taskInfo,
            ShellTaskOrganizer.TaskListener taskListener) {
        if (mActiveReachabilityEduLayout != null) {
            if (mActiveReachabilityEduLayout.needsToBeRecreated(taskInfo, taskListener)) {
                mActiveReachabilityEduLayout.release();
                mActiveReachabilityEduLayout = null;
            } else {
                // UI already exists, update the UI layout.
                if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener,
                        showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) {
@@ -441,6 +450,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
                }
                return;
            }
        }
        // Create a new UI layout.
        final Context context = getOrCreateDisplayContext(taskInfo.displayId);
        if (context == null) {
+1 −7
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED;
import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.app.TaskInfo.CameraCompatControlState;
@@ -53,9 +52,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {

    private final Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartButtonClicked;

    @NonNull
    private TaskInfo mTaskInfo;

    // Remember the last reported states in case visibility changes due to keyguard or IME updates.
    @VisibleForTesting
    boolean mHasSizeCompat;
@@ -77,7 +73,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
            CompatUIHintsState compatUIHintsState, CompatUIConfiguration compatUIConfiguration,
            Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) {
        super(context, taskInfo, syncQueue, taskListener, displayLayout);
        mTaskInfo = taskInfo;
        mCallback = callback;
        mHasSizeCompat = taskInfo.topActivityInSizeCompat;
        mCameraCompatControlState = taskInfo.cameraCompatControlState;
@@ -129,7 +124,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
    @Override
    public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
            boolean canShow) {
        mTaskInfo = taskInfo;
        final boolean prevHasSizeCompat = mHasSizeCompat;
        final int prevCameraCompatControlState = mCameraCompatControlState;
        mHasSizeCompat = taskInfo.topActivityInSizeCompat;
@@ -149,7 +143,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {

    /** Called when the restart button is clicked. */
    void onRestartButtonClicked() {
        mOnRestartButtonClicked.accept(Pair.create(mTaskInfo, getTaskListener()));
        mOnRestartButtonClicked.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
    }

    /** Called when the camera treatment button is clicked. */
+30 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -65,6 +66,9 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
    private DisplayLayout mDisplayLayout;
    private final Rect mStableBounds;

    @NonNull
    private TaskInfo mTaskInfo;

    /**
     * Utility class for adding and releasing a View hierarchy for this {@link
     * WindowlessWindowManager} to {@code mLeash}.
@@ -83,6 +87,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
            SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
            DisplayLayout displayLayout) {
        super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */);
        mTaskInfo = taskInfo;
        mContext = context;
        mSyncQueue = syncQueue;
        mTaskConfig = taskInfo.configuration;
@@ -94,6 +99,17 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
        mDisplayLayout.getStableBounds(mStableBounds);
    }

    /**
     * @return {@code true} if the instance of the specific {@link CompatUIWindowManagerAbstract}
     * for the current task id needs to be recreated loading the related resources. This happens
     * if the user switches between Light/Dark mode, if the device is docked/undocked or if the
     * user switches between multi-window mode to fullscreen where the
     * {@link ShellTaskOrganizer.TaskListener} implementation is different.
     */
    boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
        return hasUiModeChanged(mTaskInfo, taskInfo) || hasTaskListenerChanged(taskListener);
    }

    /**
     * Returns the z-order of this window which will be passed to the {@link SurfaceControl} once
     * {@link #attachToParentSurface} is called.
@@ -195,6 +211,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
    @VisibleForTesting(visibility = PROTECTED)
    public boolean updateCompatInfo(TaskInfo taskInfo,
            ShellTaskOrganizer.TaskListener taskListener, boolean canShow) {
        mTaskInfo = taskInfo;
        final Configuration prevTaskConfig = mTaskConfig;
        final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
        mTaskConfig = taskInfo.configuration;
@@ -315,6 +332,11 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
        updateSurfacePosition();
    }

    @Nullable
    protected TaskInfo getLastTaskInfo() {
        return mTaskInfo;
    }

    /**
     * Called following a change in the task bounds, display layout stable bounds, or the layout
     * direction.
@@ -402,4 +424,12 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
    protected final String getTag() {
        return getClass().getSimpleName();
    }

    protected boolean hasTaskListenerChanged(ShellTaskOrganizer.TaskListener newTaskListener) {
        return !mTaskListener.equals(newTaskListener);
    }

    protected static boolean hasUiModeChanged(TaskInfo currentTaskInfo, TaskInfo newTaskInfo) {
        return currentTaskInfo.configuration.uiMode != newTaskInfo.configuration.uiMode;
    }
}
+1 −7
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.wm.shell.compatui;
import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -69,9 +68,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
    @VisibleForTesting
    LetterboxEduDialogLayout mLayout;

    @NonNull
    private TaskInfo mTaskInfo;

    /**
     * The vertical margin between the dialog container and the task stable bounds (excluding
     * insets).
@@ -99,7 +95,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
            DialogAnimationController<LetterboxEduDialogLayout> animationController,
            DockStateReader dockStateReader, CompatUIConfiguration compatUIConfiguration) {
        super(context, taskInfo, syncQueue, taskListener, displayLayout);
        mTaskInfo = taskInfo;
        mTransitions = transitions;
        mOnDismissCallback = onDismissCallback;
        mAnimationController = animationController;
@@ -197,7 +192,7 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
        mLayout.setDismissOnClickListener(null);
        mAnimationController.startExitAnimation(mLayout, () -> {
            release();
            mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener()));
            mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener()));
        });
    }

@@ -210,7 +205,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
    @Override
    public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
            boolean canShow) {
        mTaskInfo = taskInfo;
        mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation;

        return super.updateCompatInfo(taskInfo, taskListener, canShow);
+4 −10
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -52,9 +51,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {

    private final ShellExecutor mMainExecutor;

    @NonNull
    private TaskInfo mTaskInfo;

    private boolean mIsActivityLetterboxed;

    private int mLetterboxVerticalPosition;
@@ -86,7 +82,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
            ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout,
            CompatUIConfiguration compatUIConfiguration, ShellExecutor mainExecutor) {
        super(context, taskInfo, syncQueue, taskListener, displayLayout);
        mTaskInfo = taskInfo;
        mIsActivityLetterboxed = taskInfo.isLetterboxDoubleTapEnabled;
        mLetterboxVerticalPosition = taskInfo.topActivityLetterboxVerticalPosition;
        mLetterboxHorizontalPosition = taskInfo.topActivityLetterboxHorizontalPosition;
@@ -136,7 +131,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
    @Override
    public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener,
            boolean canShow) {
        mTaskInfo = taskInfo;
        final boolean prevIsActivityLetterboxed = mIsActivityLetterboxed;
        final int prevLetterboxVerticalPosition = mLetterboxVerticalPosition;
        final int prevLetterboxHorizontalPosition = mLetterboxHorizontalPosition;
@@ -222,14 +216,14 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
        if (mLayout == null) {
            return;
        }

        final TaskInfo lastTaskInfo = getLastTaskInfo();
        final boolean eligibleForDisplayHorizontalEducation = mForceUpdate
                || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(mTaskInfo)
                || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(lastTaskInfo)
                || (mHasUserDoubleTapped
                    && (mLetterboxHorizontalPosition == REACHABILITY_LEFT_OR_UP_POSITION
                        || mLetterboxHorizontalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION));
        final boolean eligibleForDisplayVerticalEducation = mForceUpdate
                || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(mTaskInfo)
                || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(lastTaskInfo)
                || (mHasUserDoubleTapped
                    && (mLetterboxVerticalPosition == REACHABILITY_LEFT_OR_UP_POSITION
                        || mLetterboxVerticalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION));
@@ -241,7 +235,7 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract {
            mLayout.handleVisibility(eligibleForDisplayHorizontalEducation,
                    eligibleForDisplayVerticalEducation,
                    mLetterboxVerticalPosition, mLetterboxHorizontalPosition, availableWidth,
                    availableHeight, mCompatUIConfiguration, mTaskInfo);
                    availableHeight, mCompatUIConfiguration, lastTaskInfo);
            if (!mHasLetterboxSizeChanged) {
                updateHideTime();
                mMainExecutor.executeDelayed(this::hideReachability, DISAPPEAR_DELAY_MS);
Loading