diff options
author | Mariia Sandrikova <mariiasand@google.com> | 2021-12-18 21:39:13 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2021-12-18 21:39:13 +0000 |
commit | 3486eacda3563c0420e1a1d29c16876092b02eca (patch) | |
tree | e7d4b052931b55f592ddcb57b031961fbb2c2e16 /libs | |
parent | 0eeab2b04d96c650d6371b4014906cc12473dee4 (diff) | |
parent | 13e80fd997dc782c9f037925cce99ad75583c688 (diff) |
Merge changes from topic "camera-compat" into sc-v2-dev
* changes:
[3/n] Camera Compat UI: Add a camera compat control.
[2/n] Camera Compat UI: Add interfaces for client-server communication.
Diffstat (limited to 'libs')
21 files changed, 867 insertions, 141 deletions
diff --git a/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml b/libs/WindowManager/Shell/res/color/compat_background_ripple.xml index 329e5b9b31a0..329e5b9b31a0 100644 --- a/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml +++ b/libs/WindowManager/Shell/res/color/compat_background_ripple.xml diff --git a/libs/WindowManager/Shell/res/drawable/camera_compat_dismiss_button.xml b/libs/WindowManager/Shell/res/drawable/camera_compat_dismiss_button.xml new file mode 100644 index 000000000000..1c8cb914af81 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/camera_compat_dismiss_button.xml @@ -0,0 +1,33 @@ +<!-- + Copyright (C) 2019 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="43dp" + android:viewportWidth="48" + android:viewportHeight="43"> + <group> + <clip-path + android:pathData="M48,43l-48,-0l-0,-43l48,-0z"/> + <path + android:pathData="M24,43C37.2548,43 48,32.2548 48,19L48,0L0,-0L0,19C0,32.2548 10.7452,43 24,43Z" + android:fillColor="@color/compat_controls_background" + android:strokeAlpha="0.8" + android:fillAlpha="0.8"/> + <path + android:pathData="M31,12.41L29.59,11L24,16.59L18.41,11L17,12.41L22.59,18L17,23.59L18.41,25L24,19.41L29.59,25L31,23.59L25.41,18L31,12.41Z" + android:fillColor="@color/compat_controls_text"/> + </group> +</vector> diff --git a/libs/WindowManager/Shell/res/drawable/camera_compat_dismiss_ripple.xml b/libs/WindowManager/Shell/res/drawable/camera_compat_dismiss_ripple.xml new file mode 100644 index 000000000000..c81013966c35 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/camera_compat_dismiss_ripple.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/compat_background_ripple"> + <item android:drawable="@drawable/camera_compat_dismiss_button"/> +</ripple>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_applied_button.xml b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_applied_button.xml new file mode 100644 index 000000000000..c796b5967f98 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_applied_button.xml @@ -0,0 +1,32 @@ +<!-- + Copyright (C) 2019 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="43dp" + android:viewportWidth="48" + android:viewportHeight="43"> + <path + android:pathData="M24,0C10.7452,0 0,10.7452 0,24V43H48V24C48,10.7452 37.2548,0 24,0Z" + android:fillColor="@color/compat_controls_background" + android:strokeAlpha="0.8" + android:fillAlpha="0.8"/> + <path + android:pathData="M32,17H28.83L27,15H21L19.17,17H16C14.9,17 14,17.9 14,19V31C14,32.1 14.9,33 16,33H32C33.1,33 34,32.1 34,31V19C34,17.9 33.1,17 32,17ZM32,31H16V19H32V31Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M24.6618,22C23.0436,22 21.578,22.6187 20.4483,23.625L18.25,21.375V27H23.7458L21.5353,24.7375C22.3841,24.0125 23.4649,23.5625 24.6618,23.5625C26.8235,23.5625 28.6616,25.0062 29.3028,27L30.75,26.5125C29.9012,23.8938 27.5013,22 24.6618,22Z" + android:fillColor="@color/compat_controls_text"/> +</vector> diff --git a/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_applied_ripple.xml b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_applied_ripple.xml new file mode 100644 index 000000000000..3e9fe6dc3b99 --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_applied_ripple.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/compat_background_ripple"> + <item android:drawable="@drawable/camera_compat_treatment_applied_button"/> +</ripple> diff --git a/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_suggested_button.xml b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_suggested_button.xml new file mode 100644 index 000000000000..af505d1cb73c --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_suggested_button.xml @@ -0,0 +1,53 @@ +<!-- + Copyright (C) 2019 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="43dp" + android:viewportWidth="48" + android:viewportHeight="43"> + <path + android:pathData="M24,0C10.7452,0 0,10.7452 0,24V43H48V24C48,10.7452 37.2548,0 24,0Z" + android:fillColor="@color/compat_controls_background" + android:strokeAlpha="0.8" + android:fillAlpha="0.8"/> + <path + android:pathData="M32,17H28.83L27,15H21L19.17,17H16C14.9,17 14,17.9 14,19V31C14,32.1 14.9,33 16,33H32C33.1,33 34,32.1 34,31V19C34,17.9 33.1,17 32,17ZM32,31H16V19H32V31Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M18,29L18,25.5L19.5,25.5L19.5,29L18,29Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M30,29L30,25.5L28.5,25.5L28.5,29L30,29Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M30,21L30,24.5L28.5,24.5L28.5,21L30,21Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M18,21L18,24.5L19.5,24.5L19.5,21L18,21Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M18,27.5L21.5,27.5L21.5,29L18,29L18,27.5Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M30,27.5L26.5,27.5L26.5,29L30,29L30,27.5Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M30,22.5L26.5,22.5L26.5,21L30,21L30,22.5Z" + android:fillColor="@color/compat_controls_text"/> + <path + android:pathData="M18,22.5L21.5,22.5L21.5,21L18,21L18,22.5Z" + android:fillColor="@color/compat_controls_text"/> +</vector> diff --git a/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_suggested_ripple.xml b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_suggested_ripple.xml new file mode 100644 index 000000000000..c0f1c89b0cbb --- /dev/null +++ b/libs/WindowManager/Shell/res/drawable/camera_compat_treatment_suggested_ripple.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/compat_background_ripple"> + <item android:drawable="@drawable/camera_compat_treatment_suggested_button"/> +</ripple> diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml index ab74e43472c3..e6ae28207970 100644 --- a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml +++ b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml @@ -21,7 +21,9 @@ android:viewportHeight="48"> <path android:fillColor="@color/compat_controls_background" - android:pathData="M0,24 a24,24 0 1,0 48,0 a24,24 0 1,0 -48,0" /> + android:strokeAlpha="0.8" + android:fillAlpha="0.8" + android:pathData="M0,24 a24,24 0 1,0 48,0 a24,24 0 1,0 -48,0"/> <group android:translateX="12" android:translateY="12"> diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml index 95decff24ac4..6551edf6d0e6 100644 --- a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml +++ b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml @@ -15,6 +15,6 @@ ~ limitations under the License. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" - android:color="@color/size_compat_background_ripple"> + android:color="@color/compat_background_ripple"> <item android:drawable="@drawable/size_compat_restart_button"/> </ripple>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml index c04e258ea784..4ac972c6cfa7 100644 --- a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml +++ b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml @@ -16,7 +16,7 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:clipToPadding="false" @@ -26,7 +26,7 @@ <TextView android:id="@+id/compat_mode_hint_text" - android:layout_width="188dp" + android:layout_width="match_parent" android:layout_height="wrap_content" android:lineSpacingExtra="4sp" android:background="@drawable/compat_hint_bubble" diff --git a/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml b/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml index 6f946b25eaa5..c99f3fe89563 100644 --- a/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml +++ b/libs/WindowManager/Shell/res/layout/compat_ui_layout.xml @@ -21,24 +21,51 @@ android:orientation="vertical" android:gravity="bottom|end"> - <include android:id="@+id/size_compat_hint" - layout="@layout/compat_mode_hint"/> + <include android:id="@+id/camera_compat_hint" + android:visibility="gone" + android:layout_width="@dimen/camera_compat_hint_width" + android:layout_height="wrap_content" + layout="@layout/compat_mode_hint"/> - <FrameLayout - android:layout_width="@dimen/size_compat_button_width" - android:layout_height="@dimen/size_compat_button_height" + <LinearLayout + android:id="@+id/camera_compat_control" + android:visibility="gone" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:clipToPadding="false" - android:paddingBottom="16dp"> + android:layout_marginEnd="16dp" + android:layout_marginBottom="16dp" + android:orientation="vertical"> + + <ImageButton + android:id="@+id/camera_compat_treatment_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@android:color/transparent"/> <ImageButton - android:id="@+id/size_compat_restart_button" + android:id="@+id/camera_compat_dismiss_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center" - android:src="@drawable/size_compat_restart_button_ripple" + android:src="@drawable/camera_compat_dismiss_ripple" android:background="@android:color/transparent" - android:contentDescription="@string/restart_button_description"/> + android:contentDescription="@string/camera_compat_dismiss_button_description"/> + + </LinearLayout> + + <include android:id="@+id/size_compat_hint" + android:visibility="gone" + android:layout_width="@dimen/size_compat_hint_width" + android:layout_height="wrap_content" + layout="@layout/compat_mode_hint"/> - </FrameLayout> + <ImageButton + android:id="@+id/size_compat_restart_button" + android:visibility="gone" + android:layout_width="@dimen/size_compat_button_width" + android:layout_height="@dimen/size_compat_button_height" + android:src="@drawable/size_compat_restart_button_ripple" + android:background="@android:color/transparent" + android:contentDescription="@string/restart_button_description"/> </com.android.wm.shell.compatui.CompatUILayout> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index 18e91f41a698..d338e3bd74f9 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -216,6 +216,12 @@ - compat_hint_corner_radius - compat_hint_point_width /2). --> <dimen name="compat_hint_padding_end">7dp</dimen> + <!-- The width of the size compat hint. --> + <dimen name="size_compat_hint_width">188dp</dimen> + + <!-- The width of the camera compat hint. --> + <dimen name="camera_compat_hint_width">143dp</dimen> + <!-- The width of the brand image on staring surface. --> <dimen name="starting_surface_brand_image_width">200dp</dimen> diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml index c88fc16e218e..ab0013a2b0b4 100644 --- a/libs/WindowManager/Shell/res/values/strings.xml +++ b/libs/WindowManager/Shell/res/values/strings.xml @@ -158,4 +158,17 @@ <!-- Description of the restart button in the hint of size compatibility mode. [CHAR LIMIT=NONE] --> <string name="restart_button_description">Tap to restart this app and go full screen.</string> + + <!-- Description of the camera compat button for applying stretched issues treatment in the hint for + compatibility control. [CHAR LIMIT=NONE] --> + <string name="camera_compat_treatment_suggested_button_description">Camera issues?\nTap to refit</string> + + <!-- Description of the camera compat button for reverting stretched issues treatment in the hint for + compatibility control. [CHAR LIMIT=NONE] --> + <string name="camera_compat_treatment_applied_button_description">Didn\u2019t fix it?\nTap to revert</string> + + <!-- Accessibillity description of the camera dismiss button for stretched issues in the hint for + compatibility control. [CHAR LIMIT=NONE] --> + <string name="camera_compat_dismiss_button_description">No camera issues? Tap to dismiss.</string> + </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 8b3a35688f11..91ea436f81b6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -458,7 +458,7 @@ public class ShellTaskOrganizer extends TaskOrganizer implements newListener.onTaskInfoChanged(taskInfo); } notifyLocusVisibilityIfNeeded(taskInfo); - if (updated || !taskInfo.equalsForSizeCompat(data.getTaskInfo())) { + if (updated || !taskInfo.equalsForCompatUi(data.getTaskInfo())) { // Notify the compat UI if the listener or task info changed. notifyCompatUI(taskInfo, newListener); } @@ -607,6 +607,19 @@ public class ShellTaskOrganizer extends TaskOrganizer implements restartTaskTopActivityProcessIfVisible(info.getTaskInfo().token); } + @Override + public void onCameraControlStateUpdated( + int taskId, @TaskInfo.CameraCompatControlState int state) { + final TaskAppearedInfo info; + synchronized (mLock) { + info = mTasks.get(taskId); + } + if (info == null) { + return; + } + updateCameraCompatControlState(info.getTaskInfo().token, state); + } + private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info, int event) { ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo; @@ -633,14 +646,11 @@ public class ShellTaskOrganizer extends TaskOrganizer implements // The task is vanished or doesn't support compat UI, notify to remove compat UI // on this Task if there is any. if (taskListener == null || !taskListener.supportCompatUI() - || !taskInfo.topActivityInSizeCompat || !taskInfo.isVisible) { - mCompatUI.onCompatInfoChanged(taskInfo.displayId, taskInfo.taskId, - null /* taskConfig */, null /* taskListener */); + || !taskInfo.hasCompatUI() || !taskInfo.isVisible) { + mCompatUI.onCompatInfoChanged(taskInfo, null /* taskListener */); return; } - - mCompatUI.onCompatInfoChanged(taskInfo.displayId, taskInfo.taskId, - taskInfo.configuration, taskListener); + mCompatUI.onCompatInfoChanged(taskInfo, taskListener); } private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) { 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 e0b23873a980..8f4cfb0a49a4 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 @@ -17,6 +17,8 @@ package com.android.wm.shell.compatui; import android.annotation.Nullable; +import android.app.TaskInfo; +import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.content.res.Configuration; import android.hardware.display.DisplayManager; @@ -53,12 +55,14 @@ import java.util.function.Predicate; public class CompatUIController implements OnDisplaysChangedListener, DisplayImeController.ImePositionProcessor { - /** Callback for size compat UI interaction. */ + /** Callback for compat UI interaction. */ public interface CompatUICallback { /** Called when the size compat restart button appears. */ void onSizeCompatRestartButtonAppeared(int taskId); /** Called when the size compat restart button is clicked. */ void onSizeCompatRestartButtonClicked(int taskId); + /** Called when the camera compat control state is updated. */ + void onCameraControlStateUpdated(int taskId, @CameraCompatControlState int state); } private static final String TAG = "CompatUIController"; @@ -86,10 +90,12 @@ public class CompatUIController implements OnDisplaysChangedListener, private CompatUICallback mCallback; - /** Only show once automatically in the process life. */ - private boolean mHasShownHint; - /** Indicates if the keyguard is currently occluded, in which case compat UIs shouldn't - * be shown. */ + // Only show once automatically in the process life. + private boolean mHasShownSizeCompatHint; + private boolean mHasShownCameraCompatHint; + + // Indicates if the keyguard is currently occluded, in which case compat UIs shouldn't + // be shown. private boolean mKeyguardOccluded; public CompatUIController(Context context, @@ -122,23 +128,20 @@ public class CompatUIController implements OnDisplaysChangedListener, * Called when the Task info changed. Creates and updates the compat UI if there is an * activity in size compat, or removes the UI if there is no size compat activity. * - * @param displayId display the task and activity are in. - * @param taskId task the activity is in. - * @param taskConfig task config to place the compat UI with. + * @param taskInfo {@link TaskInfo} task the activity is in. * @param taskListener listener to handle the Task Surface placement. */ - public void onCompatInfoChanged(int displayId, int taskId, - @Nullable Configuration taskConfig, + public void onCompatInfoChanged(TaskInfo taskInfo, @Nullable ShellTaskOrganizer.TaskListener taskListener) { - if (taskConfig == null || taskListener == null) { + if (taskInfo.configuration == null || taskListener == null) { // Null token means the current foreground activity is not in compatibility mode. - removeLayout(taskId); - } else if (mActiveLayouts.contains(taskId)) { + removeLayout(taskInfo.taskId); + } else if (mActiveLayouts.contains(taskInfo.taskId)) { // UI already exists, update the UI layout. - updateLayout(taskId, taskConfig, taskListener); + updateLayout(taskInfo, taskListener); } else { // Create a new compat UI. - createLayout(displayId, taskId, taskConfig, taskListener); + createLayout(taskInfo, taskListener); } } @@ -215,38 +218,45 @@ public class CompatUIController implements OnDisplaysChangedListener, return mDisplaysWithIme.contains(displayId); } - private void createLayout(int displayId, int taskId, Configuration taskConfig, - ShellTaskOrganizer.TaskListener taskListener) { - final Context context = getOrCreateDisplayContext(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 " + displayId); + Log.e(TAG, "Cannot get context for display " + taskInfo.displayId); return; } final CompatUIWindowManager compatUIWindowManager = - createLayout(context, displayId, taskId, taskConfig, taskListener); - mActiveLayouts.put(taskId, compatUIWindowManager); - compatUIWindowManager.createLayout(showOnDisplay(displayId)); + createLayout(context, taskInfo, taskListener); + mActiveLayouts.put(taskInfo.taskId, compatUIWindowManager); + compatUIWindowManager.createLayout(showOnDisplay(taskInfo.displayId), + taskInfo.topActivityInSizeCompat, taskInfo.cameraCompatControlState); } @VisibleForTesting - CompatUIWindowManager createLayout(Context context, int displayId, int taskId, - Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) { + CompatUIWindowManager createLayout(Context context, TaskInfo taskInfo, + ShellTaskOrganizer.TaskListener taskListener) { final CompatUIWindowManager compatUIWindowManager = new CompatUIWindowManager(context, - taskConfig, mSyncQueue, mCallback, taskId, taskListener, - mDisplayController.getDisplayLayout(displayId), mHasShownHint); - // Only show hint for the first time. - mHasShownHint = true; + taskInfo.configuration, mSyncQueue, mCallback, taskInfo.taskId, taskListener, + mDisplayController.getDisplayLayout(taskInfo.displayId), mHasShownSizeCompatHint, + mHasShownCameraCompatHint); + // Only show hints for the first time. + if (taskInfo.topActivityInSizeCompat) { + mHasShownSizeCompatHint = true; + } + if (taskInfo.hasCameraCompatControl()) { + mHasShownCameraCompatHint = true; + } return compatUIWindowManager; } - private void updateLayout(int taskId, Configuration taskConfig, - ShellTaskOrganizer.TaskListener taskListener) { - final CompatUIWindowManager layout = mActiveLayouts.get(taskId); + private void updateLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { + final CompatUIWindowManager layout = mActiveLayouts.get(taskInfo.taskId); if (layout == null) { return; } - layout.updateCompatInfo(taskConfig, taskListener, showOnDisplay(layout.getDisplayId())); + layout.updateCompatInfo(taskInfo.configuration, taskListener, + showOnDisplay(layout.getDisplayId()), taskInfo.topActivityInSizeCompat, + taskInfo.cameraCompatControlState); } private void removeLayout(int taskId) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java index ea4f20968438..29b2baa221e7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUILayout.java @@ -16,6 +16,9 @@ package com.android.wm.shell.compatui; +import android.annotation.IdRes; +import android.app.TaskInfo; +import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.util.AttributeSet; import android.view.View; @@ -53,21 +56,59 @@ public class CompatUILayout extends LinearLayout { 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 changes like hiding / showing a hint since they affect size. - // Doing this directly in setSizeCompatHintVisibility can result in flaky animation. - mWindowManager.relayout(); + void updateCameraTreatmentButton(@CameraCompatControlState int newState) { + int buttonBkgId = newState == TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED + ? R.drawable.camera_compat_treatment_suggested_ripple + : R.drawable.camera_compat_treatment_applied_ripple; + int hintStringId = newState == TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED + ? R.string.camera_compat_treatment_suggested_button_description + : R.string.camera_compat_treatment_applied_button_description; + final ImageButton button = findViewById(R.id.camera_compat_treatment_button); + button.setImageResource(buttonBkgId); + button.setContentDescription(getResources().getString(hintStringId)); + final LinearLayout hint = findViewById(R.id.camera_compat_hint); + ((TextView) hint.findViewById(R.id.compat_mode_hint_text)).setText(hintStringId); } void setSizeCompatHintVisibility(boolean show) { - final LinearLayout sizeCompatHint = findViewById(R.id.size_compat_hint); + setViewVisibility(R.id.size_compat_hint, show); + } + + void setCameraCompatHintVisibility(boolean show) { + setViewVisibility(R.id.camera_compat_hint, show); + } + + void setRestartButtonVisibility(boolean show) { + setViewVisibility(R.id.size_compat_restart_button, show); + // Hint should never be visible without button. + if (!show) { + setSizeCompatHintVisibility(/* show= */ false); + } + } + + void setCameraControlVisibility(boolean show) { + setViewVisibility(R.id.camera_compat_control, show); + // Hint should never be visible without button. + if (!show) { + setCameraCompatHintVisibility(/* show= */ false); + } + } + + private void setViewVisibility(@IdRes int resId, boolean show) { + final View view = findViewById(resId); int visibility = show ? View.VISIBLE : View.GONE; - if (sizeCompatHint.getVisibility() == visibility) { + if (view.getVisibility() == visibility) { return; } - sizeCompatHint.setVisibility(visibility); + view.setVisibility(visibility); + } + + @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 changes like hiding / showing a hint since they affect size. + // Doing this directly in setSizeCompatHintVisibility can result in flaky animation. + mWindowManager.relayout(); } @Override @@ -85,5 +126,26 @@ public class CompatUILayout extends LinearLayout { ((TextView) sizeCompatHint.findViewById(R.id.compat_mode_hint_text)) .setText(R.string.restart_button_description); sizeCompatHint.setOnClickListener(view -> setSizeCompatHintVisibility(/* show= */ false)); + + final ImageButton cameraTreatmentButton = + findViewById(R.id.camera_compat_treatment_button); + cameraTreatmentButton.setOnClickListener( + view -> mWindowManager.onCameraTreatmentButtonClicked()); + cameraTreatmentButton.setOnLongClickListener(view -> { + mWindowManager.onCameraButtonLongClicked(); + return true; + }); + + final ImageButton cameraDismissButton = findViewById(R.id.camera_compat_dismiss_button); + cameraDismissButton.setOnClickListener( + view -> mWindowManager.onCameraDismissButtonClicked()); + cameraDismissButton.setOnLongClickListener(view -> { + mWindowManager.onCameraButtonLongClicked(); + return true; + }); + + final LinearLayout cameraCompatHint = findViewById(R.id.camera_compat_hint); + cameraCompatHint.setOnClickListener( + view -> setCameraCompatHintVisibility(/* show= */ false)); } } 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 997ad04e3b57..44526b00bf0d 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 @@ -16,6 +16,10 @@ 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.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; @@ -23,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import android.annotation.Nullable; +import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; @@ -63,8 +68,17 @@ class CompatUIWindowManager extends WindowlessWindowManager { private ShellTaskOrganizer.TaskListener mTaskListener; private DisplayLayout mDisplayLayout; + // Remember the last reported states in case visibility changes due to keyguard or + // IME updates. @VisibleForTesting - boolean mShouldShowHint; + boolean mHasSizeCompat; + @CameraCompatControlState + private int mCameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN; + + @VisibleForTesting + boolean mShouldShowSizeCompatHint; + @VisibleForTesting + boolean mShouldShowCameraCompatHint; @Nullable @VisibleForTesting @@ -78,7 +92,7 @@ class CompatUIWindowManager extends WindowlessWindowManager { CompatUIWindowManager(Context context, Configuration taskConfig, SyncTransactionQueue syncQueue, CompatUIController.CompatUICallback callback, int taskId, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, - boolean hasShownHint) { + boolean hasShownSizeCompatHint, boolean hasShownCameraCompatHint) { super(taskConfig, null /* rootSurface */, null /* hostInputToken */); mContext = context; mSyncQueue = syncQueue; @@ -88,7 +102,8 @@ class CompatUIWindowManager extends WindowlessWindowManager { mTaskId = taskId; mTaskListener = taskListener; mDisplayLayout = displayLayout; - mShouldShowHint = !hasShownHint; + mShouldShowSizeCompatHint = !hasShownSizeCompatHint; + mShouldShowCameraCompatHint = !hasShownCameraCompatHint; mStableBounds = new Rect(); mDisplayLayout.getStableBounds(mStableBounds); } @@ -113,7 +128,10 @@ class CompatUIWindowManager extends WindowlessWindowManager { } /** Creates the layout for compat controls. */ - void createLayout(boolean show) { + void createLayout(boolean show, boolean hasSizeCompat, + @CameraCompatControlState int cameraCompatControlState) { + mHasSizeCompat = hasSizeCompat; + mCameraCompatControlState = cameraCompatControlState; if (!show || mCompatUILayout != null) { // Wait until compat controls should be visible. return; @@ -122,16 +140,27 @@ class CompatUIWindowManager extends WindowlessWindowManager { initCompatUi(); updateSurfacePosition(); - mCallback.onSizeCompatRestartButtonAppeared(mTaskId); + if (hasSizeCompat) { + mCallback.onSizeCompatRestartButtonAppeared(mTaskId); + } + } + + private void createLayout(boolean show) { + createLayout(show, mHasSizeCompat, mCameraCompatControlState); } /** Called when compat info changed. */ void updateCompatInfo(Configuration taskConfig, - ShellTaskOrganizer.TaskListener taskListener, boolean show) { + ShellTaskOrganizer.TaskListener taskListener, boolean show, boolean hasSizeCompat, + @CameraCompatControlState int cameraCompatControlState) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; mTaskConfig = taskConfig; mTaskListener = taskListener; + final boolean prevHasSizeCompat = mHasSizeCompat; + final int prevCameraCompatControlState = mCameraCompatControlState; + mHasSizeCompat = hasSizeCompat; + mCameraCompatControlState = cameraCompatControlState; // Update configuration. mContext = mContext.createConfigurationContext(taskConfig); @@ -144,6 +173,11 @@ class CompatUIWindowManager extends WindowlessWindowManager { return; } + if (prevHasSizeCompat != mHasSizeCompat + || prevCameraCompatControlState != mCameraCompatControlState) { + updateVisibilityOfViews(); + } + if (!taskConfig.windowConfiguration.getBounds() .equals(prevTaskConfig.windowConfiguration.getBounds())) { // Reposition the UI surfaces. @@ -155,6 +189,7 @@ class CompatUIWindowManager extends WindowlessWindowManager { mCompatUILayout.setLayoutDirection(taskConfig.getLayoutDirection()); updateSurfacePosition(); } + } /** Called when the visibility of the UI should change. */ @@ -195,6 +230,34 @@ class CompatUIWindowManager extends WindowlessWindowManager { mCallback.onSizeCompatRestartButtonClicked(mTaskId); } + /** Called when the camera treatment button is clicked. */ + void onCameraTreatmentButtonClicked() { + if (!shouldShowCameraControl()) { + Log.w(TAG, "Camera compat shouldn't receive clicks in the hidden state."); + return; + } + // When a camera control is shown, only two states are allowed: "treament applied" and + // "treatment suggested". Clicks on the conrol's treatment button toggle between these + // two states. + mCameraCompatControlState = + mCameraCompatControlState == CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED + ? CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED + : CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + mCallback.onCameraControlStateUpdated(mTaskId, mCameraCompatControlState); + mCompatUILayout.updateCameraTreatmentButton(mCameraCompatControlState); + } + + /** Called when the camera dismiss button is clicked. */ + void onCameraDismissButtonClicked() { + if (!shouldShowCameraControl()) { + Log.w(TAG, "Camera compat shouldn't receive clicks in the hidden state."); + return; + } + mCameraCompatControlState = CAMERA_COMPAT_CONTROL_DISMISSED; + mCallback.onCameraControlStateUpdated(mTaskId, CAMERA_COMPAT_CONTROL_DISMISSED); + mCompatUILayout.setCameraControlVisibility(/* show= */ false); + } + /** Called when the restart button is long clicked. */ void onRestartButtonLongClicked() { if (mCompatUILayout == null) { @@ -203,6 +266,14 @@ class CompatUIWindowManager extends WindowlessWindowManager { mCompatUILayout.setSizeCompatHintVisibility(/* show= */ true); } + /** Called when either dismiss or treatment camera buttons is long clicked. */ + void onCameraButtonLongClicked() { + if (mCompatUILayout == null) { + return; + } + mCompatUILayout.setCameraCompatHintVisibility(/* show= */ true); + } + int getDisplayId() { return mDisplayId; } @@ -213,6 +284,8 @@ class CompatUIWindowManager extends WindowlessWindowManager { /** Releases the surface control and tears down the view hierarchy. */ void release() { + // Hiding before releasing to avoid flickering when transitioning to the Home screen. + mCompatUILayout.setVisibility(View.GONE); mCompatUILayout = null; if (mViewHost != null) { @@ -283,12 +356,35 @@ class CompatUIWindowManager extends WindowlessWindowManager { mCompatUILayout = inflateCompatUILayout(); mCompatUILayout.inject(this); - mCompatUILayout.setSizeCompatHintVisibility(mShouldShowHint); + updateVisibilityOfViews(); mViewHost.setView(mCompatUILayout, getWindowLayoutParams()); + } + + private void updateVisibilityOfViews() { + // Size Compat mode restart button. + mCompatUILayout.setRestartButtonVisibility(mHasSizeCompat); + if (mHasSizeCompat && mShouldShowSizeCompatHint) { + mCompatUILayout.setSizeCompatHintVisibility(/* show= */ true); + // Only show by default for the first time. + mShouldShowSizeCompatHint = false; + } + + // Camera control for stretched issues. + mCompatUILayout.setCameraControlVisibility(shouldShowCameraControl()); + if (shouldShowCameraControl() && mShouldShowCameraCompatHint) { + mCompatUILayout.setCameraCompatHintVisibility(/* show= */ true); + // Only show by default for the first time. + mShouldShowCameraCompatHint = false; + } + if (shouldShowCameraControl()) { + mCompatUILayout.updateCameraTreatmentButton(mCameraCompatControlState); + } + } - // Only show by default for the first time. - mShouldShowHint = false; + private boolean shouldShowCameraControl() { + return mCameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN + && mCameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED; } @VisibleForTesting diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index a3b98a8fc880..825320b4e784 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; +import android.app.TaskInfo; import android.content.Context; import android.content.LocusId; import android.content.pm.ParceledListSlice; @@ -334,8 +335,7 @@ public class ShellTaskOrganizerTests { mOrganizer.onTaskAppeared(taskInfo1, null); // sizeCompatActivity is null if top activity is not in size compat. - verify(mCompatUI).onCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId, - null /* taskConfig */, null /* taskListener */); + verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */); // sizeCompatActivity is non-null if top activity is in size compat. clearInvocations(mCompatUI); @@ -345,8 +345,7 @@ public class ShellTaskOrganizerTests { taskInfo2.topActivityInSizeCompat = true; taskInfo2.isVisible = true; mOrganizer.onTaskInfoChanged(taskInfo2); - verify(mCompatUI).onCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId, - taskInfo1.configuration, taskListener); + verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener); // Not show size compat UI if task is not visible. clearInvocations(mCompatUI); @@ -356,13 +355,82 @@ public class ShellTaskOrganizerTests { taskInfo3.topActivityInSizeCompat = true; taskInfo3.isVisible = false; mOrganizer.onTaskInfoChanged(taskInfo3); - verify(mCompatUI).onCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId, - null /* taskConfig */, null /* taskListener */); + verify(mCompatUI).onCompatInfoChanged(taskInfo3, null /* taskListener */); clearInvocations(mCompatUI); mOrganizer.onTaskVanished(taskInfo1); - verify(mCompatUI).onCompatInfoChanged(taskInfo1.displayId, taskInfo1.taskId, - null /* taskConfig */, null /* taskListener */); + verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */); + } + + @Test + public void testOnCameraCompatActivityChanged() { + final RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN); + taskInfo1.displayId = DEFAULT_DISPLAY; + taskInfo1.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; + final TrackingTaskListener taskListener = new TrackingTaskListener(); + mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN); + mOrganizer.onTaskAppeared(taskInfo1, null); + + // Task listener sent to compat UI is null if top activity doesn't request a camera + // compat control. + verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */); + + // Task linster is non-null when request a camera compat control for a visible task. + clearInvocations(mCompatUI); + final RunningTaskInfo taskInfo2 = + createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); + taskInfo2.displayId = taskInfo1.displayId; + taskInfo2.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + taskInfo2.isVisible = true; + mOrganizer.onTaskInfoChanged(taskInfo2); + verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener); + + // CompatUIController#onCompatInfoChanged is called when requested state for a camera + // compat control changes for a visible task. + clearInvocations(mCompatUI); + final RunningTaskInfo taskInfo3 = + createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); + taskInfo3.displayId = taskInfo1.displayId; + taskInfo3.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; + taskInfo3.isVisible = true; + mOrganizer.onTaskInfoChanged(taskInfo3); + verify(mCompatUI).onCompatInfoChanged(taskInfo3, taskListener); + + // CompatUIController#onCompatInfoChanged is called when a top activity goes in size compat + // mode for a visible task that has a compat control. + clearInvocations(mCompatUI); + final RunningTaskInfo taskInfo4 = + createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); + taskInfo4.displayId = taskInfo1.displayId; + taskInfo4.topActivityInSizeCompat = true; + taskInfo4.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; + taskInfo4.isVisible = true; + mOrganizer.onTaskInfoChanged(taskInfo4); + verify(mCompatUI).onCompatInfoChanged(taskInfo4, taskListener); + + // Task linster is null when a camera compat control is dimissed for a visible task. + clearInvocations(mCompatUI); + final RunningTaskInfo taskInfo5 = + createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); + taskInfo5.displayId = taskInfo1.displayId; + taskInfo5.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_DISMISSED; + taskInfo5.isVisible = true; + mOrganizer.onTaskInfoChanged(taskInfo5); + verify(mCompatUI).onCompatInfoChanged(taskInfo5, null /* taskListener */); + + // Task linster is null when request a camera compat control for a invisible task. + clearInvocations(mCompatUI); + final RunningTaskInfo taskInfo6 = + createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode()); + taskInfo6.displayId = taskInfo1.displayId; + taskInfo6.cameraCompatControlState = TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; + taskInfo6.isVisible = false; + mOrganizer.onTaskInfoChanged(taskInfo6); + verify(mCompatUI).onCompatInfoChanged(taskInfo6, null /* taskListener */); + + clearInvocations(mCompatUI); + mOrganizer.onTaskVanished(taskInfo1); + verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */); } @Test 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 f622edb7f134..4352fd3d2c27 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,6 +16,10 @@ 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; @@ -29,6 +33,9 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.app.ActivityManager.RunningTaskInfo; +import android.app.TaskInfo; +import android.app.TaskInfo.CameraCompatControlState; import android.content.Context; import android.content.res.Configuration; import android.testing.AndroidTestingRunner; @@ -90,8 +97,8 @@ public class CompatUIControllerTest extends ShellTestCase { mController = new CompatUIController(mContext, mMockDisplayController, mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) { @Override - CompatUIWindowManager createLayout(Context context, int displayId, int taskId, - Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) { + CompatUIWindowManager createLayout(Context context, TaskInfo taskInfo, + ShellTaskOrganizer.TaskListener taskListener) { return mMockLayout; } }; @@ -106,23 +113,59 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testOnCompatInfoChanged() { - final Configuration taskConfig = new Configuration(); + TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); // Verify that the restart button is added with non-null size compat info. - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(taskInfo, mMockTaskListener); - verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig), - eq(mMockTaskListener)); + verify(mController).createLayout(any(), eq(taskInfo), eq(mMockTaskListener)); // Verify that the restart button is updated with non-null new size compat info. - final Configuration newTaskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), + mMockTaskListener); + + verify(mMockLayout).updateCompatInfo(new Configuration(), mMockTaskListener, + true /* show */, true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); + + // Verify that the restart button is updated with new camera state. + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED), + mMockTaskListener); + + verify(mMockLayout).updateCompatInfo(new Configuration(), mMockTaskListener, + true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED), + mMockTaskListener); + + verify(mMockLayout).updateCompatInfo(new Configuration(), mMockTaskListener, + true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + // 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).updateCompatInfo(taskConfig, mMockTaskListener, - true /* show */); + verify(mMockLayout).release(); + + clearInvocations(mMockLayout); + clearInvocations(mController); + // Verify that compat controls are removed with 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)); - // Verify that the restart button is removed with null size compat info. - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + false /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_DISMISSED), + null /* taskListener */); verify(mMockLayout).release(); } @@ -139,8 +182,8 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testOnDisplayRemoved() { mController.onDisplayAdded(DISPLAY_ID); - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onDisplayRemoved(DISPLAY_ID + 1); @@ -157,16 +200,14 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testOnDisplayConfigurationChanged() { - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, - mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); - final Configuration newTaskConfig = new Configuration(); - mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, newTaskConfig); + mController.onDisplayConfigurationChanged(DISPLAY_ID + 1, new Configuration()); verify(mMockLayout, never()).updateDisplayLayout(any()); - mController.onDisplayConfigurationChanged(DISPLAY_ID, newTaskConfig); + mController.onDisplayConfigurationChanged(DISPLAY_ID, new Configuration()); verify(mMockLayout).updateDisplayLayout(mMockDisplayLayout); } @@ -174,9 +215,8 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testInsetsChanged() { mController.onDisplayAdded(DISPLAY_ID); - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, - mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); InsetsState insetsState = new InsetsState(); InsetsSource insetsSource = new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR); insetsSource.setFrame(0, 0, 1000, 1000); @@ -196,8 +236,8 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnImeShowHide() { - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); // Verify that the restart button is hidden after IME is showing. mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); @@ -205,10 +245,11 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while IME is showing. - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); - verify(mMockLayout).updateCompatInfo(taskConfig, mMockTaskListener, - false /* show */); + verify(mMockLayout).updateCompatInfo(new Configuration(), mMockTaskListener, + false /* show */, true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); // Verify button is shown after IME is hidden. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); @@ -218,8 +259,8 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnKeyguardOccludedChanged() { - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); // Verify that the restart button is hidden after keyguard becomes occluded. mController.onKeyguardOccludedChanged(true); @@ -227,10 +268,11 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while keyguard is occluded. - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); - verify(mMockLayout).updateCompatInfo(taskConfig, mMockTaskListener, - false /* show */); + verify(mMockLayout).updateCompatInfo(new Configuration(), mMockTaskListener, + false /* show */, true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); // Verify button is shown after keyguard becomes not occluded. mController.onKeyguardOccludedChanged(false); @@ -240,8 +282,8 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testButtonRemainsHiddenOnKeyguardOccludedFalseWhenImeIsShowing() { - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); mController.onKeyguardOccludedChanged(true); @@ -263,8 +305,8 @@ public class CompatUIControllerTest extends ShellTestCase { @Test public void testButtonRemainsHiddenOnImeHideWhenKeyguardIsOccluded() { - final Configuration taskConfig = new Configuration(); - mController.onCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); + mController.onCompatInfoChanged(createTaskInfo(DISPLAY_ID, TASK_ID, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN), mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); mController.onKeyguardOccludedChanged(true); @@ -283,4 +325,14 @@ public class CompatUIControllerTest extends ShellTestCase { verify(mMockLayout).updateVisibility(true); } + + private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat, + @CameraCompatControlState int cameraCompatControlState) { + RunningTaskInfo taskInfo = new RunningTaskInfo(); + taskInfo.taskId = taskId; + taskInfo.displayId = displayId; + taskInfo.topActivityInSizeCompat = hasSizeCompat; + taskInfo.cameraCompatControlState = cameraCompatControlState; + return taskInfo; + } } 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 2c3987bc358d..353d8fe8bc52 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 @@ -16,6 +16,11 @@ 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 com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.mockito.Mockito.doNothing; @@ -69,7 +74,7 @@ public class CompatUILayoutTest extends ShellTestCase { mWindowManager = new CompatUIWindowManager(mContext, new Configuration(), mSyncTransactionQueue, mCallback, TASK_ID, mTaskListener, new DisplayLayout(), - false /* hasShownHint */); + false /* hasShownSizeCompatHint */, false /* hasShownCameraCompatHint */); mCompatUILayout = (CompatUILayout) LayoutInflater.from(mContext).inflate(R.layout.compat_ui_layout, null); @@ -78,6 +83,7 @@ public class CompatUILayoutTest extends ShellTestCase { spyOn(mWindowManager); spyOn(mCompatUILayout); doReturn(mViewHost).when(mWindowManager).createSurfaceViewHost(); + doReturn(mCompatUILayout).when(mWindowManager).inflateCompatUILayout(); } @Test @@ -86,7 +92,6 @@ public class CompatUILayoutTest extends ShellTestCase { button.performClick(); verify(mWindowManager).onRestartButtonClicked(); - doReturn(mCompatUILayout).when(mWindowManager).inflateCompatUILayout(); verify(mCallback).onSizeCompatRestartButtonClicked(TASK_ID); } @@ -102,10 +107,92 @@ public class CompatUILayoutTest extends ShellTestCase { @Test public void testOnClickForSizeCompatHint() { - mWindowManager.createLayout(true /* show */); + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); final LinearLayout sizeCompatHint = mCompatUILayout.findViewById(R.id.size_compat_hint); sizeCompatHint.performClick(); verify(mCompatUILayout).setSizeCompatHintVisibility(/* show= */ false); } + + @Test + public void testUpdateCameraTreatmentButton_treatmentAppliedByDefault() { + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + final ImageButton button = + mCompatUILayout.findViewById(R.id.camera_compat_treatment_button); + button.performClick(); + + verify(mWindowManager).onCameraTreatmentButtonClicked(); + verify(mCallback).onCameraControlStateUpdated( + TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + button.performClick(); + + verify(mCallback).onCameraControlStateUpdated( + TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + } + + @Test + public void testUpdateCameraTreatmentButton_treatmentSuggestedByDefault() { + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + final ImageButton button = + mCompatUILayout.findViewById(R.id.camera_compat_treatment_button); + button.performClick(); + + verify(mWindowManager).onCameraTreatmentButtonClicked(); + verify(mCallback).onCameraControlStateUpdated( + TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + + button.performClick(); + + verify(mCallback).onCameraControlStateUpdated( + TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + } + + @Test + public void testOnCameraDismissButtonClicked() { + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + final ImageButton button = + mCompatUILayout.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); + } + + @Test + public void testOnLongClickForCameraTreatementButton() { + doNothing().when(mWindowManager).onCameraButtonLongClicked(); + + final ImageButton button = + mCompatUILayout.findViewById(R.id.camera_compat_treatment_button); + button.performLongClick(); + + verify(mWindowManager).onCameraButtonLongClicked(); + } + + @Test + public void testOnLongClickForCameraDismissButton() { + doNothing().when(mWindowManager).onCameraButtonLongClicked(); + + final ImageButton button = mCompatUILayout.findViewById(R.id.camera_compat_dismiss_button); + button.performLongClick(); + + verify(mWindowManager).onCameraButtonLongClicked(); + } + + @Test + public void testOnClickForCameraCompatHint() { + mWindowManager.createLayout(true /* show */, false /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + final LinearLayout hint = mCompatUILayout.findViewById(R.id.camera_compat_hint); + hint.performClick(); + + verify(mCompatUILayout).setCameraCompatHintVisibility(/* show= */ false); + } } 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 d5dcf2e11a46..11c797363819 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 @@ -16,6 +16,10 @@ 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; @@ -23,6 +27,7 @@ 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.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -81,7 +86,7 @@ public class CompatUIWindowManagerTest extends ShellTestCase { mWindowManager = new CompatUIWindowManager(mContext, new Configuration(), mSyncTransactionQueue, mCallback, TASK_ID, mTaskListener, new DisplayLayout(), - false /* hasShownHint */); + false /* hasShownSizeCompatHint */, false /* hasShownSizeCompatHint */); spyOn(mWindowManager); doReturn(mCompatUILayout).when(mWindowManager).inflateCompatUILayout(); @@ -91,31 +96,35 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test public void testCreateSizeCompatButton() { // Not create layout if show is false. - mWindowManager.createLayout(false /* show */); + mWindowManager.createLayout(false /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager, never()).inflateCompatUILayout(); // Not create hint popup. - mWindowManager.mShouldShowHint = false; - mWindowManager.createLayout(true /* show */); + mWindowManager.mShouldShowSizeCompatHint = false; + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager).inflateCompatUILayout(); - verify(mCompatUILayout).setSizeCompatHintVisibility(false /* show */); + verify(mCompatUILayout, never()).setSizeCompatHintVisibility(true /* show */); // Create hint popup. mWindowManager.release(); - mWindowManager.mShouldShowHint = true; - mWindowManager.createLayout(true /* show */); + mWindowManager.mShouldShowSizeCompatHint = true; + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager, times(2)).inflateCompatUILayout(); assertNotNull(mCompatUILayout); verify(mCompatUILayout).setSizeCompatHintVisibility(true /* show */); - assertFalse(mWindowManager.mShouldShowHint); + assertFalse(mWindowManager.mShouldShowSizeCompatHint); } @Test public void testRelease() { - mWindowManager.createLayout(true /* show */); + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager).inflateCompatUILayout(); @@ -126,32 +135,60 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test public void testUpdateCompatInfo() { - mWindowManager.createLayout(true /* show */); + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); // No diff clearInvocations(mWindowManager); - mWindowManager.updateCompatInfo(mTaskConfig, mTaskListener, true /* show */); + mWindowManager.updateCompatInfo(mTaskConfig, mTaskListener, true /* show */, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager, never()).updateSurfacePosition(); verify(mWindowManager, never()).release(); - verify(mWindowManager, never()).createLayout(anyBoolean()); + verify(mWindowManager, never()).createLayout(anyBoolean(), anyBoolean(), anyInt()); // Change task listener, recreate button. clearInvocations(mWindowManager); final ShellTaskOrganizer.TaskListener newTaskListener = mock( ShellTaskOrganizer.TaskListener.class); mWindowManager.updateCompatInfo(mTaskConfig, newTaskListener, - true /* show */); + true /* show */, true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager).release(); - verify(mWindowManager).createLayout(anyBoolean()); + verify(mWindowManager).createLayout(anyBoolean(), anyBoolean(), anyInt()); + + // Change Camera Compat state, show a control. + mWindowManager.updateCompatInfo(mTaskConfig, newTaskListener, true /* show */, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + + verify(mCompatUILayout).setCameraControlVisibility(/* show */ true); + verify(mCompatUILayout).updateCameraTreatmentButton( + CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + + clearInvocations(mWindowManager); + clearInvocations(mCompatUILayout); + // Change Camera Compat state, update a control. + mWindowManager.updateCompatInfo(mTaskConfig, newTaskListener, true /* show */, + true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + verify(mCompatUILayout).setCameraControlVisibility(/* show */ true); + verify(mCompatUILayout).updateCameraTreatmentButton( + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + clearInvocations(mWindowManager); + clearInvocations(mCompatUILayout); + // Change Camera Compat state to hidden, hide a control. + mWindowManager.updateCompatInfo(mTaskConfig, newTaskListener, + true /* show */, true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); + + verify(mCompatUILayout).setCameraControlVisibility(/* show */ false); // Change task bounds, update position. clearInvocations(mWindowManager); final Configuration newTaskConfiguration = new Configuration(); newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000)); mWindowManager.updateCompatInfo(newTaskConfiguration, newTaskListener, - true /* show */); + true /* show */, true /* hasSizeCompat */, CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager).updateSurfacePosition(); } @@ -201,23 +238,25 @@ public class CompatUIWindowManagerTest extends ShellTestCase { public void testUpdateVisibility() { // Create button if it is not created. mWindowManager.mCompatUILayout = null; + mWindowManager.mHasSizeCompat = true; mWindowManager.updateVisibility(true /* show */); - verify(mWindowManager).createLayout(true /* show */); + verify(mWindowManager).createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); // Hide button. clearInvocations(mWindowManager); doReturn(View.VISIBLE).when(mCompatUILayout).getVisibility(); mWindowManager.updateVisibility(false /* show */); - verify(mWindowManager, never()).createLayout(anyBoolean()); + verify(mWindowManager, never()).createLayout(anyBoolean(), anyBoolean(), anyInt()); verify(mCompatUILayout).setVisibility(View.GONE); // Show button. doReturn(View.GONE).when(mCompatUILayout).getVisibility(); mWindowManager.updateVisibility(true /* show */); - verify(mWindowManager, never()).createLayout(anyBoolean()); + verify(mWindowManager, never()).createLayout(anyBoolean(), anyBoolean(), anyInt()); verify(mCompatUILayout).setVisibility(View.VISIBLE); } @@ -230,6 +269,37 @@ public class CompatUIWindowManagerTest extends ShellTestCase { } @Test + public void testOnCameraDismissButtonClicked() { + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + clearInvocations(mCompatUILayout); + mWindowManager.onCameraDismissButtonClicked(); + + verify(mCallback).onCameraControlStateUpdated(TASK_ID, CAMERA_COMPAT_CONTROL_DISMISSED); + verify(mCompatUILayout).setCameraControlVisibility(/* show= */ false); + } + + @Test + public void testOnCameraTreatmentButtonClicked() { + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + clearInvocations(mCompatUILayout); + mWindowManager.onCameraTreatmentButtonClicked(); + + verify(mCallback).onCameraControlStateUpdated( + TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + verify(mCompatUILayout).updateCameraTreatmentButton( + CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED); + + mWindowManager.onCameraTreatmentButtonClicked(); + + verify(mCallback).onCameraControlStateUpdated( + TASK_ID, CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + verify(mCompatUILayout).updateCameraTreatmentButton( + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + } + + @Test public void testOnRestartButtonClicked() { mWindowManager.onRestartButtonClicked(); @@ -239,15 +309,60 @@ public class CompatUIWindowManagerTest extends ShellTestCase { @Test public void testOnRestartButtonLongClicked_showHint() { // Not create hint popup. - mWindowManager.mShouldShowHint = false; - mWindowManager.createLayout(true /* show */); + mWindowManager.mShouldShowSizeCompatHint = false; + mWindowManager.createLayout(true /* show */, true /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_HIDDEN); verify(mWindowManager).inflateCompatUILayout(); - verify(mCompatUILayout).setSizeCompatHintVisibility(false /* show */); + verify(mCompatUILayout, never()).setSizeCompatHintVisibility(true /* show */); mWindowManager.onRestartButtonLongClicked(); verify(mCompatUILayout).setSizeCompatHintVisibility(true /* show */); } + @Test + public void testOnCamerControlLongClicked_showHint() { + // Not create hint popup. + mWindowManager.mShouldShowCameraCompatHint = false; + mWindowManager.createLayout(true /* show */, false /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + verify(mWindowManager).inflateCompatUILayout(); + verify(mCompatUILayout, never()).setCameraCompatHintVisibility(true /* show */); + + mWindowManager.onCameraButtonLongClicked(); + + verify(mCompatUILayout).setCameraCompatHintVisibility(true /* show */); + } + + @Test + public void testCreateCameraCompatControl() { + // Not create layout if show is false. + mWindowManager.createLayout(false /* show */, false /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + verify(mWindowManager, never()).inflateCompatUILayout(); + + // Not create hint popup. + mWindowManager.mShouldShowCameraCompatHint = false; + mWindowManager.createLayout(true /* show */, false /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + verify(mWindowManager).inflateCompatUILayout(); + verify(mCompatUILayout, never()).setCameraCompatHintVisibility(true /* show */); + verify(mCompatUILayout).setCameraControlVisibility(true /* show */); + + // Create hint popup. + mWindowManager.release(); + mWindowManager.mShouldShowCameraCompatHint = true; + mWindowManager.createLayout(true /* show */, false /* hasSizeCompat */, + CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED); + + verify(mWindowManager, times(2)).inflateCompatUILayout(); + assertNotNull(mCompatUILayout); + verify(mCompatUILayout, times(2)).setCameraControlVisibility(true /* show */); + assertFalse(mWindowManager.mShouldShowCameraCompatHint); + } + } |