[6/n] Letterbox Education: add window manager and connect to controller.
Bug: 207010227 Test: atest WMShellUnitTests:CompatUIWindowManagerTest Test: atest WMShellUnitTests:CompatUIControllerTest Change-Id: I1f85245180ffa9b3abe409a0f18bf923bea3a442
This commit is contained in:
@@ -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<PerDisplayOnInsetsChangedListener> mOnInsetsChangedListeners =
|
||||
new SparseArray<>(0);
|
||||
|
||||
/** The showing UIs by task id. */
|
||||
private final SparseArray<CompatUIWindowManager> mActiveLayouts = new SparseArray<>(0);
|
||||
/**
|
||||
* The active Compat Control UI layouts by task id.
|
||||
*
|
||||
* <p>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<CompatUIWindowManager> mActiveCompatLayouts = new SparseArray<>(0);
|
||||
|
||||
/**
|
||||
* The active Letterbox Education layout if there is one (there can be at most one active).
|
||||
*
|
||||
* <p>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<WeakReference<Context>> 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<Integer> 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<CompatUIWindowManager> callback) {
|
||||
private void forAllLayoutsOnDisplay(int displayId,
|
||||
Consumer<CompatUIWindowManagerAbstract> callback) {
|
||||
forAllLayouts(layout -> layout.getDisplayId() == displayId, callback);
|
||||
}
|
||||
|
||||
private void forAllLayouts(Consumer<CompatUIWindowManager> callback) {
|
||||
private void forAllLayouts(Consumer<CompatUIWindowManagerAbstract> callback) {
|
||||
forAllLayouts(layout -> true, callback);
|
||||
}
|
||||
|
||||
private void forAllLayouts(Predicate<CompatUIWindowManager> condition,
|
||||
Consumer<CompatUIWindowManager> 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<CompatUIWindowManagerAbstract> condition,
|
||||
Consumer<CompatUIWindowManagerAbstract> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -49,7 +49,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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,
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user