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

Commit c295edad authored by tomnatan's avatar tomnatan
Browse files

[14/n] Letterbox Education: Add tests for WM shell code.

In addition, this CL does additional polishing to the code itself.

Bug: 215316431
Test: atest WMShellUnitTests:LetterboxEduDialogLayoutTest
Test: atest WMShellUnitTests:LetterboxEduWindowManagerTest
Test: atest WMShellUnitTests:CompatUIControllerTest
Change-Id: I3cb58f89a52f0d427545e3959dd9082e8b8b5cc7
parent 68eb4fb5
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -292,9 +292,8 @@ public class CompatUIController implements OnDisplaysChangedListener,
        if (context == null) {
            return;
        }
        LetterboxEduWindowManager newLayout = new LetterboxEduWindowManager(context, taskInfo,
                mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId),
                this::onLetterboxEduDismissed);
        LetterboxEduWindowManager newLayout = createLetterboxEduWindowManager(context, taskInfo,
                taskListener);
        if (newLayout.createLayout(showOnDisplay(taskInfo.displayId))) {
            // The new layout is eligible to be shown, make it the active layout.
            if (mActiveLetterboxEduLayout != null) {
@@ -307,6 +306,14 @@ public class CompatUIController implements OnDisplaysChangedListener,
        }
    }

    @VisibleForTesting
    LetterboxEduWindowManager createLetterboxEduWindowManager(Context context, TaskInfo taskInfo,
            ShellTaskOrganizer.TaskListener taskListener) {
        return new LetterboxEduWindowManager(context, taskInfo,
                mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId),
                this::onLetterboxEduDismissed);
    }

    private void onLetterboxEduDismissed() {
        mActiveLetterboxEduLayout = null;
    }
+18 −8
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;

import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
@@ -110,7 +114,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
     * @param canShow whether the layout is allowed to be shown by the parent controller.
     * @return whether the layout is eligible to be shown.
     */
    protected boolean createLayout(boolean canShow) {
    @VisibleForTesting(visibility = PROTECTED)
    public boolean createLayout(boolean canShow) {
        if (!eligibleToShowLayout()) {
            return false;
        }
@@ -184,7 +189,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
     * @param canShow whether the layout is allowed to be shown by the parent controller.
     * @return whether the layout is eligible to be shown.
     */
    protected boolean updateCompatInfo(TaskInfo taskInfo,
    @VisibleForTesting(visibility = PROTECTED)
    public boolean updateCompatInfo(TaskInfo taskInfo,
            ShellTaskOrganizer.TaskListener taskListener, boolean canShow) {
        final Configuration prevTaskConfig = mTaskConfig;
        final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
@@ -201,7 +207,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana

        View layout = getLayout();
        if (layout == null || prevTaskListener != taskListener) {
            // TaskListener changed, recreate the layout for new surface parent.
            // Layout wasn't created yet or TaskListener changed, recreate the layout for new
            // surface parent.
            release();
            return createLayout(canShow);
        }
@@ -227,7 +234,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
     *
     * @param canShow whether the layout is allowed to be shown by the parent controller.
     */
    void updateVisibility(boolean canShow) {
    @VisibleForTesting(visibility = PACKAGE)
    public void updateVisibility(boolean canShow) {
        View layout = getLayout();
        if (layout == null) {
            // Layout may not have been created because it was hidden previously.
@@ -242,7 +250,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
    }

    /** Called when display layout changed. */
    void updateDisplayLayout(DisplayLayout displayLayout) {
    @VisibleForTesting(visibility = PACKAGE)
    public void updateDisplayLayout(DisplayLayout displayLayout) {
        final Rect prevStableBounds = mStableBounds;
        final Rect curStableBounds = new Rect();
        displayLayout.getStableBounds(curStableBounds);
@@ -255,7 +264,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
    }

    /** Called when the surface is ready to be placed under the task surface. */
    @VisibleForTesting
    @VisibleForTesting(visibility = PRIVATE)
    void attachToParentSurface(SurfaceControl.Builder b) {
        mTaskListener.attachChildSurfaceToTask(mTaskId, b);
    }
@@ -347,8 +356,9 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
        return result;
    }

    @VisibleForTesting
    SurfaceControlViewHost createSurfaceViewHost() {
    /** Creates a {@link SurfaceControlViewHost} for this window manager. */
    @VisibleForTesting(visibility = PRIVATE)
    public SurfaceControlViewHost createSurfaceViewHost() {
        return new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
    }

+1 −7
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import com.android.internal.policy.TransitionAnimation;
/**
 * Controls the enter/exit animations of the letterbox education.
 */
// TODO(b/215316431): Add tests
class LetterboxEduAnimationController {
    private static final String TAG = "LetterboxEduAnimation";

@@ -99,15 +98,10 @@ class LetterboxEduAnimationController {
    /**
     * Starts both the background dim fade-out animation and the dialog exit animation.
     */
    void startExitAnimation(@Nullable LetterboxEduDialogLayout layout, Runnable endCallback) {
    void startExitAnimation(@NonNull LetterboxEduDialogLayout layout, Runnable endCallback) {
        // Cancel any previous animation if it's still running.
        cancelAnimation();

        if (layout == null) {
            endCallback.run();
            return;
        }

        final View dialogContainer = layout.getDialogContainer();
        mDialogAnimation = loadAnimation(WindowAnimation_windowExitAnimation);
        if (mDialogAnimation == null) {
+17 −7
Original line number Diff line number Diff line
@@ -29,18 +29,28 @@ import com.android.wm.shell.R;
/**
 * Custom layout for Letterbox Education dialog action.
 */
// TODO(b/215316431): Add tests
class LetterboxEduDialogActionLayout extends FrameLayout {

    LetterboxEduDialogActionLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    public LetterboxEduDialogActionLayout(Context context) {
        this(context, null);
    }

    public LetterboxEduDialogActionLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LetterboxEduDialogActionLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public LetterboxEduDialogActionLayout(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        TypedArray styledAttributes =
                context.getTheme().obtainStyledAttributes(
                        attrs,
                        R.styleable.LetterboxEduDialogActionLayout,
                        /* defStyleAttr= */ 0,
                        /* defStyleRes= */ 0);
                        attrs, R.styleable.LetterboxEduDialogActionLayout, defStyleAttr,
                        defStyleRes);
        int iconId = styledAttributes.getResourceId(
                R.styleable.LetterboxEduDialogActionLayout_icon, 0);
        String text = styledAttributes.getString(
+7 −7
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.compatui.letterboxedu;

import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -31,7 +32,6 @@ import com.android.wm.shell.R;
 * <p>This layout should fill the entire task and the background around the dialog acts as the
 * background dim which dismisses the dialog when clicked.
 */
// TODO(b/215316431): Add tests
class LetterboxEduDialogLayout extends ConstraintLayout {

    // The alpha of a background is a number between 0 (fully transparent) to 255 (fully opaque).
@@ -68,16 +68,16 @@ class LetterboxEduDialogLayout extends ConstraintLayout {
    /**
     * Register a callback for the dismiss button and background dim.
     *
     * @param callback The callback to register
     * @param callback The callback to register or null if all on click listeners should be removed.
     */
    void setDismissOnClickListener(Runnable callback) {
        findViewById(R.id.letterbox_education_dialog_dismiss_button).setOnClickListener(
                view -> callback.run());
    void setDismissOnClickListener(@Nullable Runnable callback) {
        final OnClickListener listener = callback == null ? null : view -> callback.run();
        findViewById(R.id.letterbox_education_dialog_dismiss_button).setOnClickListener(listener);
        // Clicks on the background dim should also dismiss the dialog.
        setOnClickListener(view -> callback.run());
        setOnClickListener(listener);
        // We add a no-op on-click listener to the dialog container so that clicks on it won't
        // propagate to the listener of the layout (which represents the background dim).
        mDialogContainer.setOnClickListener(view -> {});
        mDialogContainer.setOnClickListener(callback == null ? null : view -> {});
    }

    @Override
Loading