From 2d6097698da5eeced81f770111194449b90ae222 Mon Sep 17 00:00:00 2001 From: tomnatan Date: Wed, 19 Jan 2022 13:50:29 +0000 Subject: [PATCH] [6/n] Letterbox Education: add window manager and connect to controller. Bug: 207010227 Test: atest WMShellUnitTests:CompatUIWindowManagerTest Test: atest WMShellUnitTests:CompatUIControllerTest Change-Id: I1f85245180ffa9b3abe409a0f18bf923bea3a442 --- .../wm/shell/compatui/CompatUIController.java | 134 ++++++--- .../shell/compatui/CompatUIWindowManager.java | 43 ++- .../CompatUIWindowManagerAbstract.java | 57 ++-- .../LetterboxEduDialogLayout.java | 13 + .../LetterboxEduWindowManager.java | 150 ++++++++++ .../compatui/CompatUIControllerTest.java | 120 +++++--- .../wm/shell/compatui/CompatUILayoutTest.java | 66 +++-- .../compatui/CompatUIWindowManagerTest.java | 279 ++++++++++-------- 8 files changed, 588 insertions(+), 274 deletions(-) create mode 100644 libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java index 4d279bc4e927e..656dae3af5ac5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java @@ -40,6 +40,7 @@ import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.annotations.ExternalThread; +import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -74,8 +75,22 @@ public class CompatUIController implements OnDisplaysChangedListener, private final SparseArray mOnInsetsChangedListeners = new SparseArray<>(0); - /** The showing UIs by task id. */ - private final SparseArray mActiveLayouts = new SparseArray<>(0); + /** + * The active Compat Control UI layouts by task id. + * + *

An active layout is a layout that is eligible to be shown for the associated task but + * isn't necessarily shown at a given time. + */ + private final SparseArray mActiveCompatLayouts = new SparseArray<>(0); + + /** + * The active Letterbox Education layout if there is one (there can be at most one active). + * + *

An active layout is a layout that is eligible to be shown for the associated task but + * isn't necessarily shown at a given time. + */ + @Nullable + private LetterboxEduWindowManager mActiveLetterboxEduLayout; /** Avoid creating display context frequently for non-default display. */ private final SparseArray> mDisplayContextCache = new SparseArray<>(0); @@ -135,14 +150,12 @@ public class CompatUIController implements OnDisplaysChangedListener, @Nullable ShellTaskOrganizer.TaskListener taskListener) { if (taskInfo.configuration == null || taskListener == null) { // Null token means the current foreground activity is not in compatibility mode. - removeLayout(taskInfo.taskId); - } else if (mActiveLayouts.contains(taskInfo.taskId)) { - // UI already exists, update the UI layout. - updateLayout(taskInfo, taskListener); - } else { - // Create a new compat UI. - createLayout(taskInfo, taskListener); + removeLayouts(taskInfo.taskId); + return; } + + createOrUpdateCompatLayout(taskInfo, taskListener); + createOrUpdateLetterboxEduLayout(taskInfo, taskListener); } @Override @@ -159,7 +172,7 @@ public class CompatUIController implements OnDisplaysChangedListener, final List toRemoveTaskIds = new ArrayList<>(); forAllLayoutsOnDisplay(displayId, layout -> toRemoveTaskIds.add(layout.getTaskId())); for (int i = toRemoveTaskIds.size() - 1; i >= 0; i--) { - removeLayout(toRemoveTaskIds.get(i)); + removeLayouts(toRemoveTaskIds.get(i)); } } @@ -218,26 +231,39 @@ public class CompatUIController implements OnDisplaysChangedListener, return mDisplaysWithIme.contains(displayId); } - private void createLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { - final Context context = getOrCreateDisplayContext(taskInfo.displayId); - if (context == null) { - Log.e(TAG, "Cannot get context for display " + taskInfo.displayId); + private void createOrUpdateCompatLayout(TaskInfo taskInfo, + ShellTaskOrganizer.TaskListener taskListener) { + CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId); + if (layout != null) { + // UI already exists, update the UI layout. + if (!layout.updateCompatInfo(taskInfo, taskListener, + showOnDisplay(layout.getDisplayId()))) { + // The layout is no longer eligible to be shown, remove from active layouts. + mActiveCompatLayouts.remove(taskInfo.taskId); + } return; } - final CompatUIWindowManager compatUIWindowManager = - createLayout(context, taskInfo, taskListener); - mActiveLayouts.put(taskInfo.taskId, compatUIWindowManager); - compatUIWindowManager.createLayout(showOnDisplay(taskInfo.displayId), taskInfo); + // Create a new UI layout. + final Context context = getOrCreateDisplayContext(taskInfo.displayId); + if (context == null) { + return; + } + layout = createCompatUiWindowManager(context, taskInfo, taskListener); + if (layout.createLayout(showOnDisplay(taskInfo.displayId))) { + // The new layout is eligible to be shown, add it the active layouts. + mActiveCompatLayouts.put(taskInfo.taskId, layout); + } } @VisibleForTesting - CompatUIWindowManager createLayout(Context context, TaskInfo taskInfo, + CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { final CompatUIWindowManager compatUIWindowManager = new CompatUIWindowManager(context, - taskInfo.configuration, mSyncQueue, mCallback, taskInfo.taskId, taskListener, + taskInfo, mSyncQueue, mCallback, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), mHasShownSizeCompatHint, mHasShownCameraCompatHint); + // TODO(b/218304113): updates values only if hints are actually shown to the user. // Only show hints for the first time. if (taskInfo.topActivityInSizeCompat) { mHasShownSizeCompatHint = true; @@ -248,19 +274,53 @@ public class CompatUIController implements OnDisplaysChangedListener, return compatUIWindowManager; } - private void updateLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { - final CompatUIWindowManager layout = mActiveLayouts.get(taskInfo.taskId); - if (layout == null) { + private void createOrUpdateLetterboxEduLayout(TaskInfo taskInfo, + ShellTaskOrganizer.TaskListener taskListener) { + if (mActiveLetterboxEduLayout != null + && mActiveLetterboxEduLayout.getTaskId() == taskInfo.taskId) { + // UI already exists, update the UI layout. + if (!mActiveLetterboxEduLayout.updateCompatInfo(taskInfo, taskListener, + showOnDisplay(mActiveLetterboxEduLayout.getDisplayId()))) { + // The layout is no longer eligible to be shown, clear active layout. + mActiveLetterboxEduLayout = null; + } return; } - layout.updateCompatInfo(taskInfo, taskListener, showOnDisplay(layout.getDisplayId())); + + // Create a new UI layout. + final Context context = getOrCreateDisplayContext(taskInfo.displayId); + if (context == null) { + return; + } + LetterboxEduWindowManager newLayout = new LetterboxEduWindowManager(context, taskInfo, + mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId), + this::onLetterboxEduDismissed); + if (newLayout.createLayout(showOnDisplay(taskInfo.displayId))) { + // The new layout is eligible to be shown, make it the active layout. + if (mActiveLetterboxEduLayout != null) { + // Release the previous layout since at most one can be active. + // Since letterbox education is only shown once to the user, releasing the previous + // layout is only a precaution. + mActiveLetterboxEduLayout.release(); + } + mActiveLetterboxEduLayout = newLayout; + } } - private void removeLayout(int taskId) { - final CompatUIWindowManager layout = mActiveLayouts.get(taskId); + private void onLetterboxEduDismissed() { + mActiveLetterboxEduLayout = null; + } + + private void removeLayouts(int taskId) { + final CompatUIWindowManager layout = mActiveCompatLayouts.get(taskId); if (layout != null) { layout.release(); - mActiveLayouts.remove(taskId); + mActiveCompatLayouts.remove(taskId); + } + + if (mActiveLetterboxEduLayout != null && mActiveLetterboxEduLayout.getTaskId() == taskId) { + mActiveLetterboxEduLayout.release(); + mActiveLetterboxEduLayout = null; } } @@ -278,28 +338,34 @@ public class CompatUIController implements OnDisplaysChangedListener, if (display != null) { context = mContext.createDisplayContext(display); mDisplayContextCache.put(displayId, new WeakReference<>(context)); + } else { + Log.e(TAG, "Cannot get context for display " + displayId); } } return context; } - private void forAllLayoutsOnDisplay(int displayId, Consumer callback) { + private void forAllLayoutsOnDisplay(int displayId, + Consumer callback) { forAllLayouts(layout -> layout.getDisplayId() == displayId, callback); } - private void forAllLayouts(Consumer callback) { + private void forAllLayouts(Consumer callback) { forAllLayouts(layout -> true, callback); } - private void forAllLayouts(Predicate condition, - Consumer callback) { - for (int i = 0; i < mActiveLayouts.size(); i++) { - final int taskId = mActiveLayouts.keyAt(i); - final CompatUIWindowManager layout = mActiveLayouts.get(taskId); + private void forAllLayouts(Predicate condition, + Consumer callback) { + for (int i = 0; i < mActiveCompatLayouts.size(); i++) { + final int taskId = mActiveCompatLayouts.keyAt(i); + final CompatUIWindowManager layout = mActiveCompatLayouts.get(taskId); if (layout != null && condition.test(layout)) { callback.accept(layout); } } + if (mActiveLetterboxEduLayout != null && condition.test(mActiveLetterboxEduLayout)) { + callback.accept(mActiveLetterboxEduLayout); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java index 9c001a37e4b6a..3a37b5e5f128b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java @@ -25,7 +25,6 @@ import android.annotation.Nullable; import android.app.TaskInfo; import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; -import android.content.res.Configuration; import android.graphics.Rect; import android.util.Log; import android.view.LayoutInflater; @@ -36,6 +35,8 @@ import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.compatui.CompatUIController.CompatUICallback; +import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager; /** * Window manager for the Size Compat restart button and Camera Compat control. @@ -43,18 +44,19 @@ import com.android.wm.shell.common.SyncTransactionQueue; class CompatUIWindowManager extends CompatUIWindowManagerAbstract { /** - * The Compat UI should be the topmost child of the Task in case there can be more than one - * child. + * The Compat UI should be below the Letterbox Education. */ - private static final int Z_ORDER = Integer.MAX_VALUE; + private static final int Z_ORDER = LetterboxEduWindowManager.Z_ORDER - 1; - private final CompatUIController.CompatUICallback mCallback; + private final CompatUICallback mCallback; // Remember the last reported states in case visibility changes due to keyguard or IME updates. @VisibleForTesting boolean mHasSizeCompat; + + @VisibleForTesting @CameraCompatControlState - private int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; + int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; @VisibleForTesting boolean mShouldShowSizeCompatHint; @@ -65,12 +67,14 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { @VisibleForTesting CompatUILayout mLayout; - CompatUIWindowManager(Context context, Configuration taskConfig, - SyncTransactionQueue syncQueue, CompatUIController.CompatUICallback callback, - int taskId, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, + CompatUIWindowManager(Context context, TaskInfo taskInfo, + SyncTransactionQueue syncQueue, CompatUICallback callback, + ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, boolean hasShownSizeCompatHint, boolean hasShownCameraCompatHint) { - super(context, taskConfig, syncQueue, taskId, taskListener, displayLayout); + super(context, taskInfo, syncQueue, taskListener, displayLayout); mCallback = callback; + mHasSizeCompat = taskInfo.topActivityInSizeCompat; + mCameraCompatControlState = taskInfo.cameraCompatControlState; mShouldShowSizeCompatHint = !hasShownSizeCompatHint; mShouldShowCameraCompatHint = !hasShownCameraCompatHint; } @@ -80,7 +84,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return Z_ORDER; } - @Override protected @Nullable View getLayout() { return mLayout; @@ -96,16 +99,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { return mHasSizeCompat || shouldShowCameraControl(); } - /** - * Updates the internal state with respect to {@code taskInfo} and calls {@link - * #createLayout(boolean)}. - */ - void createLayout(boolean canShow, TaskInfo taskInfo) { - mHasSizeCompat = taskInfo.topActivityInSizeCompat; - mCameraCompatControlState = taskInfo.cameraCompatControlState; - createLayout(canShow); - } - @Override protected View createLayout() { mLayout = inflateLayout(); @@ -127,19 +120,23 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { } @Override - public void updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, + public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final boolean prevHasSizeCompat = mHasSizeCompat; final int prevCameraCompatControlState = mCameraCompatControlState; mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; - super.updateCompatInfo(taskInfo, taskListener, canShow); + if (!super.updateCompatInfo(taskInfo, taskListener, canShow)) { + return false; + } if (prevHasSizeCompat != mHasSizeCompat || prevCameraCompatControlState != mCameraCompatControlState) { updateVisibilityOfViews(); } + + return true; } /** Called when the restart button is clicked. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java index b9a9db1ee8009..bdf9d513f298a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java @@ -49,7 +49,7 @@ import com.android.wm.shell.common.SyncTransactionQueue; * *

Holds view hierarchy of a root surface and helps to inflate and manage layout. */ -abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { +public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { protected final SyncTransactionQueue mSyncQueue; protected final int mDisplayId; @@ -75,15 +75,15 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { @Nullable protected SurfaceControl mLeash; - protected CompatUIWindowManagerAbstract(Context context, Configuration taskConfig, - SyncTransactionQueue syncQueue, int taskId, - ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout) { - super(taskConfig, null /* rootSurface */, null /* hostInputToken */); + protected CompatUIWindowManagerAbstract(Context context, TaskInfo taskInfo, + SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener, + DisplayLayout displayLayout) { + super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */); mContext = context; mSyncQueue = syncQueue; - mTaskConfig = taskConfig; + mTaskConfig = taskInfo.configuration; mDisplayId = mContext.getDisplayId(); - mTaskId = taskId; + mTaskId = taskInfo.taskId; mTaskListener = taskListener; mDisplayLayout = displayLayout; mStableBounds = new Rect(); @@ -105,12 +105,18 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { * Inflates and inits the layout of this window manager on to the root surface if both {@code * canShow} and {@link #eligibleToShowLayout} are true. * + *

Doesn't do anything if layout is not eligible to be shown. + * * @param canShow whether the layout is allowed to be shown by the parent controller. + * @return whether the layout is eligible to be shown. */ - void createLayout(boolean canShow) { - if (!canShow || !eligibleToShowLayout() || getLayout() != null) { - // Wait until layout should be visible. - return; + protected boolean createLayout(boolean canShow) { + if (!eligibleToShowLayout()) { + return false; + } + if (!canShow || getLayout() != null) { + // Wait until layout should be visible, or layout was already created. + return true; } if (mViewHost != null) { @@ -123,6 +129,8 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { mViewHost.setView(createLayout(), getWindowLayoutParams()); updateSurfacePosition(); + + return true; } /** Inflates and inits the layout of this window manager. */ @@ -174,9 +182,12 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { /** * Called when compat info changed. * + *

The window manager is released if the layout is no longer eligible to be shown. + * * @param canShow whether the layout is allowed to be shown by the parent controller. + * @return whether the layout is eligible to be shown. */ - void updateCompatInfo(TaskInfo taskInfo, + protected boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; @@ -186,12 +197,16 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { // Update configuration. setConfiguration(mTaskConfig); + if (!eligibleToShowLayout()) { + release(); + return false; + } + View layout = getLayout(); if (layout == null || prevTaskListener != taskListener) { // TaskListener changed, recreate the layout for new surface parent. release(); - createLayout(canShow); - return; + return createLayout(canShow); } boolean boundsUpdated = !mTaskConfig.windowConfiguration.getBounds().equals( @@ -207,6 +222,8 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { // Update layout for RTL. layout.setLayoutDirection(mTaskConfig.getLayoutDirection()); } + + return true; } @@ -248,16 +265,16 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { mTaskListener.attachChildSurfaceToTask(mTaskId, b); } - int getDisplayId() { + public int getDisplayId() { return mDisplayId; } - int getTaskId() { + public int getTaskId() { return mTaskId; } /** Releases the surface control and tears down the view hierarchy. */ - void release() { + public void release() { // Hiding before releasing to avoid flickering when transitioning to the Home screen. View layout = getLayout(); if (layout != null) { @@ -278,7 +295,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Re-layouts the view host and updates the surface position. */ - void relayout() { + public void relayout() { if (mViewHost == null) { return; } @@ -334,7 +351,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Gets the layout params. */ - private WindowManager.LayoutParams getWindowLayoutParams() { + protected WindowManager.LayoutParams getWindowLayoutParams() { View layout = getLayout(); if (layout == null) { return new WindowManager.LayoutParams(); @@ -345,7 +362,7 @@ abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager { } /** Gets the layout params given the width and height of the layout. */ - private WindowManager.LayoutParams getWindowLayoutParams(int width, int height) { + protected WindowManager.LayoutParams getWindowLayoutParams(int width, int height) { final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams( // Cannot be wrap_content as this determines the actual window size width, height, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java index fa75d14b4aec1..b045a4af4aacb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java @@ -35,6 +35,8 @@ class LetterboxEduDialogLayout extends FrameLayout { // 204 is simply 255 * 0.8. private static final int BACKGROUND_DIM_ALPHA = 204; + private LetterboxEduWindowManager mWindowManager; + public LetterboxEduDialogLayout(Context context) { this(context, null); } @@ -52,6 +54,17 @@ class LetterboxEduDialogLayout extends FrameLayout { super(context, attrs, defStyleAttr, defStyleRes); } + void inject(LetterboxEduWindowManager windowManager) { + mWindowManager = windowManager; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + // Need to relayout after visibility changes since they affect size. + mWindowManager.relayout(); + } + /** * Register a callback for the dismiss button and background dim. * diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java new file mode 100644 index 0000000000000..e9ffca746a58a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.compatui.letterboxedu; + +import android.annotation.Nullable; +import android.app.TaskInfo; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Rect; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; + +import com.android.wm.shell.R; +import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.compatui.CompatUIWindowManagerAbstract; + +/** + * Window manager for the Letterbox Education. + */ +// TODO(b/215316431): Add tests +public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { + + /** + * The Letterbox Education should be the topmost child of the Task in case there can be more + * than one child. + */ + public static final int Z_ORDER = Integer.MAX_VALUE; + + /** + * The name of the {@link SharedPreferences} that holds which user has seen the Letterbox + * Education for specific packages and which user has seen the full dialog for any package. + */ + private static final String HAS_SEEN_LETTERBOX_EDUCATION_PREF_NAME = + "has_seen_letterbox_education"; + + /** + * The {@link SharedPreferences} instance for {@link #HAS_SEEN_LETTERBOX_EDUCATION_PREF_NAME}. + */ + private final SharedPreferences mSharedPreferences; + + // Remember the last reported state in case visibility changes due to keyguard or IME updates. + private boolean mEligibleForLetterboxEducation; + + @Nullable + private LetterboxEduDialogLayout mLayout; + + private final Runnable mOnDismissCallback; + + public LetterboxEduWindowManager(Context context, TaskInfo taskInfo, + SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener, + DisplayLayout displayLayout, Runnable onDismissCallback) { + super(context, taskInfo, syncQueue, taskListener, displayLayout); + mOnDismissCallback = onDismissCallback; + mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation; + mSharedPreferences = mContext.getSharedPreferences(HAS_SEEN_LETTERBOX_EDUCATION_PREF_NAME, + Context.MODE_PRIVATE); + } + + @Override + protected int getZOrder() { + return Z_ORDER; + } + + @Override + protected @Nullable View getLayout() { + return mLayout; + } + + @Override + protected void removeLayout() { + mLayout = null; + } + + @Override + protected boolean eligibleToShowLayout() { + // If the layout isn't null then it was previously showing, and we shouldn't check if the + // user has seen the letterbox education before. + return mEligibleForLetterboxEducation && (mLayout != null + || !getHasSeenLetterboxEducation()); + } + + @Override + protected View createLayout() { + setSeenLetterboxEducation(); + mLayout = inflateLayout(); + mLayout.inject(this); + mLayout.setDismissOnClickListener(this::onDismiss); + + return mLayout; + } + + private LetterboxEduDialogLayout inflateLayout() { + return (LetterboxEduDialogLayout) LayoutInflater.from(mContext).inflate( + R.layout.letterbox_education_dialog_layout, null); + } + + private void onDismiss() { + release(); + mOnDismissCallback.run(); + } + + @Override + public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, + boolean canShow) { + mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation; + + return super.updateCompatInfo(taskInfo, taskListener, canShow); + } + + @Override + protected void updateSurfacePosition(Rect taskBounds, Rect stableBounds) { + updateSurfacePosition(/* positionX= */ taskBounds.left, /* positionY= */ taskBounds.top); + } + + @Override + protected WindowManager.LayoutParams getWindowLayoutParams() { + final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds(); + return getWindowLayoutParams(/* width= */ taskBounds.right - taskBounds.left, + /* height= */ taskBounds.bottom - taskBounds.top); + } + + private boolean getHasSeenLetterboxEducation() { + return mSharedPreferences.getBoolean(getPrefKey(), /* default= */ false); + } + + private void setSeenLetterboxEducation() { + mSharedPreferences.edit().putBoolean(getPrefKey(), true).apply(); + } + + private String getPrefKey() { + return String.valueOf(mContext.getUserId()); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java index 741da3fe9f580..c5be4854ae8fa 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java @@ -16,15 +16,14 @@ package com.android.wm.shell.compatui; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; -import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; @@ -94,10 +93,12 @@ public class CompatUIControllerTest extends ShellTestCase { doReturn(mMockDisplayLayout).when(mMockDisplayController).getDisplayLayout(anyInt()); doReturn(DISPLAY_ID).when(mMockLayout).getDisplayId(); doReturn(TASK_ID).when(mMockLayout).getTaskId(); + doReturn(true).when(mMockLayout).createLayout(anyBoolean()); + doReturn(true).when(mMockLayout).updateCompatInfo(any(), any(), anyBoolean()); mController = new CompatUIController(mContext, mMockDisplayController, mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) { @Override - CompatUIWindowManager createLayout(Context context, TaskInfo taskInfo, + CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { return mMockLayout; } @@ -113,45 +114,78 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testOnCompatInfoChanged() { - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, true /* hasSizeCompat */, + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); - // Verify that the compat controls are added with non-null size compat info. + // Verify that the compat controls are added with non-null task listener. mController.onCompatInfoChanged(taskInfo, mMockTaskListener); - verify(mController).createLayout(any(), eq(taskInfo), eq(mMockTaskListener)); + verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); - // Verify that the compat controls are updated with non-null new size compat info. - taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, true /* hasSizeCompat */, + // Verify that the compat controls are updated with new size compat info. + clearInvocations(mMockLayout); + clearInvocations(mController); + taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); mController.onCompatInfoChanged(taskInfo, mMockTaskListener); - verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, true /* canShow */); - - // Verify that compat controls are removed with null compat info. - mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - false /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), - null /* taskListener */); - - verify(mMockLayout).release(); + verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, /* canShow= */ true); + // Verify that compat controls are removed with null task listener. clearInvocations(mMockLayout); clearInvocations(mController); - // Verify that compat controls are removed with no size compat and dismissed camera state. - taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - - mController.onCompatInfoChanged(taskInfo, mMockTaskListener); - - verify(mController).createLayout(any(), eq(taskInfo), eq(mMockTaskListener)); - mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - false /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_DISMISSED), - null /* taskListener */); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), + /* taskListener= */ null); verify(mMockLayout).release(); } + @Test + public void testOnCompatInfoChanged_createLayoutReturnsFalse() { + doReturn(false).when(mMockLayout).createLayout(anyBoolean()); + + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, + CAMERA_COMPAT_CONTROL_HIDDEN); + mController.onCompatInfoChanged(taskInfo, mMockTaskListener); + + verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); + + // Verify that the layout is created again. + clearInvocations(mMockLayout); + clearInvocations(mController); + mController.onCompatInfoChanged(taskInfo, mMockTaskListener); + + verify(mMockLayout, never()).updateCompatInfo(any(), any(), anyBoolean()); + verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); + } + + @Test + public void testOnCompatInfoChanged_updateCompatInfoReturnsFalse() { + doReturn(false).when(mMockLayout).updateCompatInfo(any(), any(), anyBoolean()); + + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, + CAMERA_COMPAT_CONTROL_HIDDEN); + mController.onCompatInfoChanged(taskInfo, mMockTaskListener); + + verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); + + clearInvocations(mMockLayout); + clearInvocations(mController); + mController.onCompatInfoChanged(taskInfo, mMockTaskListener); + + verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, /* canShow= */ true); + + // Verify that the layout is created again. + clearInvocations(mMockLayout); + clearInvocations(mController); + mController.onCompatInfoChanged(taskInfo, mMockTaskListener); + + verify(mMockLayout, never()).updateCompatInfo(any(), any(), anyBoolean()); + verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener)); + } + + @Test public void testOnDisplayAdded() { mController.onDisplayAdded(DISPLAY_ID); @@ -165,7 +199,7 @@ public class CompatUIControllerTest extends ShellTestCase { public void testOnDisplayRemoved() { mController.onDisplayAdded(DISPLAY_ID); mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onDisplayRemoved(DISPLAY_ID + 1); @@ -183,7 +217,7 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testOnDisplayConfigurationChanged() { mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, new Configuration()); @@ -198,7 +232,7 @@ public class CompatUIControllerTest extends ShellTestCase { public void testInsetsChanged() { mController.onDisplayAdded(DISPLAY_ID); mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); InsetsState insetsState = new InsetsState(); InsetsSource insetsSource = new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR); insetsSource.setFrame(0, 0, 1000, 1000); @@ -219,22 +253,22 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnImeShowHide() { mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); // Verify that the restart button is hidden after IME is showing. - mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); + mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while IME is showing. - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, true /* hasSizeCompat */, + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); mController.onCompatInfoChanged(taskInfo, mMockTaskListener); - verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, false /* canShow */); + verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, /* canShow= */ false); // Verify button is shown after IME is hidden. - mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); + mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ false); verify(mMockLayout).updateVisibility(true); } @@ -242,7 +276,7 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnKeyguardOccludedChanged() { mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); // Verify that the restart button is hidden after keyguard becomes occluded. mController.onKeyguardOccludedChanged(true); @@ -250,11 +284,11 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while keyguard is occluded. - TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, true /* hasSizeCompat */, + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); mController.onCompatInfoChanged(taskInfo, mMockTaskListener); - verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, false /* canShow */); + verify(mMockLayout).updateCompatInfo(taskInfo, mMockTaskListener, /* canShow= */ false); // Verify button is shown after keyguard becomes not occluded. mController.onKeyguardOccludedChanged(false); @@ -265,9 +299,9 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testButtonRemainsHiddenOnKeyguardOccludedFalseWhenImeIsShowing() { mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); - mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); + mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); mController.onKeyguardOccludedChanged(true); verify(mMockLayout, times(2)).updateVisibility(false); @@ -280,7 +314,7 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockLayout).updateVisibility(false); // Verify button is shown after IME is not showing. - mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); + mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ false); verify(mMockLayout).updateVisibility(true); } @@ -288,9 +322,9 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testButtonRemainsHiddenOnImeHideWhenKeyguardIsOccluded() { mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, - true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); + /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); - mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); + mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ true); mController.onKeyguardOccludedChanged(true); verify(mMockLayout, times(2)).updateVisibility(false); @@ -298,7 +332,7 @@ public class CompatUIControllerTest extends ShellTestCase { clearInvocations(mMockLayout); // Verify button remains hidden after IME is hidden since keyguard is occluded. - mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); + mController.onImeVisibilityChanged(DISPLAY_ID, /* isShowing= */ false); verify(mMockLayout).updateVisibility(false); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java index 211781798af75..352805b6aaf67 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUILayoutTest.java @@ -30,7 +30,6 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.app.TaskInfo; import android.app.TaskInfo.CameraCompatControlState; -import android.content.res.Configuration; import android.testing.AndroidTestingRunner; import android.view.LayoutInflater; import android.view.SurfaceControlViewHost; @@ -69,29 +68,31 @@ public class CompatUILayoutTest extends ShellTestCase { @Mock private SurfaceControlViewHost mViewHost; private CompatUIWindowManager mWindowManager; - private CompatUILayout mCompatUILayout; + private CompatUILayout mLayout; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mWindowManager = new CompatUIWindowManager(mContext, new Configuration(), - mSyncTransactionQueue, mCallback, TASK_ID, mTaskListener, new DisplayLayout(), - false /* hasShownSizeCompatHint */, false /* hasShownCameraCompatHint */); + mWindowManager = new CompatUIWindowManager(mContext, + createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN), + mSyncTransactionQueue, mCallback, mTaskListener, + new DisplayLayout(), /* hasShownSizeCompatHint= */ false, + /* hasShownCameraCompatHint= */ false); - mCompatUILayout = (CompatUILayout) + mLayout = (CompatUILayout) LayoutInflater.from(mContext).inflate(R.layout.compat_ui_layout, null); - mCompatUILayout.inject(mWindowManager); + mLayout.inject(mWindowManager); spyOn(mWindowManager); - spyOn(mCompatUILayout); + spyOn(mLayout); doReturn(mViewHost).when(mWindowManager).createSurfaceViewHost(); - doReturn(mCompatUILayout).when(mWindowManager).inflateLayout(); + doReturn(mLayout).when(mWindowManager).inflateLayout(); } @Test public void testOnClickForRestartButton() { - final ImageButton button = mCompatUILayout.findViewById(R.id.size_compat_restart_button); + final ImageButton button = mLayout.findViewById(R.id.size_compat_restart_button); button.performClick(); verify(mWindowManager).onRestartButtonClicked(); @@ -102,7 +103,7 @@ public class CompatUILayoutTest extends ShellTestCase { public void testOnLongClickForRestartButton() { doNothing().when(mWindowManager).onRestartButtonLongClicked(); - final ImageButton button = mCompatUILayout.findViewById(R.id.size_compat_restart_button); + final ImageButton button = mLayout.findViewById(R.id.size_compat_restart_button); button.performLongClick(); verify(mWindowManager).onRestartButtonLongClicked(); @@ -110,20 +111,20 @@ public class CompatUILayoutTest extends ShellTestCase { @Test public void testOnClickForSizeCompatHint() { - mWindowManager.createLayout(true /* show */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_HIDDEN)); - final LinearLayout sizeCompatHint = mCompatUILayout.findViewById(R.id.size_compat_hint); + mWindowManager.mHasSizeCompat = true; + mWindowManager.createLayout(/* canShow= */ true); + final LinearLayout sizeCompatHint = mLayout.findViewById(R.id.size_compat_hint); sizeCompatHint.performClick(); - verify(mCompatUILayout).setSizeCompatHintVisibility(/* show= */ false); + verify(mLayout).setSizeCompatHintVisibility(/* show= */ false); } @Test public void testUpdateCameraTreatmentButton_treatmentAppliedByDefault() { - mWindowManager.createLayout(true /* show */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED)); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; + mWindowManager.createLayout(/* canShow= */ true); final ImageButton button = - mCompatUILayout.findViewById(R.id.camera_compat_treatment_button); + mLayout.findViewById(R.id.camera_compat_treatment_button); button.performClick(); verify(mWindowManager).onCameraTreatmentButtonClicked(); @@ -138,10 +139,10 @@ public class CompatUILayoutTest extends ShellTestCase { @Test public void testUpdateCameraTreatmentButton_treatmentSuggestedByDefault() { - mWindowManager.createLayout(true /* show */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + mWindowManager.createLayout(/* canShow= */ true); final ImageButton button = - mCompatUILayout.findViewById(R.id.camera_compat_treatment_button); + mLayout.findViewById(R.id.camera_compat_treatment_button); button.performClick(); verify(mWindowManager).onCameraTreatmentButtonClicked(); @@ -156,24 +157,24 @@ public class CompatUILayoutTest extends ShellTestCase { @Test public void testOnCameraDismissButtonClicked() { - mWindowManager.createLayout(true /* show */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + mWindowManager.createLayout(/* canShow= */ true); final ImageButton button = - mCompatUILayout.findViewById(R.id.camera_compat_dismiss_button); + mLayout.findViewById(R.id.camera_compat_dismiss_button); button.performClick(); verify(mWindowManager).onCameraDismissButtonClicked(); verify(mCallback).onCameraControlStateUpdated( TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED); - verify(mCompatUILayout).setCameraControlVisibility(/* show */ false); + verify(mLayout).setCameraControlVisibility(/* show */ false); } @Test - public void testOnLongClickForCameraTreatementButton() { + public void testOnLongClickForCameraTreatmentButton() { doNothing().when(mWindowManager).onCameraButtonLongClicked(); final ImageButton button = - mCompatUILayout.findViewById(R.id.camera_compat_treatment_button); + mLayout.findViewById(R.id.camera_compat_treatment_button); button.performLongClick(); verify(mWindowManager).onCameraButtonLongClicked(); @@ -183,7 +184,7 @@ public class CompatUILayoutTest extends ShellTestCase { public void testOnLongClickForCameraDismissButton() { doNothing().when(mWindowManager).onCameraButtonLongClicked(); - final ImageButton button = mCompatUILayout.findViewById(R.id.camera_compat_dismiss_button); + final ImageButton button = mLayout.findViewById(R.id.camera_compat_dismiss_button); button.performLongClick(); verify(mWindowManager).onCameraButtonLongClicked(); @@ -191,17 +192,18 @@ public class CompatUILayoutTest extends ShellTestCase { @Test public void testOnClickForCameraCompatHint() { - mWindowManager.createLayout(true /* show */, createTaskInfo(false /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); - final LinearLayout hint = mCompatUILayout.findViewById(R.id.camera_compat_hint); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + mWindowManager.createLayout(/* canShow= */ true); + final LinearLayout hint = mLayout.findViewById(R.id.camera_compat_hint); hint.performClick(); - verify(mCompatUILayout).setCameraCompatHintVisibility(/* show= */ false); + verify(mLayout).setCameraCompatHintVisibility(/* show= */ false); } private static TaskInfo createTaskInfo(boolean hasSizeCompat, @CameraCompatControlState int cameraCompatControlState) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); + taskInfo.taskId = TASK_ID; taskInfo.topActivityInSizeCompat = hasSizeCompat; taskInfo.cameraCompatControlState = cameraCompatControlState; return taskInfo; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java index de882eae15038..f9cfd12623647 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java @@ -26,18 +26,16 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.any; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.app.TaskInfo; -import android.content.res.Configuration; import android.graphics.Rect; import android.testing.AndroidTestingRunner; import android.view.DisplayInfo; @@ -75,7 +73,7 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Mock private SyncTransactionQueue mSyncTransactionQueue; @Mock private CompatUIController.CompatUICallback mCallback; @Mock private ShellTaskOrganizer.TaskListener mTaskListener; - @Mock private CompatUILayout mCompatUILayout; + @Mock private CompatUILayout mLayout; @Mock private SurfaceControlViewHost mViewHost; private CompatUIWindowManager mWindowManager; @@ -84,47 +82,97 @@ public class CompatUIWindowManagerTest extends ShellTestCase { public void setUp() { MockitoAnnotations.initMocks(this); - mWindowManager = new CompatUIWindowManager(mContext, new Configuration(), - mSyncTransactionQueue, mCallback, TASK_ID, mTaskListener, new DisplayLayout(), - false /* hasShownSizeCompatHint */, false /* hasShownSizeCompatHint */); + mWindowManager = new CompatUIWindowManager(mContext, + createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN), + mSyncTransactionQueue, mCallback, mTaskListener, + new DisplayLayout(), /* hasShownSizeCompatHint= */ false, + /* hasShownCameraCompatHint= */ false); spyOn(mWindowManager); - doReturn(mCompatUILayout).when(mWindowManager).inflateLayout(); + doReturn(mLayout).when(mWindowManager).inflateLayout(); doReturn(mViewHost).when(mWindowManager).createSurfaceViewHost(); } @Test public void testCreateSizeCompatButton() { - // Not create layout if show is false. - mWindowManager.createLayout(false /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_HIDDEN)); + // Doesn't create layout if show is false. + mWindowManager.mHasSizeCompat = true; + assertTrue(mWindowManager.createLayout(/* canShow= */ false)); verify(mWindowManager, never()).inflateLayout(); - // Not create hint popup. + // Doesn't create hint popup. mWindowManager.mShouldShowSizeCompatHint = false; - mWindowManager.createLayout(true /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_HIDDEN)); + assertTrue(mWindowManager.createLayout(/* canShow= */ true)); verify(mWindowManager).inflateLayout(); - verify(mCompatUILayout, never()).setSizeCompatHintVisibility(true /* show */); + verify(mLayout).setRestartButtonVisibility(/* show= */ true); + verify(mLayout, never()).setSizeCompatHintVisibility(/* show= */ true); - // Create hint popup. + // Creates hint popup. + clearInvocations(mWindowManager); + clearInvocations(mLayout); mWindowManager.release(); mWindowManager.mShouldShowSizeCompatHint = true; - mWindowManager.createLayout(true /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_HIDDEN)); + assertTrue(mWindowManager.createLayout(/* canShow= */ true)); - verify(mWindowManager, times(2)).inflateLayout(); - assertNotNull(mCompatUILayout); - verify(mCompatUILayout).setSizeCompatHintVisibility(true /* show */); + verify(mWindowManager).inflateLayout(); + assertNotNull(mLayout); + verify(mLayout).setRestartButtonVisibility(/* show= */ true); + verify(mLayout).setSizeCompatHintVisibility(/* show= */ true); assertFalse(mWindowManager.mShouldShowSizeCompatHint); + + // Returns false and doesn't create layout if has Size Compat is false. + clearInvocations(mWindowManager); + mWindowManager.release(); + mWindowManager.mHasSizeCompat = false; + assertFalse(mWindowManager.createLayout(/* canShow= */ true)); + + verify(mWindowManager, never()).inflateLayout(); + } + + @Test + public void testCreateCameraCompatControl() { + // Doesn't create layout if show is false. + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + assertTrue(mWindowManager.createLayout(/* canShow= */ false)); + + verify(mWindowManager, never()).inflateLayout(); + + // Doesn't create hint popup. + mWindowManager.mShouldShowCameraCompatHint = false; + assertTrue(mWindowManager.createLayout(/* canShow= */ true)); + + verify(mWindowManager).inflateLayout(); + verify(mLayout).setCameraControlVisibility(/* show= */ true); + verify(mLayout, never()).setCameraCompatHintVisibility(/* show= */ true); + + // Creates hint popup. + clearInvocations(mWindowManager); + clearInvocations(mLayout); + mWindowManager.release(); + mWindowManager.mShouldShowCameraCompatHint = true; + assertTrue(mWindowManager.createLayout(/* canShow= */ true)); + + verify(mWindowManager).inflateLayout(); + assertNotNull(mLayout); + verify(mLayout).setCameraControlVisibility(/* show= */ true); + verify(mLayout).setCameraCompatHintVisibility(/* show= */ true); + assertFalse(mWindowManager.mShouldShowCameraCompatHint); + + // Returns false and doesn't create layout if Camera Compat state is hidden + clearInvocations(mWindowManager); + mWindowManager.release(); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; + assertFalse(mWindowManager.createLayout(/* canShow= */ true)); + + verify(mWindowManager, never()).inflateLayout(); } @Test public void testRelease() { - mWindowManager.createLayout(true /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_HIDDEN)); + mWindowManager.mHasSizeCompat = true; + mWindowManager.createLayout(/* canShow= */ true); verify(mWindowManager).inflateLayout(); @@ -135,12 +183,13 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test public void testUpdateCompatInfo() { - TaskInfo taskInfo = createTaskInfo(true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.createLayout(true /* canShow */, taskInfo); + mWindowManager.mHasSizeCompat = true; + mWindowManager.createLayout(/* canShow= */ true); // No diff clearInvocations(mWindowManager); - mWindowManager.updateCompatInfo(taskInfo, mTaskListener, true /* canShow */); + TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true)); verify(mWindowManager, never()).updateSurfacePosition(); verify(mWindowManager, never()).release(); @@ -150,84 +199,98 @@ public class CompatUIWindowManagerTest extends ShellTestCase { clearInvocations(mWindowManager); final ShellTaskOrganizer.TaskListener newTaskListener = mock( ShellTaskOrganizer.TaskListener.class); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); verify(mWindowManager).release(); - verify(mWindowManager).createLayout(true); - - // Change in Size Compat to false, hides restart button. - clearInvocations(mWindowManager); - taskInfo = createTaskInfo(false /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); - - verify(mCompatUILayout).setRestartButtonVisibility(/* show */ false); - - // Change in Size Compat to true, shows restart button. - clearInvocations(mWindowManager); - clearInvocations(mCompatUILayout); - taskInfo = createTaskInfo(true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); - - verify(mCompatUILayout).setRestartButtonVisibility(/* show */ true); + verify(mWindowManager).createLayout(/* canShow= */ true); // Change Camera Compat state, show a control. clearInvocations(mWindowManager); - clearInvocations(mCompatUILayout); - taskInfo = createTaskInfo(true /* hasSizeCompat */, + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - verify(mCompatUILayout).setCameraControlVisibility(/* show */ true); - verify(mCompatUILayout).updateCameraTreatmentButton( + verify(mLayout).setCameraControlVisibility(/* show= */ true); + verify(mLayout).updateCameraTreatmentButton( CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); // Change Camera Compat state, update a control. clearInvocations(mWindowManager); - clearInvocations(mCompatUILayout); - taskInfo = createTaskInfo(true /* hasSizeCompat */, + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - verify(mCompatUILayout).setCameraControlVisibility(/* show */ true); - verify(mCompatUILayout).updateCameraTreatmentButton( + verify(mLayout).setCameraControlVisibility(/* show= */ true); + verify(mLayout).updateCameraTreatmentButton( CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - // Change Camera Compat state to hidden, hide a control. + // Change has Size Compat to false, hides restart button. clearInvocations(mWindowManager); - clearInvocations(mCompatUILayout); - taskInfo = createTaskInfo(true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ false, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); - verify(mCompatUILayout).setCameraControlVisibility(/* show */ false); + verify(mLayout).setRestartButtonVisibility(/* show= */ false); + + // Change has Size Compat to true, shows restart button. + clearInvocations(mWindowManager); + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); + + verify(mLayout).setRestartButtonVisibility(/* show= */ true); + + // Change Camera Compat state to dismissed, hide a control. + clearInvocations(mWindowManager); + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_DISMISSED); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); + + verify(mLayout).setCameraControlVisibility(/* show= */ false); // Change task bounds, update position. clearInvocations(mWindowManager); - taskInfo = createTaskInfo(true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); taskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000)); - mWindowManager.updateCompatInfo(taskInfo, newTaskListener, true /* canShow */); + assertTrue(mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); verify(mWindowManager).updateSurfacePosition(); + + // Change has Size Compat to false, release layout. + clearInvocations(mWindowManager); + clearInvocations(mLayout); + taskInfo = createTaskInfo(/* hasSizeCompat= */ false, CAMERA_COMPAT_CONTROL_HIDDEN); + assertFalse( + mWindowManager.updateCompatInfo(taskInfo, newTaskListener, /* canShow= */ true)); + + verify(mWindowManager).release(); } @Test public void testUpdateCompatInfoLayoutNotInflatedYet() { - TaskInfo taskInfo = createTaskInfo(true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.createLayout(false /* canShow */, taskInfo); + mWindowManager.mHasSizeCompat = true; + mWindowManager.createLayout(/* canShow= */ false); verify(mWindowManager, never()).inflateLayout(); // Change topActivityInSizeCompat to false and pass canShow true, layout shouldn't be // inflated clearInvocations(mWindowManager); - taskInfo = createTaskInfo(false /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.updateCompatInfo(taskInfo, mTaskListener, true /* canShow */); + TaskInfo taskInfo = createTaskInfo(/* hasSizeCompat= */ false, + CAMERA_COMPAT_CONTROL_HIDDEN); + mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true); verify(mWindowManager, never()).inflateLayout(); // Change topActivityInSizeCompat to true and pass canShow true, layout should be inflated. clearInvocations(mWindowManager); - taskInfo = createTaskInfo(true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); - mWindowManager.updateCompatInfo(taskInfo, mTaskListener, true /* canShow */); + taskInfo = createTaskInfo(/* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN); + mWindowManager.updateCompatInfo(taskInfo, mTaskListener, /* canShow= */ true); verify(mWindowManager).inflateLayout(); } @@ -278,24 +341,24 @@ public class CompatUIWindowManagerTest extends ShellTestCase { // Create button if it is not created. mWindowManager.mLayout = null; mWindowManager.mHasSizeCompat = true; - mWindowManager.updateVisibility(true /* canShow */); + mWindowManager.updateVisibility(/* canShow= */ true); - verify(mWindowManager).createLayout(true /* canShow */); + verify(mWindowManager).createLayout(/* canShow= */ true); // Hide button. clearInvocations(mWindowManager); - doReturn(View.VISIBLE).when(mCompatUILayout).getVisibility(); - mWindowManager.updateVisibility(false /* canShow */); + doReturn(View.VISIBLE).when(mLayout).getVisibility(); + mWindowManager.updateVisibility(/* canShow= */ false); - verify(mWindowManager, never()).createLayout(anyBoolean(), any()); - verify(mCompatUILayout).setVisibility(View.GONE); + verify(mWindowManager, never()).createLayout(anyBoolean()); + verify(mLayout).setVisibility(View.GONE); // Show button. - doReturn(View.GONE).when(mCompatUILayout).getVisibility(); - mWindowManager.updateVisibility(true /* canShow */); + doReturn(View.GONE).when(mLayout).getVisibility(); + mWindowManager.updateVisibility(/* canShow= */ true); - verify(mWindowManager, never()).createLayout(anyBoolean(), any()); - verify(mCompatUILayout).setVisibility(View.VISIBLE); + verify(mWindowManager, never()).createLayout(anyBoolean()); + verify(mLayout).setVisibility(View.VISIBLE); } @Test @@ -308,32 +371,32 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test public void testOnCameraDismissButtonClicked() { - mWindowManager.createLayout(true /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); - clearInvocations(mCompatUILayout); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + mWindowManager.createLayout(/* canShow= */ true); + clearInvocations(mLayout); mWindowManager.onCameraDismissButtonClicked(); verify(mCallback).onCameraControlStateUpdated(TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED); - verify(mCompatUILayout).setCameraControlVisibility(/* show= */ false); + verify(mLayout).setCameraControlVisibility(/* show= */ false); } @Test public void testOnCameraTreatmentButtonClicked() { - mWindowManager.createLayout(true /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); - clearInvocations(mCompatUILayout); + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + mWindowManager.createLayout(/* canShow= */ true); + clearInvocations(mLayout); mWindowManager.onCameraTreatmentButtonClicked(); verify(mCallback).onCameraControlStateUpdated( TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); - verify(mCompatUILayout).updateCameraTreatmentButton( + verify(mLayout).updateCameraTreatmentButton( CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); mWindowManager.onCameraTreatmentButtonClicked(); verify(mCallback).onCameraControlStateUpdated( TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); - verify(mCompatUILayout).updateCameraTreatmentButton( + verify(mLayout).updateCameraTreatmentButton( CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); } @@ -347,65 +410,37 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test public void testOnRestartButtonLongClicked_showHint() { // Not create hint popup. + mWindowManager.mHasSizeCompat = true; mWindowManager.mShouldShowSizeCompatHint = false; - mWindowManager.createLayout(true /* canShow */, createTaskInfo(true /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_HIDDEN)); + mWindowManager.createLayout(/* canShow= */ true); verify(mWindowManager).inflateLayout(); - verify(mCompatUILayout, never()).setSizeCompatHintVisibility(true /* show */); + verify(mLayout, never()).setSizeCompatHintVisibility(/* show= */ true); mWindowManager.onRestartButtonLongClicked(); - verify(mCompatUILayout).setSizeCompatHintVisibility(true /* show */); + verify(mLayout).setSizeCompatHintVisibility(/* show= */ true); } @Test public void testOnCamerControlLongClicked_showHint() { // Not create hint popup. + mWindowManager.mCameraCompatControlState = CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; mWindowManager.mShouldShowCameraCompatHint = false; - mWindowManager.createLayout(true /* canShow */, createTaskInfo(false /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); + mWindowManager.createLayout(/* canShow= */ true); verify(mWindowManager).inflateLayout(); - verify(mCompatUILayout, never()).setCameraCompatHintVisibility(true /* show */); + verify(mLayout, never()).setCameraCompatHintVisibility(/* show= */ true); mWindowManager.onCameraButtonLongClicked(); - verify(mCompatUILayout).setCameraCompatHintVisibility(true /* show */); - } - - @Test - public void testCreateCameraCompatControl() { - // Not create layout if show is false. - mWindowManager.createLayout(false /* canShow */, createTaskInfo(false /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); - - verify(mWindowManager, never()).inflateLayout(); - - // Not create hint popup. - mWindowManager.mShouldShowCameraCompatHint = false; - mWindowManager.createLayout(true /* canShow */, createTaskInfo(false /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); - - verify(mWindowManager).inflateLayout(); - verify(mCompatUILayout, never()).setCameraCompatHintVisibility(true /* show */); - verify(mCompatUILayout).setCameraControlVisibility(true /* show */); - - // Create hint popup. - mWindowManager.release(); - mWindowManager.mShouldShowCameraCompatHint = true; - mWindowManager.createLayout(true /* canShow */, createTaskInfo(false /* hasSizeCompat */, - CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED)); - - verify(mWindowManager, times(2)).inflateLayout(); - assertNotNull(mCompatUILayout); - verify(mCompatUILayout, times(2)).setCameraControlVisibility(true /* show */); - assertFalse(mWindowManager.mShouldShowCameraCompatHint); + verify(mLayout).setCameraCompatHintVisibility(/* show= */ true); } private static TaskInfo createTaskInfo(boolean hasSizeCompat, @TaskInfo.CameraCompatControlState int cameraCompatControlState) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); + taskInfo.taskId = TASK_ID; taskInfo.topActivityInSizeCompat = hasSizeCompat; taskInfo.cameraCompatControlState = cameraCompatControlState; return taskInfo;