summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/Android.bp2
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml145
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_app_info_pill.xml58
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_more_actions_pill.xml47
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_windowing_pill.xml63
-rw-r--r--libs/WindowManager/Shell/res/values-eu/strings.xml4
-rw-r--r--libs/WindowManager/Shell/res/values-sq/strings.xml2
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java72
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/PipModule.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/performance/PerfHintController.kt56
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java (renamed from libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipTransition.java)62
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java270
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java23
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt3
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt64
-rw-r--r--libs/WindowManager/Shell/tests/unittest/Android.bp2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java33
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenConstantsTest.kt59
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java111
-rw-r--r--libs/dream/lowlight/tests/Android.bp2
-rw-r--r--libs/hwui/OWNERS3
-rw-r--r--libs/hwui/jni/Shader.cpp57
-rw-r--r--libs/securebox/tests/Android.bp2
51 files changed, 989 insertions, 523 deletions
diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
index b6e743a2b7e1..ed2ff2de245b 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/Android.bp
+++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
@@ -37,7 +37,7 @@ android_test {
"androidx.test.rules",
"androidx.test.ext.junit",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
"testables",
"platform-test-annotations",
],
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
new file mode 100644
index 000000000000..ee9f070f6765
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="@dimen/desktop_mode_handle_menu_width"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/desktop_mode_handle_menu_app_info_pill_height"
+ android:layout_marginTop="@dimen/desktop_mode_handle_menu_margin_top"
+ android:layout_marginStart="1dp"
+ android:elevation="1dp"
+ android:orientation="horizontal"
+ android:background="@drawable/desktop_mode_decor_handle_menu_background"
+ android:gravity="center_vertical">
+
+ <ImageView
+ android:id="@+id/application_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginStart="14dp"
+ android:layout_marginEnd="14dp"
+ android:contentDescription="@string/app_icon_text"/>
+
+ <TextView
+ android:id="@+id/application_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ tools:text="Gmail"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
+ android:textSize="14sp"
+ android:textFontWeight="500"
+ android:lineHeight="20dp"
+ android:textStyle="normal"
+ android:layout_weight="1"/>
+
+ <ImageButton
+ android:id="@+id/collapse_menu_button"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:padding="4dp"
+ android:layout_marginEnd="14dp"
+ android:layout_marginStart="14dp"
+ android:contentDescription="@string/collapse_menu_text"
+ android:src="@drawable/ic_baseline_expand_more_24"
+ android:rotation="180"
+ android:tint="?androidprv:attr/materialColorOnSurface"
+ android:background="?android:selectableItemBackgroundBorderless"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/desktop_mode_handle_menu_windowing_pill_height"
+ android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin"
+ android:layout_marginStart="1dp"
+ android:orientation="horizontal"
+ android:elevation="1dp"
+ android:background="@drawable/desktop_mode_decor_handle_menu_background"
+ android:gravity="center_vertical">
+
+ <ImageButton
+ android:id="@+id/fullscreen_button"
+ android:layout_marginEnd="4dp"
+ android:contentDescription="@string/fullscreen_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_fullscreen"
+ android:tint="?androidprv:attr/materialColorOnSurface"
+ android:layout_weight="1"
+ style="@style/DesktopModeHandleMenuWindowingButton"/>
+
+ <ImageButton
+ android:id="@+id/split_screen_button"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:contentDescription="@string/split_screen_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_splitscreen"
+ android:tint="?androidprv:attr/materialColorOnSurface"
+ android:layout_weight="1"
+ style="@style/DesktopModeHandleMenuWindowingButton"/>
+
+ <ImageButton
+ android:id="@+id/floating_button"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:contentDescription="@string/float_button_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_floating"
+ android:tint="?androidprv:attr/materialColorOnSurface"
+ android:layout_weight="1"
+ style="@style/DesktopModeHandleMenuWindowingButton"/>
+
+ <ImageButton
+ android:id="@+id/desktop_button"
+ android:layout_marginStart="4dp"
+ android:contentDescription="@string/desktop_text"
+ android:src="@drawable/desktop_mode_ic_handle_menu_desktop"
+ android:tint="?androidprv:attr/materialColorOnSurface"
+ android:layout_weight="1"
+ style="@style/DesktopModeHandleMenuWindowingButton"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/desktop_mode_handle_menu_more_actions_pill_height"
+ android:layout_marginTop="@dimen/desktop_mode_handle_menu_pill_spacing_margin"
+ android:layout_marginStart="1dp"
+ android:orientation="vertical"
+ android:elevation="1dp"
+ android:background="@drawable/desktop_mode_decor_handle_menu_background">
+
+ <Button
+ android:id="@+id/screenshot_button"
+ android:contentDescription="@string/screenshot_text"
+ android:text="@string/screenshot_text"
+ android:drawableStart="@drawable/desktop_mode_ic_handle_menu_screenshot"
+ android:drawableTint="?androidprv:attr/materialColorOnSurface"
+ style="@style/DesktopModeHandleMenuActionButton"/>
+
+ <Button
+ android:id="@+id/select_button"
+ android:contentDescription="@string/select_text"
+ android:text="@string/select_text"
+ android:drawableStart="@drawable/desktop_mode_ic_handle_menu_select"
+ android:drawableTint="?androidprv:attr/materialColorOnSurface"
+ style="@style/DesktopModeHandleMenuActionButton"/>
+
+ </LinearLayout>
+</LinearLayout>
+
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_app_info_pill.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_app_info_pill.xml
deleted file mode 100644
index c2ee3066d059..000000000000
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_app_info_pill.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="@dimen/desktop_mode_handle_menu_width"
- android:layout_height="@dimen/desktop_mode_handle_menu_app_info_pill_height"
- android:orientation="horizontal"
- android:background="@drawable/desktop_mode_decor_handle_menu_background"
- android:gravity="center_vertical">
-
- <ImageView
- android:id="@+id/application_icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_marginStart="14dp"
- android:layout_marginEnd="14dp"
- android:contentDescription="@string/app_icon_text"/>
-
- <TextView
- android:id="@+id/application_name"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- tools:text="Gmail"
- android:textColor="?androidprv:attr/materialColorOnSurface"
- android:textSize="14sp"
- android:textFontWeight="500"
- android:lineHeight="20dp"
- android:textStyle="normal"
- android:layout_weight="1"/>
-
- <ImageButton
- android:id="@+id/collapse_menu_button"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:padding="4dp"
- android:layout_marginEnd="14dp"
- android:layout_marginStart="14dp"
- android:contentDescription="@string/collapse_menu_text"
- android:src="@drawable/ic_baseline_expand_more_24"
- android:rotation="180"
- android:tint="?androidprv:attr/materialColorOnSurface"
- android:background="?android:selectableItemBackgroundBorderless"/>
-</LinearLayout> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_more_actions_pill.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_more_actions_pill.xml
deleted file mode 100644
index e637671937bd..000000000000
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_more_actions_pill.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:layout_width="@dimen/desktop_mode_handle_menu_width"
- android:layout_height="@dimen/desktop_mode_handle_menu_more_actions_pill_height"
- android:orientation="vertical"
- android:background="@drawable/desktop_mode_decor_handle_menu_background">
-
- <Button
- android:id="@+id/screenshot_button"
- android:contentDescription="@string/screenshot_text"
- android:text="@string/screenshot_text"
- android:drawableStart="@drawable/desktop_mode_ic_handle_menu_screenshot"
- android:drawableTint="?androidprv:attr/materialColorOnSurface"
- style="@style/DesktopModeHandleMenuActionButton"/>
-
- <Button
- android:id="@+id/select_button"
- android:contentDescription="@string/select_text"
- android:text="@string/select_text"
- android:drawableStart="@drawable/desktop_mode_ic_handle_menu_select"
- android:drawableTint="?androidprv:attr/materialColorOnSurface"
- style="@style/DesktopModeHandleMenuActionButton"/>
- <Button
- android:id="@+id/close_button"
- android:contentDescription="@string/close_text"
- android:text="@string/close_text"
- android:drawableStart="@drawable/desktop_mode_ic_handle_menu_close"
- android:drawableTint="?androidprv:attr/materialColorOnSurface"
- style="@style/DesktopModeHandleMenuActionButton"/>
-
-</LinearLayout> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_windowing_pill.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_windowing_pill.xml
deleted file mode 100644
index c4b688daeb6e..000000000000
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu_windowing_pill.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:layout_width="@dimen/desktop_mode_handle_menu_width"
- android:layout_height="@dimen/desktop_mode_handle_menu_windowing_pill_height"
- android:orientation="horizontal"
- android:background="@drawable/desktop_mode_decor_handle_menu_background"
- android:gravity="center_vertical">
-
- <ImageButton
- android:id="@+id/fullscreen_button"
- android:layout_marginEnd="4dp"
- android:contentDescription="@string/fullscreen_text"
- android:src="@drawable/desktop_mode_ic_handle_menu_fullscreen"
- android:tint="?androidprv:attr/materialColorOnSurface"
- android:layout_weight="1"
- style="@style/DesktopModeHandleMenuWindowingButton"/>
-
- <ImageButton
- android:id="@+id/split_screen_button"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:contentDescription="@string/split_screen_text"
- android:src="@drawable/desktop_mode_ic_handle_menu_splitscreen"
- android:tint="?androidprv:attr/materialColorOnSurface"
- android:layout_weight="1"
- style="@style/DesktopModeHandleMenuWindowingButton"/>
-
- <ImageButton
- android:id="@+id/floating_button"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:contentDescription="@string/float_button_text"
- android:src="@drawable/desktop_mode_ic_handle_menu_floating"
- android:tint="?androidprv:attr/materialColorOnSurface"
- android:layout_weight="1"
- style="@style/DesktopModeHandleMenuWindowingButton"/>
-
- <ImageButton
- android:id="@+id/desktop_button"
- android:layout_marginStart="4dp"
- android:contentDescription="@string/desktop_text"
- android:src="@drawable/desktop_mode_ic_handle_menu_desktop"
- android:tint="?androidprv:attr/materialColorOnSurface"
- android:layout_weight="1"
- style="@style/DesktopModeHandleMenuWindowingButton"/>
-
-</LinearLayout> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index fae83883b7c4..1dbc57b73f6c 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -36,7 +36,7 @@
<string name="dock_non_resizeble_failed_to_dock_text" msgid="2733543750291266047">"Aplikazioak ez du onartzen pantaila zatitua"</string>
<string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Leiho bakar batean ireki daiteke aplikazioa."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Baliteke aplikazioak ez funtzionatzea bigarren mailako pantailetan."</string>
- <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikazioa ezin da abiarazi bigarren mailako pantailatan."</string>
+ <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikazioa ezin da exekutatu bigarren mailako pantailatan."</string>
<string name="accessibility_divider" msgid="6407584574218956849">"Pantaila-zatitzailea"</string>
<string name="divider_title" msgid="1963391955593749442">"Pantaila-zatitzailea"</string>
<string name="accessibility_action_divider_left_full" msgid="1792313656305328536">"Ezarri ezkerraldea pantaila osoan"</string>
@@ -110,7 +110,7 @@
<string name="app_icon_text" msgid="2823268023931811747">"Aplikazioaren ikonoa"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string>
- <string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitua"</string>
+ <string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitzea"</string>
<string name="more_button_text" msgid="3655388105592893530">"Gehiago"</string>
<string name="float_button_text" msgid="9221657008391364581">"Leiho gainerakorra"</string>
<string name="select_text" msgid="5139083974039906583">"Hautatu"</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index e155c72bf297..afccac292ebe 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -97,7 +97,7 @@
<string name="letterbox_education_got_it" msgid="4057634570866051177">"E kuptova"</string>
<string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Zgjeroje për më shumë informacion."</string>
<string name="letterbox_restart_dialog_title" msgid="8543049527871033505">"Rinis për një pamje më të mirë?"</string>
- <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Mund të rinisësh aplikacionin në mënyrë që të duket më mirë në ekranin tënd, por mund të humbësh progresin ose çdo ndryshim të paruajtur"</string>
+ <string name="letterbox_restart_dialog_description" msgid="6096946078246557848">"Mund ta rinisësh aplikacionin në mënyrë që të duket më mirë në ekranin tënd, por mund ta humbasësh progresin ose çdo ndryshim të paruajtur"</string>
<string name="letterbox_restart_cancel" msgid="1342209132692537805">"Anulo"</string>
<string name="letterbox_restart_restart" msgid="8529976234412442973">"Rinis"</string>
<string name="letterbox_restart_dialog_checkbox_title" msgid="5252918008140768386">"Mos e shfaq përsëri"</string>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 705e38731a0c..1f6f7aeadd45 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -143,7 +143,9 @@
<dimen name="bubble_expanded_view_padding">16dp</dimen>
<!-- Padding for the edge of the expanded view that is closest to the edge of the screen used
when displaying in landscape on a large screen. -->
- <dimen name="bubble_expanded_view_largescreen_landscape_padding">128dp</dimen>
+ <dimen name="bubble_expanded_view_largescreen_landscape_padding">102dp</dimen>
+ <!-- The width of the expanded view on large screens. -->
+ <dimen name="bubble_expanded_view_largescreen_width">540dp</dimen>
<!-- This should be at least the size of bubble_expanded_view_padding; it is used to include
a slight touch slop around the expanded view. -->
<dimen name="bubble_expanded_view_slop">8dp</dimen>
@@ -434,11 +436,11 @@
<!-- The height of the handle menu's "Windowing" pill in desktop mode. -->
<dimen name="desktop_mode_handle_menu_windowing_pill_height">52dp</dimen>
- <!-- The height of the handle menu's "More Actions" pill in desktop mode, but not freeform. -->
- <dimen name="desktop_mode_handle_menu_more_actions_pill_height">104dp</dimen>
+ <!-- The height of the handle menu's "More Actions" pill in desktop mode. -->
+ <dimen name="desktop_mode_handle_menu_more_actions_pill_height">52dp</dimen>
- <!-- The height of the handle menu's "More Actions" pill in freeform desktop windowing mode. -->
- <dimen name="desktop_mode_handle_menu_more_actions_pill_freeform_height">52dp</dimen>
+ <!-- The height of the handle menu in desktop mode. -->
+ <dimen name="desktop_mode_handle_menu_height">328dp</dimen>
<!-- The top margin of the handle menu in desktop mode. -->
<dimen name="desktop_mode_handle_menu_margin_top">4dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
index 410ae78dba1b..38550b405c0e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -32,6 +32,7 @@ import android.view.SurfaceControl;
import android.window.DisplayAreaAppearedInfo;
import android.window.DisplayAreaInfo;
import android.window.DisplayAreaOrganizer;
+import android.window.SystemPerformanceHinter;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -58,6 +59,14 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
/** {@link DisplayAreaContext} list, which is mapped by display IDs. */
private final SparseArray<DisplayAreaContext> mDisplayAreaContexts = new SparseArray<>();
+ private final SystemPerformanceHinter.DisplayRootProvider mPerfRootProvider =
+ new SystemPerformanceHinter.DisplayRootProvider() {
+ @Override
+ public SurfaceControl getRootForDisplay(int displayId) {
+ return mLeashes.get(displayId);
+ }
+ };
+
private final Context mContext;
public RootTaskDisplayAreaOrganizer(Executor executor, Context context) {
@@ -229,6 +238,11 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
return mDisplayAreaContexts.get(displayId);
}
+ @NonNull
+ public SystemPerformanceHinter.DisplayRootProvider getPerformanceRootProvider() {
+ return mPerfRootProvider;
+ }
+
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
final String childPrefix = innerPrefix + " ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
index f1ee8fa38485..a67821b7e819 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
@@ -318,7 +318,7 @@ public class BadgedImageView extends ConstraintLayout {
/**
* Animates the dot to the given scale, running the optional callback when the animation ends.
*/
- private void animateDotScale(float toScale, @Nullable Runnable after) {
+ public void animateDotScale(float toScale, @Nullable Runnable after) {
mDotIsAnimating = true;
// Don't restart the animation if we're already animating to the given value.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index f259902e9565..dddcbd4c96c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -512,6 +512,7 @@ public class BubbleController implements ConfigurationChangeListener,
* <p>If bubble bar is supported, bubble views will be updated to switch to bar mode.
*/
public void registerBubbleStateListener(Bubbles.BubbleStateListener listener) {
+ mBubbleProperties.refresh();
if (canShowAsBubbleBar() && listener != null) {
// Only set the listener if we can show the bubble bar.
mBubbleStateListener = listener;
@@ -529,6 +530,7 @@ public class BubbleController implements ConfigurationChangeListener,
* will be updated accordingly.
*/
public void unregisterBubbleStateListener() {
+ mBubbleProperties.refresh();
if (mBubbleStateListener != null) {
mBubbleStateListener = null;
setUpBubbleViewsForMode();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index df19757203eb..dc099d9abda4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -27,6 +27,7 @@ import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.util.PathParser
import android.view.LayoutInflater
+import android.view.View.VISIBLE
import android.widget.FrameLayout
import com.android.launcher3.icons.BubbleIconFactory
import com.android.wm.shell.R
@@ -156,7 +157,9 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
fun setShowDot(show: Boolean) {
showDot = show
- overflowBtn?.updateDotVisibility(true /* animate */)
+ if (overflowBtn?.visibility == VISIBLE) {
+ overflowBtn?.updateDotVisibility(true /* animate */)
+ }
}
/** Creates the expanded view for bubbles showing in the stack view. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index ea7053d8ee49..17e06e93b3a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -54,10 +54,6 @@ public class BubblePositioner {
public static final float FLYOUT_MAX_WIDTH_PERCENT_LARGE_SCREEN = 0.3f;
/** The max percent of screen width to use for the flyout on phone. */
public static final float FLYOUT_MAX_WIDTH_PERCENT = 0.6f;
- /** The percent of screen width for the expanded view on a large screen. **/
- private static final float EXPANDED_VIEW_LARGE_SCREEN_LANDSCAPE_WIDTH_PERCENT = 0.48f;
- /** The percent of screen width for the expanded view on a large screen. **/
- private static final float EXPANDED_VIEW_LARGE_SCREEN_PORTRAIT_WIDTH_PERCENT = 0.70f;
/** The percent of screen width for the expanded view on a small tablet. **/
private static final float EXPANDED_VIEW_SMALL_TABLET_WIDTH_PERCENT = 0.72f;
/** The percent of screen width for the expanded view when shown in the bubble bar. **/
@@ -95,6 +91,7 @@ public class BubblePositioner {
private int mPointerWidth;
private int mPointerHeight;
private int mPointerOverlap;
+ private int mManageButtonHeightIncludingMargins;
private int mManageButtonHeight;
private int mOverflowHeight;
private int mMinimumFlyoutWidthLargeScreen;
@@ -176,21 +173,20 @@ public class BubblePositioner {
mExpandedViewLargeScreenWidth = (int) (bounds.width()
* EXPANDED_VIEW_SMALL_TABLET_WIDTH_PERCENT);
} else {
- mExpandedViewLargeScreenWidth = isLandscape()
- ? (int) (bounds.width() * EXPANDED_VIEW_LARGE_SCREEN_LANDSCAPE_WIDTH_PERCENT)
- : (int) (bounds.width() * EXPANDED_VIEW_LARGE_SCREEN_PORTRAIT_WIDTH_PERCENT);
+ mExpandedViewLargeScreenWidth =
+ res.getDimensionPixelSize(R.dimen.bubble_expanded_view_largescreen_width);
}
if (mIsLargeScreen) {
- if (isLandscape() && !mIsSmallTablet) {
+ if (mIsSmallTablet) {
+ final int centeredInset = (bounds.width() - mExpandedViewLargeScreenWidth) / 2;
+ mExpandedViewLargeScreenInsetClosestEdge = centeredInset;
+ mExpandedViewLargeScreenInsetFurthestEdge = centeredInset;
+ } else {
mExpandedViewLargeScreenInsetClosestEdge = res.getDimensionPixelSize(
R.dimen.bubble_expanded_view_largescreen_landscape_padding);
mExpandedViewLargeScreenInsetFurthestEdge = bounds.width()
- mExpandedViewLargeScreenInsetClosestEdge
- mExpandedViewLargeScreenWidth;
- } else {
- final int centeredInset = (bounds.width() - mExpandedViewLargeScreenWidth) / 2;
- mExpandedViewLargeScreenInsetClosestEdge = centeredInset;
- mExpandedViewLargeScreenInsetFurthestEdge = centeredInset;
}
} else {
mExpandedViewLargeScreenInsetClosestEdge = mExpandedViewPadding;
@@ -202,7 +198,9 @@ public class BubblePositioner {
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
mPointerOverlap = res.getDimensionPixelSize(R.dimen.bubble_pointer_overlap);
- mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_total_height);
+ mManageButtonHeightIncludingMargins =
+ res.getDimensionPixelSize(R.dimen.bubble_manage_button_total_height);
+ mManageButtonHeight = res.getDimensionPixelSize(R.dimen.bubble_manage_button_height);
mExpandedViewMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
mMinimumFlyoutWidthLargeScreen = res.getDimensionPixelSize(
@@ -420,7 +418,7 @@ public class BubblePositioner {
int pointerSize = showBubblesVertically()
? mPointerWidth
: (mPointerHeight + mPointerMargin);
- int bottomPadding = isOverflow ? mExpandedViewPadding : mManageButtonHeight;
+ int bottomPadding = isOverflow ? mExpandedViewPadding : mManageButtonHeightIncludingMargins;
return getAvailableRect().height()
- expandedContainerY
- paddingTop
@@ -438,6 +436,15 @@ public class BubblePositioner {
// overflow in landscape on phone is max
return MAX_HEIGHT;
}
+
+ if (mIsLargeScreen && !mIsSmallTablet && !isOverflow) {
+ // the expanded view height on large tablets is calculated based on the shortest screen
+ // size and is the same in both portrait and landscape
+ int maxVerticalInset = Math.max(mInsets.top, mInsets.bottom);
+ int shortestScreenSide = Math.min(mScreenRect.height(), mScreenRect.width());
+ return shortestScreenSide - 2 * maxVerticalInset - mManageButtonHeight;
+ }
+
float desiredHeight = isOverflow
? mOverflowHeight
: ((Bubble) bubble).getDesiredHeight(mContext);
@@ -466,7 +473,8 @@ public class BubblePositioner {
return topAlignment;
}
// If we're here, we're showing vertically & developer has made height less than maximum.
- int manageButtonHeight = isOverflow ? mExpandedViewPadding : mManageButtonHeight;
+ int manageButtonHeight =
+ isOverflow ? mExpandedViewPadding : mManageButtonHeightIncludingMargins;
float pointerPosition = getPointerPosition(bubblePosition);
float bottomIfCentered = pointerPosition + (expandedViewHeight / 2) + manageButtonHeight;
float topIfCentered = pointerPosition - (expandedViewHeight / 2);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index c124b532b89d..2241c343a208 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1864,6 +1864,14 @@ public class BubbleStackView extends FrameLayout
: GONE);
}
+ private void updateOverflowDotVisibility(boolean expanding) {
+ if (mBubbleOverflow.showDot()) {
+ mBubbleOverflow.getIconView().animateDotScale(expanding ? 1 : 0f, () -> {
+ mBubbleOverflow.setVisible(expanding ? VISIBLE : GONE);
+ });
+ }
+ }
+
// via BubbleData.Listener
void updateBubble(Bubble bubble) {
animateInFlyoutForBubble(bubble);
@@ -2274,6 +2282,7 @@ public class BubbleStackView extends FrameLayout
if (mIsExpanded && mExpandedBubble.getExpandedView() != null) {
maybeShowManageEdu();
}
+ updateOverflowDotVisibility(true /* expanding */);
} /* after */);
int index;
if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
@@ -2405,11 +2414,15 @@ public class BubbleStackView extends FrameLayout
// since we're about to animate collapsed.
mExpandedAnimationController.notifyPreparingToCollapse();
+ updateOverflowDotVisibility(false /* expanding */);
final Runnable collapseBackToStack = () -> mExpandedAnimationController.collapseBackToStack(
mStackAnimationController
.getStackPositionAlongNearestHorizontalEdge()
/* collapseTo */,
- () -> mBubbleContainer.setActiveController(mStackAnimationController));
+ () -> {
+ mBubbleContainer.setActiveController(mStackAnimationController);
+ updateOverflowVisibility();
+ });
final Runnable after = () -> {
final BubbleViewProvider previouslySelected = mExpandedBubble;
@@ -2424,7 +2437,6 @@ public class BubbleStackView extends FrameLayout
Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
mExpandedBubble));
}
- updateOverflowVisibility();
updateZOrder();
updateBadges(true /* setBadgeForCollapsedStack */);
afterExpandedViewAnimation();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 4d7042bbb3d2..738c94e82a95 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -34,6 +34,8 @@ import androidx.dynamicanimation.animation.SpringForce;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.animation.PhysicsAnimator;
+import com.android.wm.shell.bubbles.BadgedImageView;
+import com.android.wm.shell.bubbles.BubbleOverflow;
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
@@ -63,6 +65,12 @@ public class ExpandedAnimationController
/** Damping ratio for expand/collapse spring. */
private static final float DAMPING_RATIO_MEDIUM_LOW_BOUNCY = 0.65f;
+ /**
+ * Damping ratio for the overflow bubble spring; this is less bouncy so it doesn't bounce behind
+ * the top bubble when it goes to disappear.
+ */
+ private static final float DAMPING_RATIO_OVERFLOW_BOUNCY = 0.90f;
+
/** Stiffness for the expand/collapse path-following animation. */
private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 400;
@@ -274,9 +282,14 @@ public class ExpandedAnimationController
// of the screen where the bubble will be stacked.
path.lineTo(stackedX, p.y);
+ // The overflow should animate to the collapse point, so 0 offset.
+ final boolean isOverflow = bubble instanceof BadgedImageView
+ && BubbleOverflow.KEY.equals(((BadgedImageView) bubble).getKey());
+ final float offsetY = isOverflow
+ ? 0
+ : Math.min(index, NUM_VISIBLE_WHEN_RESTING - 1) * mStackOffsetPx;
// Then, draw a line down to the stack position.
- path.lineTo(stackedX, mCollapsePoint.y
- + Math.min(index, NUM_VISIBLE_WHEN_RESTING - 1) * mStackOffsetPx);
+ path.lineTo(stackedX, mCollapsePoint.y + offsetY);
}
// The lead bubble should be the bubble with the longest distance to travel when we're
@@ -505,8 +518,12 @@ public class ExpandedAnimationController
@Override
SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
+ boolean isOverflow = (view instanceof BadgedImageView)
+ && BubbleOverflow.KEY.equals(((BadgedImageView) view).getKey());
return new SpringForce()
- .setDampingRatio(DAMPING_RATIO_MEDIUM_LOW_BOUNCY)
+ .setDampingRatio(isOverflow
+ ? DAMPING_RATIO_OVERFLOW_BOUNCY
+ : DAMPING_RATIO_MEDIUM_LOW_BOUNCY)
.setStiffness(SpringForce.STIFFNESS_LOW);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt
index 85aaa8ef585c..4206d9320b7d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt
@@ -29,4 +29,7 @@ interface BubbleProperties {
* When this is `false`, bubbles will be floating.
*/
val isBubbleBarEnabled: Boolean
+
+ /** Refreshes the current value of [isBubbleBarEnabled]. */
+ fun refresh()
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt
index 9d8b9a6f3260..e1dea3babbc2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt
@@ -22,6 +22,13 @@ import android.os.SystemProperties
object ProdBubbleProperties : BubbleProperties {
// TODO(b/256873975) Should use proper flag when available to shell/launcher
- override val isBubbleBarEnabled =
- SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false)
+ private var _isBubbleBarEnabled =
+ SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false)
+
+ override val isBubbleBarEnabled
+ get() = _isBubbleBarEnabled
+
+ override fun refresh() {
+ _isBubbleBarEnabled = SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false)
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 5e42782431fd..e9344ffcce0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -203,7 +203,7 @@ public class SystemWindows {
+ "SystemWindow:" + view);
return null;
}
- return root.getFocusGrantToken();
+ return root.getInputTransferToken();
}
private class PerDisplay {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 26b5a5052594..63cdb4f151ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -67,6 +67,7 @@ import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.InteractionJankMonitorUtils;
+import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
@@ -484,7 +485,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
/** Updates divide position and split bounds base on the ratio within root bounds. */
- public void setDivideRatio(@SnapPosition int snapPosition) {
+ public void setDivideRatio(@PersistentSnapPosition int snapPosition) {
final DividerSnapAlgorithm.SnapTarget snapTarget = mDividerSnapAlgorithm.findSnapTarget(
snapPosition);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java
index ff38b7e70410..e73430056c89 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java
@@ -26,6 +26,16 @@ import android.annotation.IntDef;
/** Helper utility class of methods and constants that are available to be imported in Launcher. */
public class SplitScreenConstants {
+ /**
+ * Duration used for every split fade-in or fade-out.
+ */
+ public static final int FADE_DURATION = 133;
+
+ ///////////////
+ // IMPORTANT for the following SPLIT_POSITION and SNAP_TO constants:
+ // These int values must not be changed -- they are persisted to user-defined app pairs, and
+ // will break things if changed.
+ //
/**
* Split position isn't specified normally meaning to use what ever it is currently set to.
@@ -44,11 +54,6 @@ public class SplitScreenConstants {
*/
public static final int SPLIT_POSITION_BOTTOM_OR_RIGHT = 1;
- /**
- * Duration used for every split fade-in or fade-out.
- */
- public static final int FADE_DURATION = 133;
-
@IntDef(prefix = {"SPLIT_POSITION_"}, value = {
SPLIT_POSITION_UNDEFINED,
SPLIT_POSITION_TOP_OR_LEFT,
@@ -57,38 +62,61 @@ public class SplitScreenConstants {
public @interface SplitPosition {
}
- /** The divider doesn't snap to any target and is freely placeable. */
- public static final int SNAP_TO_NONE = 0;
-
- /** A snap target positioned near the screen edge for a minimized task */
- public static final int SNAP_TO_MINIMIZE = 1;
-
- /** If the divider reaches this value, the left/top task should be dismissed. */
- public static final int SNAP_TO_START_AND_DISMISS = 2;
-
/** A snap target in the first half of the screen, where the split is roughly 30-70. */
- public static final int SNAP_TO_30_70 = 3;
+ public static final int SNAP_TO_30_70 = 0;
/** The 50-50 snap target */
- public static final int SNAP_TO_50_50 = 4;
+ public static final int SNAP_TO_50_50 = 1;
/** A snap target in the latter half of the screen, where the split is roughly 70-30. */
- public static final int SNAP_TO_70_30 = 5;
+ public static final int SNAP_TO_70_30 = 2;
+
+ /**
+ * These snap targets are used for split pairs in a stable, non-transient state. They may be
+ * persisted in Launcher when the user saves an app pair. They are a subset of
+ * {@link SnapPosition}.
+ */
+ @IntDef(prefix = { "SNAP_TO_" }, value = {
+ SNAP_TO_30_70,
+ SNAP_TO_50_50,
+ SNAP_TO_70_30
+ })
+ public @interface PersistentSnapPosition {}
+
+ /**
+ * Checks if the snapPosition in question is a {@link PersistentSnapPosition}.
+ */
+ public static boolean isPersistentSnapPosition(@SnapPosition int snapPosition) {
+ return snapPosition == SNAP_TO_30_70
+ || snapPosition == SNAP_TO_50_50
+ || snapPosition == SNAP_TO_70_30;
+ }
+
+ /** The divider doesn't snap to any target and is freely placeable. */
+ public static final int SNAP_TO_NONE = 10;
+
+ /** If the divider reaches this value, the left/top task should be dismissed. */
+ public static final int SNAP_TO_START_AND_DISMISS = 11;
/** If the divider reaches this value, the right/bottom task should be dismissed. */
- public static final int SNAP_TO_END_AND_DISMISS = 6;
+ public static final int SNAP_TO_END_AND_DISMISS = 12;
+
+ /** A snap target positioned near the screen edge for a minimized task */
+ public static final int SNAP_TO_MINIMIZE = 13;
@IntDef(prefix = { "SNAP_TO_" }, value = {
- SNAP_TO_NONE,
- SNAP_TO_MINIMIZE,
- SNAP_TO_START_AND_DISMISS,
SNAP_TO_30_70,
SNAP_TO_50_50,
SNAP_TO_70_30,
- SNAP_TO_END_AND_DISMISS
+ SNAP_TO_NONE,
+ SNAP_TO_START_AND_DISMISS,
+ SNAP_TO_END_AND_DISMISS,
+ SNAP_TO_MINIMIZE
})
public @interface SnapPosition {}
+ ///////////////
+
public static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
public static final int[] CONTROLLED_WINDOWING_MODES =
{WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 998cd5d08c72..e6d3abcc6e1d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -25,6 +25,7 @@ import android.os.Handler;
import android.os.SystemProperties;
import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
+import android.window.SystemPerformanceHinter;
import com.android.internal.logging.UiEventLogger;
import com.android.launcher3.icons.IconProvider;
@@ -85,6 +86,7 @@ import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
import com.android.wm.shell.keyguard.KeyguardTransitions;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedController;
+import com.android.wm.shell.performance.PerfHintController;
import com.android.wm.shell.recents.RecentTasks;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.recents.RecentsTransitionHandler;
@@ -296,6 +298,17 @@ public abstract class WMShellBaseModule {
return new LaunchAdjacentController(syncQueue);
}
+ @WMSingleton
+ @Provides
+ static SystemPerformanceHinter provideSystemPerformanceHinter(Context context,
+ ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler,
+ RootTaskDisplayAreaOrganizer rootTdaOrganizer) {
+ final PerfHintController perfHintController =
+ new PerfHintController(context, shellInit, shellCommandHandler, rootTdaOrganizer);
+ return perfHintController.getHinter();
+ }
+
//
// Back animation
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 9f9854e7e244..5dfba5e7ff1d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -199,6 +199,7 @@ public abstract class WMShellModule {
@ShellMainThread Handler mainHandler,
@ShellMainThread Choreographer mainChoreographer,
ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler,
ShellTaskOrganizer taskOrganizer,
DisplayController displayController,
ShellController shellController,
@@ -213,6 +214,7 @@ public abstract class WMShellModule {
mainHandler,
mainChoreographer,
shellInit,
+ shellCommandHandler,
taskOrganizer,
displayController,
shellController,
@@ -492,13 +494,14 @@ public abstract class WMShellModule {
ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
@DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
LaunchAdjacentController launchAdjacentController,
+ RecentsTransitionHandler recentsTransitionHandler,
@ShellMainThread ShellExecutor mainExecutor
) {
return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
transitions, enterDesktopTransitionHandler, exitDesktopTransitionHandler,
toggleResizeDesktopTaskTransitionHandler, desktopModeTaskRepository,
- launchAdjacentController, mainExecutor);
+ launchAdjacentController, recentsTransitionHandler, mainExecutor);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index af97cf68915f..8a6403705c1c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -23,7 +23,7 @@ import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.dagger.WMShellBaseModule;
import com.android.wm.shell.dagger.WMSingleton;
-import com.android.wm.shell.pip2.PipTransition;
+import com.android.wm.shell.pip2.phone.PipTransition;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/PipModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/PipModule.java
index 570f0a3db35a..f2631eff890d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/PipModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/PipModule.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.dagger.pip;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.dagger.WMSingleton;
import com.android.wm.shell.pip.PipTransitionController;
+import com.android.wm.shell.pip2.phone.PipTransition;
import dagger.Module;
import dagger.Provides;
@@ -36,7 +37,7 @@ public abstract class PipModule {
@Provides
static PipTransitionController providePipTransitionController(
com.android.wm.shell.pip.PipTransition legacyPipTransition,
- com.android.wm.shell.pip2.PipTransition newPipTransition) {
+ PipTransition newPipTransition) {
if (PipUtils.isPip2ExperimentEnabled()) {
return newPipTransition;
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 09ba4f79326e..412a5b5a6997 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -60,6 +60,8 @@ import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.TO_DESKTOP_INDICATOR
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.recents.RecentsTransitionHandler
+import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP
import com.android.wm.shell.sysui.ShellCommandHandler
@@ -68,7 +70,6 @@ import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.ShellSharedConstants
import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
-import com.android.wm.shell.transition.Transitions.TransitionHandler
import com.android.wm.shell.util.KtProtoLog
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
@@ -93,6 +94,7 @@ class DesktopTasksController(
ToggleResizeDesktopTaskTransitionHandler,
private val desktopModeTaskRepository: DesktopModeTaskRepository,
private val launchAdjacentController: LaunchAdjacentController,
+ private val recentsTransitionHandler: RecentsTransitionHandler,
@ShellMainThread private val mainExecutor: ShellExecutor
) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler {
@@ -119,6 +121,8 @@ class DesktopTasksController(
com.android.wm.shell.R.dimen.desktop_mode_transition_area_width
)
+ private var recentsAnimationRunning = false
+
// This is public to avoid cyclic dependency; it is set by SplitScreenController
lateinit var splitScreenController: SplitScreenController
@@ -139,6 +143,19 @@ class DesktopTasksController(
)
transitions.addHandler(this)
desktopModeTaskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor)
+
+ recentsTransitionHandler.addTransitionStateListener(
+ object : RecentsTransitionStateListener {
+ override fun onAnimationStateChanged(running: Boolean) {
+ KtProtoLog.v(
+ WM_SHELL_DESKTOP_MODE,
+ "DesktopTasksController: recents animation state changed running=%b",
+ running
+ )
+ recentsAnimationRunning = running
+ }
+ }
+ )
}
/** Show all tasks, that are part of the desktop, on top of launcher */
@@ -644,6 +661,10 @@ class DesktopTasksController(
val triggerTask = request.triggerTask
val shouldHandleRequest =
when {
+ recentsAnimationRunning -> {
+ reason = "recents animation is running"
+ false
+ }
// Only handle open or to front transitions
request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> {
reason = "transition type not handled (${request.type})"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index b71c48e16acb..53b5bd7ceb94 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -159,9 +159,15 @@ public class KeyguardTransitionHandler implements Transitions.TransitionHandler
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull TransitionFinishCallback finishCallback) {
+
+ if (remoteHandler == null) {
+ ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+ "missing handler for keyguard %s transition", description);
+ return false;
+ }
+
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
"start keyguard %s transition, info = %s", description, info);
-
try {
mStartedTransitions.put(transition,
new StartedTransition(info, finishTransaction, remoteHandler));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/performance/PerfHintController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/performance/PerfHintController.kt
new file mode 100644
index 000000000000..f7977f88006e
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/performance/PerfHintController.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 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.performance
+
+import android.content.Context
+import android.os.PerformanceHintManager
+import android.os.Process
+import android.window.SystemPerformanceHinter
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer
+import com.android.wm.shell.sysui.ShellCommandHandler
+import com.android.wm.shell.sysui.ShellInit
+import java.io.PrintWriter
+import java.util.concurrent.TimeUnit
+
+/**
+ * Manages the performance hints to the system.
+ */
+class PerfHintController(private val mContext: Context,
+ shellInit: ShellInit,
+ private val mShellCommandHandler: ShellCommandHandler,
+ rootTdaOrganizer: RootTaskDisplayAreaOrganizer) {
+
+ // The system perf hinter
+ val hinter: SystemPerformanceHinter
+
+ init {
+ hinter = SystemPerformanceHinter(mContext,
+ rootTdaOrganizer.performanceRootProvider)
+ shellInit.addInitCallback(this::onInit, this)
+ }
+
+ private fun onInit() {
+ mShellCommandHandler.addDumpCallback(this::dump, this)
+ val perfHintMgr = mContext.getSystemService(PerformanceHintManager::class.java)
+ val adpfSession = perfHintMgr!!.createHintSession(intArrayOf(Process.myTid()),
+ TimeUnit.SECONDS.toNanos(1))
+ hinter.setAdpfSession(adpfSession)
+ }
+
+ fun dump(pw: PrintWriter, prefix: String?) {
+ hinter.dump(pw, prefix)
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index b8e4c04ac262..d704b091754f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -14,9 +14,14 @@
* limitations under the License.
*/
-package com.android.wm.shell.pip2;
+package com.android.wm.shell.pip2.phone;
+
+import static android.view.WindowManager.TRANSIT_OPEN;
import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.app.PictureInPictureParams;
+import android.graphics.Rect;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -34,8 +39,13 @@ import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
-/** Placeholder, for demonstrate purpose only. */
+/**
+ * Implementation of transitions for PiP on phone.
+ */
public class PipTransition extends PipTransitionController {
+ @Nullable
+ private IBinder mAutoEnterButtonNavTransition;
+
public PipTransition(
@NonNull ShellInit shellInit,
@NonNull ShellTaskOrganizer shellTaskOrganizer,
@@ -58,15 +68,63 @@ public class PipTransition extends PipTransitionController {
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
+ if (isAutoEnterInButtonNavigation(request)) {
+ mAutoEnterButtonNavTransition = transition;
+ return getEnterPipTransaction(transition, request);
+ }
return null;
}
@Override
+ public void augmentRequest(@NonNull IBinder transition, @NonNull TransitionRequestInfo request,
+ @NonNull WindowContainerTransaction outWct) {
+ if (isAutoEnterInButtonNavigation(request)) {
+ outWct.merge(getEnterPipTransaction(transition, request), true /* transfer */);
+ mAutoEnterButtonNavTransition = transition;
+ }
+ }
+
+ private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ final ActivityManager.RunningTaskInfo pipTask = request.getPipTask();
+ PictureInPictureParams pipParams = pipTask.pictureInPictureParams;
+ mPipBoundsState.setBoundsStateForEntry(pipTask.topActivity, pipTask.topActivityInfo,
+ pipParams, mPipBoundsAlgorithm);
+
+ // calculate the entry bounds and notify core to move task to pinned with final bounds
+ final Rect entryBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.movePipActivityToPinnedRootTask(pipTask.token, entryBounds);
+ return wct;
+ }
+
+ private boolean isAutoEnterInButtonNavigation(@NonNull TransitionRequestInfo requestInfo) {
+ final ActivityManager.RunningTaskInfo pipTask = requestInfo.getPipTask();
+ if (pipTask == null) {
+ return false;
+ }
+ if (pipTask.pictureInPictureParams == null) {
+ return false;
+ }
+
+ // Assuming auto-enter is enabled and pipTask is non-null, the TRANSIT_OPEN request type
+ // implies that we are entering PiP in button navigation mode. This is guaranteed by
+ // TaskFragment#startPausing()` in Core which wouldn't get called in gesture nav.
+ return requestInfo.getType() == TRANSIT_OPEN
+ && pipTask.pictureInPictureParams.isAutoEnterEnabled();
+ }
+
+ @Override
public boolean startAnimation(@NonNull IBinder transition,
@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
+ if (transition == mAutoEnterButtonNavTransition) {
+ startTransaction.apply();
+ finishCallback.onTransitionFinished(null);
+ return true;
+ }
return false;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index ead2f9cbd1ad..d31476c63890 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -54,6 +54,7 @@ import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -279,7 +280,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
mDeathHandler = () -> {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
"[%d] RecentsController.DeathRecipient: binder died", mInstanceId);
- finish(mWillFinishToHome, false /* leaveHint */);
+ finish(mWillFinishToHome, false /* leaveHint */, null /* finishCb */);
};
try {
mListener.asBinder().linkToDeath(mDeathHandler, 0 /* flags */);
@@ -313,7 +314,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
}
}
if (mFinishCB != null) {
- finishInner(toHome, false /* userLeave */);
+ finishInner(toHome, false /* userLeave */, null /* finishCb */);
} else {
cleanUp();
}
@@ -670,7 +671,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
// now and let it do its animation (since recents is going to be occluded).
sendCancelWithSnapshots();
mExecutor.executeDelayed(
- () -> finishInner(true /* toHome */, false /* userLeaveHint */), 0);
+ () -> finishInner(true /* toHome */, false /* userLeaveHint */,
+ null /* finishCb */), 0);
return;
}
if (recentsOpening != null) {
@@ -899,11 +901,12 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
@Override
@SuppressLint("NewApi")
- public void finish(boolean toHome, boolean sendUserLeaveHint) {
- mExecutor.execute(() -> finishInner(toHome, sendUserLeaveHint));
+ public void finish(boolean toHome, boolean sendUserLeaveHint, IResultReceiver finishCb) {
+ mExecutor.execute(() -> finishInner(toHome, sendUserLeaveHint, finishCb));
}
- private void finishInner(boolean toHome, boolean sendUserLeaveHint) {
+ private void finishInner(boolean toHome, boolean sendUserLeaveHint,
+ IResultReceiver runnerFinishCb) {
if (mFinishCB == null) {
Slog.e(TAG, "Duplicate call to finish");
return;
@@ -993,6 +996,16 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
}
cleanUp();
finishCB.onTransitionFinished(wct.isEmpty() ? null : wct);
+ if (runnerFinishCb != null) {
+ try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.finishInner: calling finish callback",
+ mInstanceId);
+ runnerFinishCb.send(0, null);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to report transition finished", e);
+ }
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index ccffa02a22c1..664d44910e72 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -23,6 +23,7 @@ import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
+
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -85,7 +86,7 @@ import com.android.wm.shell.common.SingleInstanceRemoteListener;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
+import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -601,7 +602,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (options1 == null) options1 = new Bundle();
final ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
@@ -632,7 +633,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1,
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
+ @PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
InstanceId instanceId) {
if (options1 == null) options1 = new Bundle();
final ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
@@ -675,7 +676,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
private void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, int userId1,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
Intent fillInIntent = null;
final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
@@ -702,7 +703,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
private void startIntentAndTask(PendingIntent pendingIntent, int userId1,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
Intent fillInIntent = null;
final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent);
@@ -736,7 +737,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
@Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
+ InstanceId instanceId) {
Intent fillInIntent1 = null;
Intent fillInIntent2 = null;
final String packageName1 = SplitScreenUtils.getPackageName(pendingIntent1);
@@ -767,7 +769,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
@Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
+ @PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
InstanceId instanceId) {
Intent fillInIntent1 = null;
Intent fillInIntent2 = null;
@@ -1225,7 +1227,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Override
public void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, RemoteAnimationAdapter adapter,
+ @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController, "startTasks",
(controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition(
@@ -1236,7 +1238,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Override
public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, int userId1,
Bundle options1, int taskId, Bundle options2, int splitPosition,
- @SnapPosition int snapPosition, RemoteAnimationAdapter adapter,
+ @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController,
"startIntentAndTaskWithLegacyTransition", (controller) ->
@@ -1248,7 +1250,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Override
public void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController,
"startShortcutAndTaskWithLegacyTransition", (controller) ->
@@ -1260,8 +1262,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Override
public void startTasks(int taskId1, @Nullable Bundle options1, int taskId2,
@Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
- InstanceId instanceId) {
+ @PersistentSnapPosition int snapPosition,
+ @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController, "startTasks",
(controller) -> controller.mStageCoordinator.startTasks(taskId1, options1,
taskId2, options2, splitPosition, snapPosition, remoteTransition,
@@ -1271,7 +1273,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Override
public void startIntentAndTask(PendingIntent pendingIntent, int userId1,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController, "startIntentAndTask",
(controller) -> controller.startIntentAndTask(pendingIntent, userId1, options1,
@@ -1282,8 +1284,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Override
public void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1,
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
- InstanceId instanceId) {
+ @PersistentSnapPosition int snapPosition,
+ @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController, "startShortcutAndTask",
(controller) -> controller.startShortcutAndTask(shortcutInfo, options1, taskId,
options2, splitPosition, snapPosition, remoteTransition, instanceId));
@@ -1294,7 +1296,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
@Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, RemoteAnimationAdapter adapter,
+ @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController, "startIntentsWithLegacyTransition",
(controller) ->
@@ -1309,8 +1311,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, int userId2, @Nullable ShortcutInfo shortcutInfo2,
@Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
- InstanceId instanceId) {
+ @PersistentSnapPosition int snapPosition,
+ @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
executeRemoteCallWithTaskPermission(mController, "startIntents",
(controller) ->
controller.startIntents(pendingIntent1, userId1, shortcutInfo1,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 4ea14f473c39..b2948667f9e6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -128,7 +128,7 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.split.SplitLayout;
-import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
+import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.common.split.SplitWindowManager;
@@ -143,6 +143,8 @@ import com.android.wm.shell.util.SplitBounds;
import com.android.wm.shell.util.TransitionUtil;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
+import dalvik.annotation.optimization.NeverCompile;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
@@ -633,7 +635,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Starts 2 tasks in one transition. */
void startTasks(int taskId1, @Nullable Bundle options1, int taskId2, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (taskId2 == INVALID_TASK_ID) {
@@ -661,7 +663,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Start an intent and a task to a split pair in one transition. */
void startIntentAndTask(PendingIntent pendingIntent, Intent fillInIntent,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (taskId == INVALID_TASK_ID) {
@@ -683,7 +685,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Starts a shortcut and a task to a split pair in one transition. */
void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1,
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
+ @PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition,
InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (taskId == INVALID_TASK_ID) {
@@ -710,7 +712,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
* {@link SplitscreenEventLogger#logEnter(float, int, int, int, int, boolean)}
*/
private void startWithTask(WindowContainerTransaction wct, int mainTaskId,
- @Nullable Bundle mainOptions, @SnapPosition int snapPosition,
+ @Nullable Bundle mainOptions, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
if (!mMainStage.isActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
@@ -744,7 +746,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
PendingIntent pendingIntent2, Intent fillInIntent2,
@Nullable ShortcutInfo shortcutInfo2, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (pendingIntent2 == null) {
@@ -796,7 +798,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Starts a pair of tasks using legacy transition. */
void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
- @SnapPosition int snapPosition, RemoteAnimationAdapter adapter, InstanceId instanceId) {
+ @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
+ InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
if (taskId2 == INVALID_TASK_ID) {
@@ -826,7 +829,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Nullable ShortcutInfo shortcutInfo1, @Nullable Bundle options1,
@Nullable PendingIntent pendingIntent2, Intent fillInIntent2,
@Nullable ShortcutInfo shortcutInfo2, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
@@ -851,7 +854,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
@@ -872,7 +875,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** Starts a pair of shortcut and task using legacy transition. */
void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo,
@Nullable Bundle options1, int taskId, @Nullable Bundle options2,
- @SplitPosition int splitPosition, @SnapPosition int snapPosition,
+ @SplitPosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (options1 == null) options1 = new Bundle();
@@ -934,7 +937,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void startWithLegacyTransition(WindowContainerTransaction wct,
@Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
@Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle mainOptions,
- @SplitPosition int sidePosition, @SnapPosition int snapPosition,
+ @SplitPosition int sidePosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
startWithLegacyTransition(wct, INVALID_TASK_ID, mainPendingIntent, mainFillInIntent,
mainShortcutInfo, mainOptions, sidePosition, snapPosition, adapter, instanceId);
@@ -942,7 +945,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
@Nullable Bundle mainOptions, @SplitPosition int sidePosition,
- @SnapPosition int snapPosition, RemoteAnimationAdapter adapter,
+ @PersistentSnapPosition int snapPosition, RemoteAnimationAdapter adapter,
InstanceId instanceId) {
startWithLegacyTransition(wct, mainTaskId, null /* mainPendingIntent */,
null /* mainFillInIntent */, null /* mainShortcutInfo */, mainOptions, sidePosition,
@@ -957,7 +960,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId,
@Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
@Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle options,
- @SplitPosition int sidePosition, @SnapPosition int snapPosition,
+ @SplitPosition int sidePosition, @PersistentSnapPosition int snapPosition,
RemoteAnimationAdapter adapter, InstanceId instanceId) {
if (!isSplitScreenVisible()) {
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
@@ -3108,6 +3111,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER);
}
+ @NeverCompile
@Override
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 83dc7fa5e869..e828eedc275c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -23,6 +23,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
+
import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
@@ -693,9 +694,19 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
+ Transitions.TransitionFinishCallback finishCB = wct -> {
+ mixed.mInFlightSubAnimations--;
+ if (mixed.mInFlightSubAnimations == 0) {
+ mActiveTransitions.remove(mixed);
+ finishCallback.onTransitionFinished(wct);
+ }
+ };
+
+ mixed.mInFlightSubAnimations++;
boolean consumed = mRecentsHandler.startAnimation(
- mixed.mTransition, info, startTransaction, finishTransaction, finishCallback);
+ mixed.mTransition, info, startTransaction, finishTransaction, finishCB);
if (!consumed) {
+ mixed.mInFlightSubAnimations--;
return false;
}
if (mDesktopTasksController != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java
index a68b41d6563a..3e06d2d0e797 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java
@@ -19,7 +19,7 @@ import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.wm.shell.common.split.SplitScreenConstants.SnapPosition;
+import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
import java.util.Objects;
@@ -39,7 +39,7 @@ public class SplitBounds implements Parcelable {
public final float leftTaskPercent;
public final float dividerWidthPercent;
public final float dividerHeightPercent;
- public final @SnapPosition int snapPosition;
+ public final @PersistentSnapPosition int snapPosition;
/**
* If {@code true}, that means at the time of creation of this object, the
* split-screened apps were vertically stacked. This is useful in scenarios like
@@ -51,7 +51,7 @@ public class SplitBounds implements Parcelable {
public final int rightBottomTaskId;
public SplitBounds(Rect leftTopBounds, Rect rightBottomBounds, int leftTopTaskId,
- int rightBottomTaskId, @SnapPosition int snapPosition) {
+ int rightBottomTaskId, @PersistentSnapPosition int snapPosition) {
this.leftTopBounds = leftTopBounds;
this.rightBottomBounds = rightBottomBounds;
this.leftTopTaskId = leftTopTaskId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index afa2754803f1..bf99ab35cdd7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -79,11 +79,13 @@ import com.android.wm.shell.recents.RecentsTransitionStateListener;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.KeyguardChangeListener;
+import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration.ExclusionRegionListener;
+import java.io.PrintWriter;
import java.util.Optional;
import java.util.function.Supplier;
@@ -97,6 +99,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
private final DesktopModeWindowDecoration.Factory mDesktopModeWindowDecorFactory;
private final ActivityTaskManager mActivityTaskManager;
+ private final ShellCommandHandler mShellCommandHandler;
private final ShellTaskOrganizer mTaskOrganizer;
private final ShellController mShellController;
private final Context mContext;
@@ -134,6 +137,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
Handler mainHandler,
Choreographer mainChoreographer,
ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler,
ShellTaskOrganizer taskOrganizer,
DisplayController displayController,
ShellController shellController,
@@ -148,6 +152,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mainHandler,
mainChoreographer,
shellInit,
+ shellCommandHandler,
taskOrganizer,
displayController,
shellController,
@@ -167,6 +172,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
Handler mainHandler,
Choreographer mainChoreographer,
ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler,
ShellTaskOrganizer taskOrganizer,
DisplayController displayController,
ShellController shellController,
@@ -189,7 +195,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mTransitions = transitions;
mDesktopTasksController = desktopTasksController;
mRecentsTransitionHandler = recentsTransitionHandler;
-
+ mShellCommandHandler = shellCommandHandler;
mDesktopModeWindowDecorFactory = desktopModeWindowDecorFactory;
mInputMonitorFactory = inputMonitorFactory;
mTransactionFactory = transactionFactory;
@@ -206,6 +212,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
onRecentsTransitionStarted(transition);
}
});
+ mShellCommandHandler.addDumpCallback(this::dump, this);
}
@Override
@@ -369,7 +376,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
public void onClick(View v) {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
final int id = v.getId();
- if (id == R.id.close_window || id == R.id.close_button) {
+ if (id == R.id.close_window) {
mTaskOperations.closeTask(mTaskToken);
if (isTaskInSplitScreen(mTaskId)) {
RunningTaskInfo remainingTask = getOtherSplitTask(mTaskId);
@@ -593,6 +600,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
super.dispose();
}
+ @Override
+ public String toString() {
+ return "EventReceiver"
+ + "{"
+ + "tasksOnDisplay="
+ + mTasksOnDisplay
+ + "}";
+ }
+
private void incrementTaskNumber() {
mTasksOnDisplay++;
}
@@ -981,6 +997,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
&& mSplitScreenController.isTaskInSplitScreen(taskId);
}
+ private void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + "DesktopModeWindowDecorViewModel");
+ pw.println(innerPrefix + "DesktopModeStatus=" + DesktopModeStatus.isEnabled());
+ pw.println(innerPrefix + "mTransitionDragActive=" + mTransitionDragActive);
+ pw.println(innerPrefix + "mEventReceiversByDisplay=" + mEventReceiversByDisplay);
+ pw.println(innerPrefix + "mWindowDecorByTaskId=" + mWindowDecorByTaskId);
+ }
+
private class DragStartListenerImpl
implements DragPositioningCallbackUtility.DragStartListener {
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 84ec6b389c4a..380b59e84485 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.windowdecor;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.windowingModeToString;
import android.app.ActivityManager;
import android.app.WindowConfiguration.WindowingMode;
@@ -661,6 +662,17 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mRelayoutBlock++;
}
+ @Override
+ public String toString() {
+ return "{"
+ + "mPositionInParent=" + mPositionInParent + ", "
+ + "mRelayoutBlock=" + mRelayoutBlock + ", "
+ + "taskId=" + mTaskInfo.taskId + ", "
+ + "windowingMode=" + windowingModeToString(mTaskInfo.getWindowingMode()) + ", "
+ + "isFocused=" + isFocused()
+ + "}";
+ }
+
static class Factory {
DesktopModeWindowDecoration create(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
index a7a11dee80f2..15f8f1cfadf2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
@@ -42,7 +42,6 @@ import android.widget.TextView;
import android.window.SurfaceSyncGroup;
import com.android.wm.shell.R;
-import com.android.wm.shell.desktopmode.DesktopModeStatus;
/**
* Handle menu opened when the appropriate button is clicked on.
@@ -56,12 +55,8 @@ class HandleMenu {
private static final String TAG = "HandleMenu";
private final Context mContext;
private final WindowDecoration mParentDecor;
- private WindowDecoration.AdditionalWindow mAppInfoPill;
- private WindowDecoration.AdditionalWindow mWindowingPill;
- private WindowDecoration.AdditionalWindow mMoreActionsPill;
- private final PointF mAppInfoPillPosition = new PointF();
- private final PointF mWindowingPillPosition = new PointF();
- private final PointF mMoreActionsPillPosition = new PointF();
+ private WindowDecoration.AdditionalWindow mHandleMenuWindow;
+ private final PointF mHandleMenuPosition = new PointF();
private final boolean mShouldShowWindowingPill;
private final Drawable mAppIcon;
private final CharSequence mAppName;
@@ -73,13 +68,8 @@ class HandleMenu {
private final int mCaptionY;
private int mMarginMenuTop;
private int mMarginMenuStart;
- private int mMarginMenuSpacing;
+ private int mMenuHeight;
private int mMenuWidth;
- private int mAppInfoPillHeight;
- private int mWindowingPillHeight;
- private int mMoreActionsPillHeight;
- private int mShadowRadius;
- private int mCornerRadius;
HandleMenu(WindowDecoration parentDecor, int layoutResId, int captionX, int captionY,
@@ -104,102 +94,86 @@ class HandleMenu {
final SurfaceSyncGroup ssg = new SurfaceSyncGroup(TAG);
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- createAppInfoPill(t, ssg);
- if (mShouldShowWindowingPill) {
- createWindowingPill(t, ssg);
- }
- createMoreActionsPill(t, ssg);
+ createHandleMenuWindow(t, ssg);
ssg.addTransaction(t);
ssg.markSyncReady();
setupHandleMenu();
}
- private void createAppInfoPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
- final int x = (int) mAppInfoPillPosition.x;
- final int y = (int) mAppInfoPillPosition.y;
- mAppInfoPill = mParentDecor.addWindow(
- R.layout.desktop_mode_window_decor_handle_menu_app_info_pill,
- "Menu's app info pill",
- t, ssg, x, y, mMenuWidth, mAppInfoPillHeight, mShadowRadius, mCornerRadius);
+ private void createHandleMenuWindow(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
+ final int x = (int) mHandleMenuPosition.x;
+ final int y = (int) mHandleMenuPosition.y;
+ mHandleMenuWindow = mParentDecor.addWindow(
+ R.layout.desktop_mode_window_decor_handle_menu, "Handle Menu",
+ t, ssg, x, y, mMenuWidth, mMenuHeight);
}
- private void createWindowingPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
- final int x = (int) mWindowingPillPosition.x;
- final int y = (int) mWindowingPillPosition.y;
- mWindowingPill = mParentDecor.addWindow(
- R.layout.desktop_mode_window_decor_handle_menu_windowing_pill,
- "Menu's windowing pill",
- t, ssg, x, y, mMenuWidth, mWindowingPillHeight, mShadowRadius, mCornerRadius);
- }
-
- private void createMoreActionsPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
- final int x = (int) mMoreActionsPillPosition.x;
- final int y = (int) mMoreActionsPillPosition.y;
- mMoreActionsPill = mParentDecor.addWindow(
- R.layout.desktop_mode_window_decor_handle_menu_more_actions_pill,
- "Menu's more actions pill",
- t, ssg, x, y, mMenuWidth, mMoreActionsPillHeight, mShadowRadius, mCornerRadius);
+ /**
+ * Set up all three pills of the handle menu: app info pill, windowing pill, & more actions
+ * pill.
+ */
+ private void setupHandleMenu() {
+ final View handleMenu = mHandleMenuWindow.mWindowViewHost.getView();
+ handleMenu.setOnTouchListener(mOnTouchListener);
+ setupAppInfoPill(handleMenu);
+ if (mShouldShowWindowingPill) {
+ setupWindowingPill(handleMenu);
+ }
+ setupMoreActionsPill(handleMenu);
}
/**
- * Set up interactive elements and color of this handle menu
+ * Set up interactive elements of handle menu's app info pill.
*/
- private void setupHandleMenu() {
- // App Info pill setup.
- final View appInfoPillView = mAppInfoPill.mWindowViewHost.getView();
- final ImageButton collapseBtn = appInfoPillView.findViewById(R.id.collapse_menu_button);
- final ImageView appIcon = appInfoPillView.findViewById(R.id.application_icon);
- final TextView appName = appInfoPillView.findViewById(R.id.application_name);
+ private void setupAppInfoPill(View handleMenu) {
+ final ImageButton collapseBtn = handleMenu.findViewById(R.id.collapse_menu_button);
+ final ImageView appIcon = handleMenu.findViewById(R.id.application_icon);
+ final TextView appName = handleMenu.findViewById(R.id.application_name);
collapseBtn.setOnClickListener(mOnClickListener);
- appInfoPillView.setOnTouchListener(mOnTouchListener);
appIcon.setImageDrawable(mAppIcon);
appName.setText(mAppName);
+ }
- // Windowing pill setup.
- if (mShouldShowWindowingPill) {
- final View windowingPillView = mWindowingPill.mWindowViewHost.getView();
- final ImageButton fullscreenBtn = windowingPillView.findViewById(
- R.id.fullscreen_button);
- final ImageButton splitscreenBtn = windowingPillView.findViewById(
- R.id.split_screen_button);
- final ImageButton floatingBtn = windowingPillView.findViewById(R.id.floating_button);
- // TODO: Remove once implemented.
- floatingBtn.setVisibility(View.GONE);
-
- final ImageButton desktopBtn = windowingPillView.findViewById(R.id.desktop_button);
- fullscreenBtn.setOnClickListener(mOnClickListener);
- splitscreenBtn.setOnClickListener(mOnClickListener);
- floatingBtn.setOnClickListener(mOnClickListener);
- desktopBtn.setOnClickListener(mOnClickListener);
- // The button corresponding to the windowing mode that the task is currently in uses a
- // different color than the others.
- final int[] iconColors = getWindowingIconColor();
- final ColorStateList inActiveColorStateList = ColorStateList.valueOf(iconColors[0]);
- final ColorStateList activeColorStateList = ColorStateList.valueOf(iconColors[1]);
- fullscreenBtn.setImageTintList(
- mTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
- ? activeColorStateList : inActiveColorStateList);
- splitscreenBtn.setImageTintList(
- mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
- ? activeColorStateList : inActiveColorStateList);
- floatingBtn.setImageTintList(mTaskInfo.getWindowingMode() == WINDOWING_MODE_PINNED
- ? activeColorStateList : inActiveColorStateList);
- desktopBtn.setImageTintList(mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
- ? activeColorStateList : inActiveColorStateList);
- }
+ /**
+ * Set up interactive elements and color of handle menu's windowing pill.
+ */
+ private void setupWindowingPill(View handleMenu) {
+ final ImageButton fullscreenBtn = handleMenu.findViewById(
+ R.id.fullscreen_button);
+ final ImageButton splitscreenBtn = handleMenu.findViewById(
+ R.id.split_screen_button);
+ final ImageButton floatingBtn = handleMenu.findViewById(R.id.floating_button);
+ // TODO: Remove once implemented.
+ floatingBtn.setVisibility(View.GONE);
+
+ final ImageButton desktopBtn = handleMenu.findViewById(R.id.desktop_button);
+ fullscreenBtn.setOnClickListener(mOnClickListener);
+ splitscreenBtn.setOnClickListener(mOnClickListener);
+ floatingBtn.setOnClickListener(mOnClickListener);
+ desktopBtn.setOnClickListener(mOnClickListener);
+ // The button corresponding to the windowing mode that the task is currently in uses a
+ // different color than the others.
+ final ColorStateList[] iconColors = getWindowingIconColor();
+ final ColorStateList inActiveColorStateList = iconColors[0];
+ final ColorStateList activeColorStateList = iconColors[1];
+ final int windowingMode = mTaskInfo.getWindowingMode();
+ fullscreenBtn.setImageTintList(windowingMode == WINDOWING_MODE_FULLSCREEN
+ ? activeColorStateList : inActiveColorStateList);
+ splitscreenBtn.setImageTintList(windowingMode == WINDOWING_MODE_MULTI_WINDOW
+ ? activeColorStateList : inActiveColorStateList);
+ floatingBtn.setImageTintList(windowingMode == WINDOWING_MODE_PINNED
+ ? activeColorStateList : inActiveColorStateList);
+ desktopBtn.setImageTintList(windowingMode == WINDOWING_MODE_FREEFORM
+ ? activeColorStateList : inActiveColorStateList);
+ }
- // More Actions pill setup.
- final View moreActionsPillView = mMoreActionsPill.mWindowViewHost.getView();
- final Button closeBtn = moreActionsPillView.findViewById(R.id.close_button);
- if (shouldShowCloseButton()) {
- closeBtn.setVisibility(View.GONE);
- } else {
- closeBtn.setVisibility(View.VISIBLE);
- closeBtn.setOnClickListener(mOnClickListener);
- }
- final Button selectBtn = moreActionsPillView.findViewById(R.id.select_button);
+ /**
+ * Set up interactive elements & height of handle menu's more actions pill
+ */
+ private void setupMoreActionsPill(View handleMenu) {
+ final Button selectBtn = handleMenu.findViewById(R.id.select_button);
selectBtn.setOnClickListener(mOnClickListener);
- final Button screenshotBtn = moreActionsPillView.findViewById(R.id.screenshot_button);
+ final Button screenshotBtn = handleMenu.findViewById(R.id.screenshot_button);
// TODO: Remove once implemented.
screenshotBtn.setVisibility(View.GONE);
}
@@ -208,7 +182,7 @@ class HandleMenu {
* Returns array of windowing icon color based on current UI theme. First element of the
* array is for inactive icons and the second is for active icons.
*/
- private int[] getWindowingIconColor() {
+ private ColorStateList[] getWindowingIconColor() {
final int mode = mContext.getResources().getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_MASK;
final boolean isNightMode = (mode == Configuration.UI_MODE_NIGHT_YES);
@@ -218,11 +192,12 @@ class HandleMenu {
final int inActiveColor = typedArray.getColor(0, isNightMode ? Color.WHITE : Color.BLACK);
final int activeColor = typedArray.getColor(1, isNightMode ? Color.WHITE : Color.BLACK);
typedArray.recycle();
- return new int[] {inActiveColor, activeColor};
+ return new ColorStateList[]{ColorStateList.valueOf(inActiveColor),
+ ColorStateList.valueOf(activeColor)};
}
/**
- * Updates the handle menu pills' position variables to reflect their next positions
+ * Updates handle menu's position variables to reflect its next position.
*/
private void updateHandleMenuPillPositions() {
final int menuX, menuY;
@@ -239,39 +214,19 @@ class HandleMenu {
menuY = mCaptionY + mMarginMenuStart;
}
- // App Info pill setup.
- final int appInfoPillY = menuY;
- mAppInfoPillPosition.set(menuX, appInfoPillY);
+ // Handle Menu position setup.
+ mHandleMenuPosition.set(menuX, menuY);
- final int windowingPillY, moreActionsPillY;
- if (mShouldShowWindowingPill) {
- windowingPillY = appInfoPillY + mAppInfoPillHeight + mMarginMenuSpacing;
- mWindowingPillPosition.set(menuX, windowingPillY);
- moreActionsPillY = windowingPillY + mWindowingPillHeight + mMarginMenuSpacing;
- mMoreActionsPillPosition.set(menuX, moreActionsPillY);
- } else {
- // Just start after the end of the app info pill + margins.
- moreActionsPillY = appInfoPillY + mAppInfoPillHeight + mMarginMenuSpacing;
- mMoreActionsPillPosition.set(menuX, moreActionsPillY);
- }
}
/**
* Update pill layout, in case task changes have caused positioning to change.
*/
void relayout(SurfaceControl.Transaction t) {
- if (mAppInfoPill != null) {
+ if (mHandleMenuWindow != null) {
updateHandleMenuPillPositions();
- t.setPosition(mAppInfoPill.mWindowSurface,
- mAppInfoPillPosition.x, mAppInfoPillPosition.y);
- // Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
- final boolean shouldShowWindowingPill = DesktopModeStatus.isEnabled();
- if (shouldShowWindowingPill) {
- t.setPosition(mWindowingPill.mWindowSurface,
- mWindowingPillPosition.x, mWindowingPillPosition.y);
- }
- t.setPosition(mMoreActionsPill.mWindowSurface,
- mMoreActionsPillPosition.x, mMoreActionsPillPosition.y);
+ t.setPosition(mHandleMenuWindow.mWindowSurface,
+ mHandleMenuPosition.x, mHandleMenuPosition.y);
}
}
@@ -283,12 +238,12 @@ class HandleMenu {
* @param ev the MotionEvent to compare against.
*/
void checkClickEvent(MotionEvent ev) {
- final View appInfoPill = mAppInfoPill.mWindowViewHost.getView();
- final ImageButton collapse = appInfoPill.findViewById(R.id.collapse_menu_button);
+ final View handleMenu = mHandleMenuWindow.mWindowViewHost.getView();
+ final ImageButton collapse = handleMenu.findViewById(R.id.collapse_menu_button);
// Translate the input point from display coordinates to the same space as the collapse
// button, meaning its parent (app info pill view).
- final PointF inputPoint = new PointF(ev.getX() - mAppInfoPillPosition.x,
- ev.getY() - mAppInfoPillPosition.y);
+ final PointF inputPoint = new PointF(ev.getX() - mHandleMenuPosition.x,
+ ev.getY() - mHandleMenuPosition.y);
if (pointInView(collapse, inputPoint.x, inputPoint.y)) {
mOnClickListener.onClick(collapse);
}
@@ -303,23 +258,10 @@ class HandleMenu {
*/
boolean isValidMenuInput(PointF inputPoint) {
if (!viewsLaidOut()) return true;
- final boolean pointInAppInfoPill = pointInView(
- mAppInfoPill.mWindowViewHost.getView(),
- inputPoint.x - mAppInfoPillPosition.x,
- inputPoint.y - mAppInfoPillPosition.y);
- boolean pointInWindowingPill = false;
- if (mWindowingPill != null) {
- pointInWindowingPill = pointInView(
- mWindowingPill.mWindowViewHost.getView(),
- inputPoint.x - mWindowingPillPosition.x,
- inputPoint.y - mWindowingPillPosition.y);
- }
- final boolean pointInMoreActionsPill = pointInView(
- mMoreActionsPill.mWindowViewHost.getView(),
- inputPoint.x - mMoreActionsPillPosition.x,
- inputPoint.y - mMoreActionsPillPosition.y);
-
- return pointInAppInfoPill || pointInWindowingPill || pointInMoreActionsPill;
+ return pointInView(
+ mHandleMenuWindow.mWindowViewHost.getView(),
+ inputPoint.x - mHandleMenuPosition.x,
+ inputPoint.y - mHandleMenuPosition.y);
}
private boolean pointInView(View v, float x, float y) {
@@ -331,33 +273,31 @@ class HandleMenu {
* Check if the views for handle menu can be seen.
*/
private boolean viewsLaidOut() {
- return mAppInfoPill.mWindowViewHost.getView().isLaidOut();
+ return mHandleMenuWindow.mWindowViewHost.getView().isLaidOut();
}
-
private void loadHandleMenuDimensions() {
final Resources resources = mContext.getResources();
mMenuWidth = loadDimensionPixelSize(resources,
R.dimen.desktop_mode_handle_menu_width);
+ mMenuHeight = getHandleMenuHeight(resources);
mMarginMenuTop = loadDimensionPixelSize(resources,
R.dimen.desktop_mode_handle_menu_margin_top);
mMarginMenuStart = loadDimensionPixelSize(resources,
R.dimen.desktop_mode_handle_menu_margin_start);
- mMarginMenuSpacing = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_pill_spacing_margin);
- mAppInfoPillHeight = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_app_info_pill_height);
- mWindowingPillHeight = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_windowing_pill_height);
- mMoreActionsPillHeight = shouldShowCloseButton()
- ? loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_more_actions_pill_freeform_height)
- : loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_more_actions_pill_height);
- mShadowRadius = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_shadow_radius);
- mCornerRadius = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_corner_radius);
+ }
+
+ /**
+ * Determines handle menu height based on if windowing pill should be shown.
+ */
+ private int getHandleMenuHeight(Resources resources) {
+ int menuHeight = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_height);
+ if (!mShouldShowWindowingPill) {
+ menuHeight -= loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_windowing_pill_height);
+ }
+ return menuHeight;
}
private int loadDimensionPixelSize(Resources resources, int resourceId) {
@@ -367,19 +307,9 @@ class HandleMenu {
return resources.getDimensionPixelSize(resourceId);
}
- private boolean shouldShowCloseButton() {
- return mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM;
- }
-
void close() {
- mAppInfoPill.releaseView();
- mAppInfoPill = null;
- if (mWindowingPill != null) {
- mWindowingPill.releaseView();
- mWindowingPill = null;
- }
- mMoreActionsPill.releaseView();
- mMoreActionsPill = null;
+ mHandleMenuWindow.releaseView();
+ mHandleMenuWindow = null;
}
static final class Builder {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 07fee4316c08..335a5886ba28 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -44,6 +44,7 @@ import android.window.WindowContainerTransaction;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
import java.util.function.Supplier;
@@ -283,10 +284,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
// Task surface itself
float shadowRadius = loadDimension(resources, params.mShadowRadiusId);
- int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor();
- mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
- mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
- mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
final Point taskPosition = mTaskInfo.positionInParent;
if (isFullscreen) {
// Setting the task crop to the width/height stops input events from being sent to
@@ -302,13 +299,22 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
finishT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
}
startT.setShadowRadius(mTaskSurface, shadowRadius)
- .setColor(mTaskSurface, mTmpColor)
.show(mTaskSurface);
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
.setShadowRadius(mTaskSurface, shadowRadius);
if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ if (!DesktopModeStatus.isVeiledResizeEnabled()) {
+ // When fluid resize is enabled, add a background to freeform tasks
+ int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor();
+ mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
+ mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
+ mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
+ startT.setColor(mTaskSurface, mTmpColor);
+ }
startT.setCornerRadius(mTaskSurface, params.mCornerRadius);
finishT.setCornerRadius(mTaskSurface, params.mCornerRadius);
+ } else if (!DesktopModeStatus.isVeiledResizeEnabled()) {
+ startT.unsetColor(mTaskSurface);
}
if (mCaptionWindowManager == null) {
@@ -425,13 +431,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
* @param yPos y position of new window
* @param width width of new window
* @param height height of new window
- * @param shadowRadius radius of the shadow of the new window
- * @param cornerRadius radius of the corners of the new window
* @return the {@link AdditionalWindow} that was added.
*/
AdditionalWindow addWindow(int layoutId, String namePrefix, SurfaceControl.Transaction t,
- SurfaceSyncGroup ssg, int xPos, int yPos, int width, int height, int shadowRadius,
- int cornerRadius) {
+ SurfaceSyncGroup ssg, int xPos, int yPos, int width, int height) {
final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
SurfaceControl windowSurfaceControl = builder
.setName(namePrefix + " of Task=" + mTaskInfo.taskId)
@@ -442,8 +445,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
t.setPosition(windowSurfaceControl, xPos, yPos)
.setWindowCrop(windowSurfaceControl, width, height)
- .setShadowRadius(windowSurfaceControl, shadowRadius)
- .setCornerRadius(windowSurfaceControl, cornerRadius)
.show(windowSurfaceControl);
final WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(width, height,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
index 213d596a6131..943b16c33a98 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipFromSplitScreenOnGoToHomeTest.kt
@@ -23,7 +23,6 @@ import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
-import android.tools.common.flicker.subject.region.RegionTraceSubject
import android.tools.device.helpers.WindowUtils
import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.filters.RequiresDevice
@@ -87,8 +86,6 @@ class AutoEnterPipFromSplitScreenOnGoToHomeTest(flicker: LegacyFlickerTest) :
pipApp.enableAutoEnterForPipActivity()
}
teardown {
- // close gracefully so that onActivityUnpinned() can be called before force exit
- pipApp.closePipWindow(wmHelper)
pipApp.exit(wmHelper)
secondAppForSplitScreen.exit(wmHelper)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index e38c4c34fc53..19c8435facaf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -67,8 +67,6 @@ open class AutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) :
override val defaultTeardown: FlickerBuilder.() -> Unit = {
teardown {
- // close gracefully so that onActivityUnpinned() can be called before force exit
- pipApp.closePipWindow(wmHelper)
pipApp.exit(wmHelper)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 6dd68b0d029d..820af9316aae 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -55,8 +55,6 @@ class EnterPipOnUserLeaveHintTest(flicker: LegacyFlickerTest) : EnterPipTransiti
override val defaultTeardown: FlickerBuilder.() -> Unit = {
teardown {
- // close gracefully so that onActivityUnpinned() can be called before force exit
- pipApp.closePipWindow(wmHelper)
pipApp.exit(wmHelper)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt
new file mode 100644
index 000000000000..4f27ceddd705
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipAspectRatioChangeTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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.flicker.pip
+
+import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.LegacyFlickerTest
+import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
+import com.android.wm.shell.flicker.pip.common.PipTransition
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/** Test changing aspect ratio of pip. */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipAspectRatioChangeTest(flicker: LegacyFlickerTest) : PipTransition(flicker) {
+ override val thisTransition: FlickerBuilder.() -> Unit = {
+ transitions {
+ pipApp.changeAspectRatio()
+ }
+ }
+
+ @Presubmit
+ @Test
+ fun pipAspectRatioChangesProperly() {
+ flicker.assertLayersStart { this.visibleRegion(pipApp).isSameAspectRatio(16, 9) }
+ flicker.assertLayersEnd { this.visibleRegion(pipApp).isSameAspectRatio(1, 2) }
+ }
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams() =
+ LegacyFlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(Rotation.ROTATION_0)
+ )
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 54f94986d90c..d09a90cd7dc7 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -45,7 +45,7 @@ android_test {
"kotlinx-coroutines-core",
"mockito-kotlin2",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
"testables",
"platform-test-annotations",
"servicestests-utils",
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
index 58d9a6486ff2..287a97c9b5b0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubblePositionerTest.java
@@ -22,20 +22,24 @@ import static android.view.View.LAYOUT_DIRECTION_LTR;
import static android.view.View.LAYOUT_DIRECTION_RTL;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableResources;
+import android.util.DisplayMetrics;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;
@@ -257,6 +261,27 @@ public class BubblePositionerTest extends ShellTestCase {
assertThat(mPositioner.hasUserModifiedDefaultPosition()).isTrue();
}
+ @Test
+ public void testExpandedViewHeight_onLargeTablet() {
+ Insets insets = Insets.of(10, 20, 5, 15);
+ Rect screenBounds = new Rect(0, 0, 1800, 2600);
+
+ new WindowManagerConfig()
+ .setLargeScreen()
+ .setInsets(insets)
+ .setScreenBounds(screenBounds)
+ .setUpConfig();
+ mPositioner.update();
+
+ Intent intent = new Intent(Intent.ACTION_VIEW).setPackage(mContext.getPackageName());
+ Bubble bubble = Bubble.createAppBubble(intent, new UserHandle(1), null, directExecutor());
+
+ int manageButtonHeight =
+ mContext.getResources().getDimensionPixelSize(R.dimen.bubble_manage_button_height);
+ float expectedHeight = 1800 - 2 * 20 - manageButtonHeight;
+ assertThat(mPositioner.getExpandedViewHeight(bubble)).isWithin(0.1f).of(expectedHeight);
+ }
+
/**
* Calculates the Y position bubbles should be placed based on the config. Based on
* the calculations in {@link BubblePositioner#getDefaultStartPosition()} and
@@ -323,6 +348,8 @@ public class BubblePositionerTest extends ShellTestCase {
? MIN_WIDTH_FOR_TABLET
: MIN_WIDTH_FOR_TABLET - 1;
mConfiguration.orientation = mOrientation;
+ mConfiguration.screenWidthDp = pxToDp(mScreenBounds.width());
+ mConfiguration.screenHeightDp = pxToDp(mScreenBounds.height());
when(mConfiguration.getLayoutDirection()).thenReturn(mLayoutDirection);
WindowInsets windowInsets = mock(WindowInsets.class);
@@ -331,5 +358,11 @@ public class BubblePositionerTest extends ShellTestCase {
when(mWindowMetrics.getBounds()).thenReturn(mScreenBounds);
when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
}
+
+ private int pxToDp(float px) {
+ int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
+ float dp = px / ((float) dpi / DisplayMetrics.DENSITY_DEFAULT);
+ return (int) dp;
+ }
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenConstantsTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenConstantsTest.kt
new file mode 100644
index 000000000000..fe261107d65b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitScreenConstantsTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.common.split
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SplitScreenConstantsTest {
+
+ /**
+ * Ensures that some important constants are not changed from their set values. These values
+ * are persisted in user-defined app pairs, and changing them will break things.
+ */
+ @Test
+ fun shouldKeepExistingConstantValues() {
+ assertEquals(
+ "the value of SPLIT_POSITION_TOP_OR_LEFT should be 0",
+ 0,
+ SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT,
+ )
+ assertEquals(
+ "the value of SPLIT_POSITION_BOTTOM_OR_RIGHT should be 1",
+ 1,
+ SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT,
+ )
+ assertEquals(
+ "the value of SNAP_TO_30_70 should be 0",
+ 0,
+ SplitScreenConstants.SNAP_TO_30_70,
+ )
+ assertEquals(
+ "the value of SNAP_TO_50_50 should be 1",
+ 1,
+ SplitScreenConstants.SNAP_TO_50_50,
+ )
+ assertEquals(
+ "the value of SNAP_TO_70_30 should be 2",
+ 2,
+ SplitScreenConstants.SNAP_TO_70_30,
+ )
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index dea161786da2..ebcb6407a6fd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -54,6 +54,8 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreef
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask
+import com.android.wm.shell.recents.RecentsTransitionHandler
+import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
@@ -101,11 +103,13 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Mock lateinit var launchAdjacentController: LaunchAdjacentController
@Mock lateinit var desktopModeWindowDecoration: DesktopModeWindowDecoration
@Mock lateinit var splitScreenController: SplitScreenController
+ @Mock lateinit var recentsTransitionHandler: RecentsTransitionHandler
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var controller: DesktopTasksController
private lateinit var shellInit: ShellInit
private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
+ private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
private val shellExecutor = TestShellExecutor()
// Mock running tasks are registered here so we can get the list from mock shell task organizer
@@ -126,6 +130,10 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.splitScreenController = splitScreenController
shellInit.init()
+
+ val captor = ArgumentCaptor.forClass(RecentsTransitionStateListener::class.java)
+ verify(recentsTransitionHandler).addTransitionStateListener(captor.capture())
+ recentsTransitionStateListener = captor.value
}
private fun createController(): DesktopTasksController {
@@ -144,6 +152,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
mToggleResizeDesktopTaskTransitionHandler,
desktopModeTaskRepository,
launchAdjacentController,
+ recentsTransitionHandler,
shellExecutor
)
}
@@ -355,7 +364,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun moveToDesktop_splitTaskExitsSplit() {
- var task = setUpSplitScreenTask()
+ val task = setUpSplitScreenTask()
controller.moveToDesktop(desktopModeWindowDecoration, task)
val wct = getLatestMoveToDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -367,7 +376,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun moveToDesktop_fullscreenTaskDoesNotExitSplit() {
- var task = setUpFullscreenTask()
+ val task = setUpFullscreenTask()
controller.moveToDesktop(desktopModeWindowDecoration, task)
val wct = getLatestMoveToDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -666,6 +675,20 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
@Test
+ fun handleRequest_recentsAnimationRunning_returnNull() {
+ // Set up a visible freeform task so a fullscreen task should be converted to freeform
+ val freeformTask = setUpFreeformTask()
+ markTaskVisible(freeformTask)
+
+ // Mark recents animation running
+ recentsTransitionStateListener.onAnimationStateChanged(true)
+
+ // Open a fullscreen task, check that it does not result in a WCT with changes to it
+ val fullscreenTask = createFullscreenTask()
+ assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull()
+ }
+
+ @Test
fun stashDesktopApps_stateUpdates() {
whenever(DesktopModeStatus.isStashingEnabled()).thenReturn(true)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 00d70a75837b..8eaf5a004c0a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -49,6 +49,7 @@ import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.recents.RecentsTransitionHandler
import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.sysui.KeyguardChangeListener
+import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.Transitions
@@ -89,6 +90,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
@Mock private lateinit var mockShellExecutor: ShellExecutor
@Mock private lateinit var mockRootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
@Mock private lateinit var mockRecentsTransitionHandler: RecentsTransitionHandler
+ @Mock private lateinit var mockShellCommandHandler: ShellCommandHandler
private val transactionFactory = Supplier<SurfaceControl.Transaction> {
SurfaceControl.Transaction()
@@ -105,6 +107,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
mockMainHandler,
mockMainChoreographer,
shellInit,
+ mockShellCommandHandler,
mockTaskOrganizer,
mockDisplayController,
mockShellController,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 76bc25aa66ef..fcb7863429d6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -17,7 +17,9 @@
package com.android.wm.shell.windowdecor;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlBuilder;
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlTransaction;
@@ -36,6 +38,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.quality.Strictness.LENIENT;
import android.app.ActivityManager;
import android.content.Context;
@@ -59,10 +62,12 @@ import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.tests.R;
import org.junit.Before;
@@ -119,8 +124,6 @@ public class WindowDecorationTests extends ShellTestCase {
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
private Configuration mWindowConfiguration = new Configuration();
private int mCaptionMenuWidthId;
- private int mCaptionMenuShadowRadiusId;
- private int mCaptionMenuCornerRadiusId;
@Before
public void setUp() {
@@ -131,8 +134,6 @@ public class WindowDecorationTests extends ShellTestCase {
mRelayoutParams.mLayoutResId = 0;
mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
mCaptionMenuWidthId = R.dimen.test_freeform_decor_caption_menu_width;
- mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
- mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
mRelayoutParams.mCornerRadius = CORNER_RADIUS;
@@ -205,12 +206,8 @@ public class WindowDecorationTests extends ShellTestCase {
createMockSurfaceControlBuilder(captionContainerSurface);
mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
- final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
- new ActivityManager.TaskDescription.Builder()
- .setBackgroundColor(Color.YELLOW);
final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
.setDisplayId(Display.DEFAULT_DISPLAY)
- .setTaskDescriptionBuilder(taskDescriptionBuilder)
.setBounds(TASK_BOUNDS)
.setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
.setVisible(true)
@@ -259,8 +256,6 @@ public class WindowDecorationTests extends ShellTestCase {
verify(mMockSurfaceControlFinishT).setCornerRadius(taskSurface, CORNER_RADIUS);
verify(mMockSurfaceControlStartT)
.show(taskSurface);
- verify(mMockSurfaceControlStartT)
- .setColor(taskSurface, new float[] {1.f, 1.f, 0.f});
verify(mMockSurfaceControlStartT).setShadowRadius(taskSurface, 10);
assertEquals(300, mRelayoutResult.mWidth);
@@ -417,16 +412,6 @@ public class WindowDecorationTests extends ShellTestCase {
final int height = WindowDecoration.loadDimensionPixelSize(
windowDecor.mDecorWindowContext.getResources(), mRelayoutParams.mCaptionHeightId);
verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, width, height);
- final int shadowRadius = WindowDecoration.loadDimensionPixelSize(
- windowDecor.mDecorWindowContext.getResources(),
- mCaptionMenuShadowRadiusId);
- verify(mMockSurfaceControlAddWindowT)
- .setShadowRadius(additionalWindowSurface, shadowRadius);
- final int cornerRadius = WindowDecoration.loadDimensionPixelSize(
- windowDecor.mDecorWindowContext.getResources(),
- mCaptionMenuCornerRadiusId);
- verify(mMockSurfaceControlAddWindowT)
- .setCornerRadius(additionalWindowSurface, cornerRadius);
verify(mMockSurfaceControlAddWindowT).show(additionalWindowSurface);
verify(mMockSurfaceControlViewHostFactory, Mockito.times(2))
.create(any(), eq(defaultDisplay), any());
@@ -516,6 +501,86 @@ public class WindowDecorationTests extends ShellTestCase {
verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
}
+ @Test
+ public void testRelayout_fluidResizeEnabled_freeformTask_setTaskSurfaceColor() {
+ StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
+ DesktopModeStatus.class).strictness(
+ LENIENT).startMocking();
+ when(DesktopModeStatus.isVeiledResizeEnabled()).thenReturn(false);
+
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder decorContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(decorContainerSurface);
+ mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+ final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+ new ActivityManager.TaskDescription.Builder()
+ .setBackgroundColor(Color.YELLOW);
+
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setVisible(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM)
+ .build();
+ taskInfo.isFocused = true;
+ final SurfaceControl taskSurface = mock(SurfaceControl.class);
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+ windowDecor.relayout(taskInfo);
+
+ verify(mMockSurfaceControlStartT).setColor(taskSurface, new float[] {1.f, 1.f, 0.f});
+
+ mockitoSession.finishMocking();
+ }
+
+ @Test
+ public void testRelayout_fluidResizeEnabled_fullscreenTask_clearTaskSurfaceColor() {
+ StaticMockitoSession mockitoSession = mockitoSession().mockStatic(
+ DesktopModeStatus.class).strictness(LENIENT).startMocking();
+ when(DesktopModeStatus.isVeiledResizeEnabled()).thenReturn(false);
+
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder decorContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(decorContainerSurface);
+ mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+ final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+ new ActivityManager.TaskDescription.Builder()
+ .setBackgroundColor(Color.YELLOW);
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setVisible(true)
+ .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+ .build();
+ taskInfo.isFocused = true;
+ final SurfaceControl taskSurface = mock(SurfaceControl.class);
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+ windowDecor.relayout(taskInfo);
+
+ verify(mMockSurfaceControlStartT).unsetColor(taskSurface);
+
+ mockitoSession.finishMocking();
+ }
+
private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
@@ -588,13 +653,11 @@ public class WindowDecorationTests extends ShellTestCase {
int y = mRelayoutParams.mCaptionY;
int width = loadDimensionPixelSize(resources, mCaptionMenuWidthId);
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
- int shadowRadius = loadDimensionPixelSize(resources, mCaptionMenuShadowRadiusId);
- int cornerRadius = loadDimensionPixelSize(resources, mCaptionMenuCornerRadiusId);
String name = "Test Window";
WindowDecoration.AdditionalWindow additionalWindow =
- addWindow(R.layout.desktop_mode_window_decor_handle_menu_app_info_pill, name,
+ addWindow(R.layout.desktop_mode_window_decor_handle_menu, name,
mMockSurfaceControlAddWindowT, mMockSurfaceSyncGroup, x, y,
- width, height, shadowRadius, cornerRadius);
+ width, height);
return additionalWindow;
}
}
diff --git a/libs/dream/lowlight/tests/Android.bp b/libs/dream/lowlight/tests/Android.bp
index 64b53cbb5c5a..4dafd0aa6df4 100644
--- a/libs/dream/lowlight/tests/Android.bp
+++ b/libs/dream/lowlight/tests/Android.bp
@@ -34,7 +34,7 @@ android_test {
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"testables",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.mock",
diff --git a/libs/hwui/OWNERS b/libs/hwui/OWNERS
index 6ca991d8b294..bc174599a4d3 100644
--- a/libs/hwui/OWNERS
+++ b/libs/hwui/OWNERS
@@ -4,9 +4,8 @@ alecmouri@google.com
djsollen@google.com
jreck@google.com
njawad@google.com
-reed@google.com
scroggo@google.com
-stani@google.com
+sumir@google.com
# For text, e.g. Typeface, Font, Minikin, etc.
nona@google.com
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 2c13ceb77b52..a952be020855 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -65,21 +65,41 @@ static jlong Shader_getNativeFinalizer(JNIEnv*, jobject) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref));
}
-static jlong createBitmapShaderHelper(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
- jint tileModeX, jint tileModeY, bool isDirectSampled,
- const SkSamplingOptions& sampling) {
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static SkGainmapInfo sNoOpGainmap = {
+ .fGainmapRatioMin = {1.f, 1.f, 1.f, 1.0},
+ .fGainmapRatioMax = {1.f, 1.f, 1.f, 1.0},
+ .fGainmapGamma = {1.f, 1.f, 1.f, 1.f},
+ .fEpsilonSdr = {0.f, 0.f, 0.f, 1.0},
+ .fEpsilonHdr = {0.f, 0.f, 0.f, 1.0},
+ .fDisplayRatioSdr = 1.f,
+ .fDisplayRatioHdr = 1.f,
+};
+
+static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
+ jint tileModeX, jint tileModeY, jint maxAniso, bool filter,
+ bool isDirectSampled, jlong overrideGainmapPtr) {
+ SkSamplingOptions sampling = maxAniso > 0 ? SkSamplingOptions::Aniso(static_cast<int>(maxAniso))
+ : SkSamplingOptions(filter ? SkFilterMode::kLinear
+ : SkFilterMode::kNearest,
+ SkMipmapMode::kNone);
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+ const Gainmap* gainmap = reinterpret_cast<Gainmap*>(overrideGainmapPtr);
sk_sp<SkImage> image;
if (bitmapHandle) {
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
auto& bitmap = android::bitmap::toBitmap(bitmapHandle);
image = bitmap.makeImage();
+ if (!gainmap && bitmap.hasGainmap()) {
+ gainmap = bitmap.gainmap().get();
+ }
- if (!isDirectSampled && bitmap.hasGainmap()) {
- sk_sp<SkShader> gainmapShader = MakeGainmapShader(
- image, bitmap.gainmap()->bitmap->makeImage(), bitmap.gainmap()->info,
- (SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
+ if (!isDirectSampled && gainmap && gainmap->info != sNoOpGainmap) {
+ sk_sp<SkShader> gainmapShader =
+ MakeGainmapShader(image, gainmap->bitmap->makeImage(), gainmap->info,
+ (SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
if (gainmapShader) {
if (matrix) {
gainmapShader = gainmapShader->makeWithLocalMatrix(*matrix);
@@ -111,26 +131,6 @@ static jlong createBitmapShaderHelper(JNIEnv* env, jobject o, jlong matrixPtr, j
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
- jint tileModeX, jint tileModeY, bool filter,
- bool isDirectSampled) {
- SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,
- SkMipmapMode::kNone);
- return createBitmapShaderHelper(env, o, matrixPtr, bitmapHandle, tileModeX, tileModeY,
- isDirectSampled, sampling);
-}
-
-static jlong BitmapShader_constructorWithMaxAniso(JNIEnv* env, jobject o, jlong matrixPtr,
- jlong bitmapHandle, jint tileModeX,
- jint tileModeY, jint maxAniso,
- bool isDirectSampled) {
- auto sampling = SkSamplingOptions::Aniso(static_cast<int>(maxAniso));
- return createBitmapShaderHelper(env, o, matrixPtr, bitmapHandle, tileModeX, tileModeY,
- isDirectSampled, sampling);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-
static std::vector<SkColor4f> convertColorLongs(JNIEnv* env, jlongArray colorArray) {
const size_t count = env->GetArrayLength(colorArray);
const jlong* colorValues = env->GetLongArrayElements(colorArray, nullptr);
@@ -419,8 +419,7 @@ static const JNINativeMethod gShaderMethods[] = {
};
static const JNINativeMethod gBitmapShaderMethods[] = {
- {"nativeCreate", "(JJIIZZ)J", (void*)BitmapShader_constructor},
- {"nativeCreateWithMaxAniso", "(JJIIIZ)J", (void*)BitmapShader_constructorWithMaxAniso},
+ {"nativeCreate", "(JJIIIZZJ)J", (void*)BitmapShader_constructor},
};
diff --git a/libs/securebox/tests/Android.bp b/libs/securebox/tests/Android.bp
index 7df546ae0ff6..80b501da1aa5 100644
--- a/libs/securebox/tests/Android.bp
+++ b/libs/securebox/tests/Android.bp
@@ -32,7 +32,7 @@ android_test {
"platform-test-annotations",
"testables",
"testng",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.mock",