Merge "Make AllAppsRecyclerViewContainer GONE when hidden" into udc-qpr-dev
diff --git a/Android.bp b/Android.bp
index 9b696a2..316f9c0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -153,7 +153,8 @@
"androidx.cardview_cardview",
"com.google.android.material_material",
"iconloader_base",
- "view_capture"
+ "view_capture",
+ "animationlib"
],
manifest: "AndroidManifest-common.xml",
sdk_version: "current",
diff --git a/go/quickstep/res/drawable/ic_listen.xml b/go/quickstep/res/drawable/ic_listen.xml
index 16bb597..a226e49 100644
--- a/go/quickstep/res/drawable/ic_listen.xml
+++ b/go/quickstep/res/drawable/ic_listen.xml
@@ -19,6 +19,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M15.08,7.05c0.84,1.18 0.84,2.71 0,3.89l1.68,1.69c2.02,-2.02 2.02,-5.07 0,-7.27l-1.68,1.69zM20.07,2l-1.63,1.63c2.77,3.02 2.77,7.56 0,10.74L20.07,16c3.9,-3.89 3.91,-9.95 0,-14zM9,13c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM9,7c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2zM9,14c-2.67,0 -8,1.34 -8,4v3h16v-3c0,-2.66 -5.33,-4 -8,-4zM15,19L3,19v-0.99C3.2,17.29 6.3,16 9,16s5.8,1.29 6,2v1z"/>
</vector>
diff --git a/go/quickstep/res/drawable/ic_search.xml b/go/quickstep/res/drawable/ic_search.xml
index ce290d9..33297cf 100644
--- a/go/quickstep/res/drawable/ic_search.xml
+++ b/go/quickstep/res/drawable/ic_search.xml
@@ -19,18 +19,18 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M16,3h-2v2h2c1.65,0 3,1.35 3,3v2h2V8C21,5.24 18.76,3 16,3z"/>
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M5,16v-2H3v2c0,2.76 2.24,5 5,5h2v-2H8C6.35,19 5,17.65 5,16z"/>
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M12,8.5c-1.93,0 -3.5,1.57 -3.5,3.5s1.57,3.5 3.5,3.5s3.5,-1.57 3.5,-3.5S13.93,8.5 12,8.5z"/>
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M18,18m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M5,8c0,-1.65 1.35,-3 3,-3h2V3H8C5.24,3 3,5.24 3,8v2h2V8z"/>
</vector>
diff --git a/go/quickstep/res/drawable/ic_translate.xml b/go/quickstep/res/drawable/ic_translate.xml
index e3df56f..26e9ced 100644
--- a/go/quickstep/res/drawable/ic_translate.xml
+++ b/go/quickstep/res/drawable/ic_translate.xml
@@ -19,6 +19,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
- android:fillColor="@android:color/white"
+ android:fillColor="@color/overview_button"
android:pathData="M12.87,15.07l-2.54,-2.51 0.03,-0.03c1.74,-1.94 2.98,-4.17 3.71,-6.53L17,6L17,4h-7L10,2L8,2v2L1,4v1.99h11.17C11.5,7.92 10.44,9.75 9,11.35 8.07,10.32 7.3,9.19 6.69,8h-2c0.73,1.63 1.73,3.17 2.98,4.56l-5.09,5.02L4,19l5,-5 3.11,3.11 0.76,-2.04zM18.5,10h-2L12,22h2l1.12,-3h4.75L21,22h2l-4.5,-12zM15.88,17l1.62,-4.33L19.12,17h-3.24z"/>
</vector>
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index 48650aa..20bd937 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -23,8 +23,8 @@
<LinearLayout
android:id="@+id/action_buttons"
android:layout_width="match_parent"
- android:layout_height="@dimen/overview_actions_height"
- android:layout_gravity="top|center_horizontal"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal">
<Space
@@ -104,13 +104,11 @@
</LinearLayout>
<!-- Unused. Included only for compatibility with parent class. -->
- <Button
+ <ImageButton
android:id="@+id/action_split"
style="@style/GoOverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableStart="@drawable/ic_split_vertical"
- android:text="@string/action_split"
+ android:src="@drawable/ic_split_vertical"
+ android:contentDescription="@string/action_split"
android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:visibility="gone" />
diff --git a/go/quickstep/res/values/dimens.xml b/go/quickstep/res/values/dimens.xml
index 84d7fe5..dda4c26 100644
--- a/go/quickstep/res/values/dimens.xml
+++ b/go/quickstep/res/values/dimens.xml
@@ -24,7 +24,7 @@
<dimen name="go_overview_button_container_width">80dp</dimen>
<dimen name="go_overview_button_container_margin">16dp</dimen>
<dimen name="go_overview_button_caption_margin">8dp</dimen>
- <dimen name="overview_actions_height">96dp</dimen>
+ <dimen name="overview_actions_size">96dp</dimen>
<dimen name="overview_proactive_row_height">0dp</dimen>
<dimen name="overview_proactive_row_bottom_margin">24dp</dimen>
<dimen name="task_corner_radius_override">28dp</dimen>
diff --git a/res/interpolator/standard_decelerate.xml b/quickstep/res/drawable/bg_bubble_dismiss_circle.xml
similarity index 65%
rename from res/interpolator/standard_decelerate.xml
rename to quickstep/res/drawable/bg_bubble_dismiss_circle.xml
index 579f4f5..b793eec 100644
--- a/res/interpolator/standard_decelerate.xml
+++ b/quickstep/res/drawable/bg_bubble_dismiss_circle.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2022 The Android Open Source Project
+ ~ 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.
@@ -15,8 +15,13 @@
~ limitations under the License.
-->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0"
- android:controlY1="0"
- android:controlX2="0"
- android:controlY2="1"/>
\ No newline at end of file
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+
+ <stroke
+ android:width="2dp"
+ android:color="@android:color/system_accent1_600" />
+
+ <solid android:color="@android:color/system_accent1_600" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/ic_bubble_dismiss_white.xml b/quickstep/res/drawable/ic_bubble_dismiss_white.xml
new file mode 100644
index 0000000..b15111b
--- /dev/null
+++ b/quickstep/res/drawable/ic_bubble_dismiss_white.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="20dp"
+ android:height="20dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+ android:fillColor="@android:color/system_neutral1_50"/>
+</vector>
diff --git a/quickstep/res/drawable/ic_screenshot.xml b/quickstep/res/drawable/ic_screenshot.xml
index 9ee6c44..ea10661 100644
--- a/quickstep/res/drawable/ic_screenshot.xml
+++ b/quickstep/res/drawable/ic_screenshot.xml
@@ -1,32 +1,10 @@
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="20dp"
- android:height="20dp"
- android:viewportWidth="20"
- android:viewportHeight="20">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:pathData="M5.8334,1.666H8.3334V3.3327H5.8334V6.666H4.1667V3.3327C4.1667,2.4122 4.9129,1.666 5.8334,1.666Z"
- android:fillColor="#000000"/>
- <path
- android:pathData="M4.1667,13.3327V16.666C4.1667,17.5865 4.9129,18.3327 5.8334,18.3327H8.3334V16.666H5.8334V13.3327H4.1667Z"
- android:fillColor="#000000"/>
- <path
- android:pathData="M14.1667,13.3327V16.666H11.6667V18.3327H14.1667C15.0872,18.3327 15.8334,17.5865 15.8334,16.666V13.3327H14.1667Z"
- android:fillColor="#000000"/>
- <path
- android:pathData="M15.8334,6.666V3.3327C15.8334,2.4122 15.0872,1.666 14.1667,1.666H11.6667V3.3327H14.1667V6.666H15.8334Z"
- android:fillColor="#000000"/>
-</vector>
\ No newline at end of file
+ android:pathData="M5,4C5,2.343 6.343,1 8,1L16,1C17.657,1 19,2.343 19,4L19,20C19,21.657 17.657,23 16,23L8,23C6.343,23 5,21.657 5,20L5,4ZM8,3C7.448,3 7,3.448 7,4L7,20C7,20.552 7.448,21 8,21L16,21C16.552,21 17,20.552 17,20L17,4C17,3.448 16.552,3 16,3L8,3ZM8,4L8,8L9.5,8L9.5,5.5L12,5.5L12,4L8,4ZM16,16L16,20L12,20L12,18.5L14.5,18.5L14.5,16L16,16Z"
+ android:fillColor="@color/overview_button"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/quickstep/res/interpolator/three_point_fast_out_extra_slow_in.xml b/quickstep/res/interpolator/three_point_fast_out_extra_slow_in.xml
deleted file mode 100644
index 70c4231..0000000
--- a/quickstep/res/interpolator/three_point_fast_out_extra_slow_in.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2021, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"/>
diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml
index bfeb82d..f0ea09c 100644
--- a/quickstep/res/layout/fallback_recents_activity.xml
+++ b/quickstep/res/layout/fallback_recents_activity.xml
@@ -15,6 +15,7 @@
-->
<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 0fda0bf..2192a64 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -22,7 +22,7 @@
<LinearLayout
android:id="@+id/action_buttons"
android:layout_width="match_parent"
- android:layout_height="@dimen/overview_actions_height"
+ android:layout_height="@dimen/overview_actions_size"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal">
@@ -31,13 +31,14 @@
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
android:id="@+id/action_screenshot"
style="@style/OverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableStart="@drawable/ic_screenshot"
- android:text="@string/action_screenshot"
+ android:layout_width="@dimen/overview_actions_size"
+ android:layout_height="@dimen/overview_actions_size"
+ android:gravity="center"
+ android:src="@drawable/ic_screenshot"
+ android:contentDescription="@string/action_screenshot"
android:theme="@style/ThemeControlHighlightWorkspaceColor" />
<Space
@@ -46,12 +47,14 @@
android:layout_height="1dp"
android:visibility="gone" />
- <Button
+ <ImageButton
android:id="@+id/action_split"
style="@style/OverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/action_split"
+ android:layout_width="@dimen/overview_actions_size"
+ android:layout_height="@dimen/overview_actions_size"
+ android:gravity="center"
+ android:src="@drawable/ic_split_vertical"
+ android:contentDescription="@string/action_split"
android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:visibility="gone" />
diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml
index 7a6d16a..0890a4e 100644
--- a/quickstep/res/layout/transient_taskbar.xml
+++ b/quickstep/res/layout/transient_taskbar.xml
@@ -49,6 +49,7 @@
android:visibility="gone"
android:gravity="center"
android:clipChildren="false"
+ android:elevation="@dimen/bubblebar_elevation"
/>
<FrameLayout
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 8007646..b589e32 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skermkiekie"</string>
<string name="action_split" msgid="2098009717623550676">"Verdeel"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tik op ’n ander app om verdeelde skerm te gebruik"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Verlaat verdeeldeskermkeuse"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Kies nog ’n app as jy verdeelde skerm wil gebruik"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Jou organisasie laat nie hierdie program toe nie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Slaan navigasietutoriaal oor?"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index d0269b8..d9e9691 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -33,12 +33,12 @@
<string name="all_apps_prediction_tip" msgid="2672336544844936186">"የእርስዎ የሚገመቱ መተግበሪያዎች"</string>
<string name="hotseat_edu_title_migrate" msgid="306578144424489980">"በመነሻ ገጽዎ ታችኛው ረድፍ ላይ የመተግበሪያ አስተያየት ጥቆማዎችን ያግኙ"</string>
<string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"በመነሻ ማያ ገጽዎ የተወዳጆች ረድፍ ላይ የመተግበሪያ አስተያየት ጥቆማዎችን ያግኙ"</string>
- <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"በጣም ስራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ። በታችኛው ረድፍ ላይ ያሉ መተግበሪያዎች ወደ መነሻ ገጽዎ ይወሰዳሉ።"</string>
+ <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"በጣም ሥራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ። በታችኛው ረድፍ ላይ ያሉ መተግበሪያዎች ወደ መነሻ ገጽዎ ይወሰዳሉ።"</string>
<string name="hotseat_edu_message_migrate_landscape" msgid="4248943380443387697">"በጣም ሥራ ላይ የዋሉ መተግበሪያዎችዎን በቀላሉ ከመነሻ ገጹ ሆነው ይድረሱባቸው። የአስተያየት ጥቆማዎች በእርስዎ ዕለት ተዕለት ተግባራት ላይ በመመሥረት ይቀየራሉ። በተወዳጆች ረድፍ ውስጥ ያሉ መተግበሪያዎች ወደ የእርስዎ መነሻ ማያ ገፅ ይንቀሳቀሳሉ።"</string>
<string name="hotseat_edu_accept" msgid="1611544083278999837">"የመተግበሪያ አስተያየት ጥቆማዎችን አግኝ"</string>
<string name="hotseat_edu_dismiss" msgid="2781161822780201689">"አይ፣ አመሰግናለሁ"</string>
<string name="hotseat_prediction_settings" msgid="6246554993566070818">"ቅንብሮች"</string>
- <string name="hotseat_auto_enrolled" msgid="522100018967146807">"በብዛት ስራ ላይ የዋሉ መተግበሪያዎች እዚህ ይመጣሉ፣ እና በዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ"</string>
+ <string name="hotseat_auto_enrolled" msgid="522100018967146807">"በብዛት ሥራ ላይ የዋሉ መተግበሪያዎች እዚህ ይመጣሉ፣ እና በዕለት ተዕለት ተግባራት ላይ በመመስረት ይቀየራሉ"</string>
<string name="hotseat_tip_no_empty_slots" msgid="1325212677738179185">"የመተግበሪያ ጥቆማዎችን ለማግኘት መተግበሪያዎችን ከታችኛው ረድፍ ይጎትቱ"</string>
<string name="hotseat_tip_gaps_filled" msgid="3035673010274223538">"የመተግበሪያ አስተያየት ጥቆማዎች ወደ ባዶ ቦታ ታክለዋል"</string>
<string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"የመተግበሪያ አስተያየት ጥቆማዎች ነቅቷል"</string>
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ቅጽበታዊ ገፅ እይታ"</string>
<string name="action_split" msgid="2098009717623550676">"ክፈል"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"የተከፈለ ማያ ገጽን ለመጠቀም ሌላ መተግበሪያ መታ ያድርጉ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ከተከፈለ ማያ ገፅ ምርጫ ይውጡ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"የተከፈለ ማያ ገጽን ለመቀበል ሌላ መተግበሪያ ይምረጡ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ይህ ድርጊት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"የአሰሳ አጋዥ ሥልጠናን ይዝለሉ?"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 3f711de..6d7effc 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"لقطة شاشة"</string>
<string name="action_split" msgid="2098009717623550676">"تقسيم"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"انقر على تطبيق آخر لاستخدام وضع تقسيم الشاشة."</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"الخروج من وضع تقسيم الشاشة"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"اختَر تطبيقًا آخر لاستخدام وضع تقسيم الشاشة."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"لا يسمح التطبيق أو لا تسمح مؤسستك بهذا الإجراء."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"هل تريد تخطي الدليل التوجيهي للتنقّل؟"</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 9ab8c30..a68aee5 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্ৰীনশ্বট"</string>
<string name="action_split" msgid="2098009717623550676">"বিভাজন কৰক"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপত টিপক"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"বিভাজিত স্ক্ৰীনৰ বাছনিৰ পৰা বাহিৰ হওক"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ অন্য এটা এপ্ বাছক"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"এপ্টোৱে অথবা আপোনাৰ প্ৰতিষ্ঠানে এই কাৰ্যটোৰ অনুমতি নিদিয়ে"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশ্বনৰ টিউট’ৰিয়েল এৰিব বিচাৰে নেকি?"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 4b45d50..9fff2d8 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skrinşot"</string>
<string name="action_split" msgid="2098009717623550676">"Ayırın"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Bölünmüş ekran üçün başqa tətbiqə toxunun"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Bölünmüş ekran seçimindən çıxın"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Bölünmüş ekrandan istifadə üçün başqa tətbiq seçin"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Bu əməliyyata tətbiq və ya təşkilatınız tərəfindən icazə verilmir"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Naviqasiya dərsliyi ötürülsün?"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index b818edc..9a7aa4b 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="action_split" msgid="2098009717623550676">"Podeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu aplikaciju za podeljeni ekran"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Izlazak iz biranja podeljenog ekrana"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Odaberite drugu aplikaciju za podeljeni ekran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili organizacija ne dozvoljavaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite da preskočite vodič za kretanje?"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 6438392..ca62108 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Здымак экрана"</string>
<string name="action_split" msgid="2098009717623550676">"Падзелены экран"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Каб падзяліць экран, націсніце на іншую праграму"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Выйсці з рэжыму падзеленага экрана"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Каб падзяліць экран, выберыце іншую праграму"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Гэта дзеянне не дазволена праграмай ці вашай арганізацыяй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Прапусціць дапаможнік па навігацыі?"</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index c8f19f1..72e731a 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Екранна снимка"</string>
<string name="action_split" msgid="2098009717623550676">"Разделяне на екрана"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Докоснете друго прил., за да ползвате разд. екран"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Изход от избора на разделен екран"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"За разделен екран изберете още едно приложение"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Това действие не е разрешено от приложението или организацията ви"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропускане на урока за навигиране?"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index b114620..0973a50 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"স্ক্রিনশট নিন"</string>
<string name="action_split" msgid="2098009717623550676">"স্প্লিট"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"স্প্লিট স্ক্রিন ব্যবহারের জন্য অ্যাপে ট্যাপ করুন"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"স্প্লিট স্ক্রিন বেছে নেওয়ার বিকল্প থেকে বেরিয়ে আসুন"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"স্প্লিট স্ক্রিন ব্যবহার করতে অন্য অ্যাপ বেছে নিন"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"নেভিগেশন টিউটোরিয়াল এড়িয়ে যেতে চান?"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index c186550..a2e4e33 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimak ekrana"</string>
<string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu apl. da koristite podijeljeni ekran"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Izlaz iz odabira podijeljenog ekrana"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Odaberite drugu apl. da koristite podijeljeni ekran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ovu radnju ne dozvoljava aplikacija ili vaša organizacija"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Preskočiti vodič za navigiranje?"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index d446190..0cfe820 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
<string name="action_split" msgid="2098009717623550676">"Divideix"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toca una altra app per utilitzar pantalla dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Surt de la selecció de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Tria una altra app per utilitzar pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'aplicació o la teva organització no permeten aquesta acció"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vols ometre el tutorial de navegació?"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index afb026e..3582005 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snímek obrazovky"</string>
<string name="action_split" msgid="2098009717623550676">"Rozdělit"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Obrazovku rozdělíte klepnutím na jinou aplikaci"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Výběr opuštění rozdělené obrazovky"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Vyberte podporovanou aplikaci"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikace nebo organizace zakazuje tuto akci"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Přeskočit výukový program k navigaci?"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index bfce9a1..d0fed79 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Opdel"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tryk på en anden app for at bruge opdelt skærm"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Luk valg af opdelt skærm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Vælg en anden app for at bruge opdelt skærm"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller din organisation tillader ikke denne handling"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du springe vejledningen for navigation over?"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 1eedbb8..b48e5d6 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Teilen"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Für Splitscreen auf weitere App tippen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Splitscreen-Auswahl beenden"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Für Splitscreen andere App auswählen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Die App oder deine Organisation lässt diese Aktion nicht zu"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Tutorial zur Bedienung überspringen?"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 3ea7c1e..ab9fe6d 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Στιγμιότυπο οθόνης"</string>
<string name="action_split" msgid="2098009717623550676">"Διαχωρισμός"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Πατήστε άλλη εφαρμογή για διαχωρισμό οθόνης"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Έξοδος από την επιλογή διαχωρισμού οθόνης"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Επιλέξτε άλλη εφαρμογή για διαχωρισμό οθόνης"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Αυτή η ενέργεια δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Παράβλεψη οδηγού πλοήγησης;"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index db6a6cc..dde0177 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 2e3010e..eed32b3 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organization"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index db6a6cc..dde0177 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index db6a6cc..dde0177 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 342d580..ae825c1 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tap another app to use split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Exit split screen selection"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choose another app to use split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"This action isn\'t allowed by the app or your organization"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Skip navigation tutorial?"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 35ab3db..b737129 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captura de pantalla"</string>
<string name="action_split" msgid="2098009717623550676">"Pantalla dividida"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Presiona otra app para usar la pantalla dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Salir de la selección de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Elige otra app para usar la pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"La app o tu organización no permiten realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Omitir el instructivo de navegación?"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 3377381..7a681b1 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Hacer captura"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toca otra aplicación para usar la pantalla dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Salir de la selección de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Elige otra app para usar la pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"No puedes hacerlo porque la aplicación o tu organización no lo permiten"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"¿Saltar tutorial de navegación?"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 1bf92c4..176741a 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
<string name="action_split" msgid="2098009717623550676">"Eralda"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Jagatud ekraanikuva kasutamiseks puudutage muud rakendust"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Jagatud ekraanikuva valikust väljumine"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Valige jagatud ekraanikuva jaoks muu rakendus"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Rakendus või teie organisatsioon on selle toimingu keelanud"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kas jätta navigeerimise õpetused vahele?"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index c801297..0d6c664 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Atera pantaila-argazki bat"</string>
<string name="action_split" msgid="2098009717623550676">"Zatitu"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Sakatu beste aplikazio bat pantaila zatitzeko"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Irten Pantaila zatitzea eginbidearen hautapenetik"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pantaila zatitua ikusteko, aukeratu beste aplikazio bat"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikazioak edo erakundeak ez du eman ekintza hori gauzatzeko baimena"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Nabigazio-tutoriala saltatu nahi duzu?"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 879796a..6de4e90 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"نماگرفت"</string>
<string name="action_split" msgid="2098009717623550676">"دونیمه"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"زدن روی برنامهای دیگر برای استفاده از صفحه دونیمه"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"خروج از انتخاب صفحهٔ دونیمه"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"انتخاب برنامهای دیگر برای استفاده از صفحه دونیمه"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"برنامه یا سازمان شما اجازه نمیدهد این کنش انجام شود."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"آموزش گامبهگام پیمایش رد شود؟"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 02c4ad3..60d6618 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
<string name="action_split" msgid="2098009717623550676">"Jaa"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Avaa jaettu näyttö napauttamalla toista sovellusta"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Poistu jaetun näytön valinnasta"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Käytä jaettua näyttöä valitsemalla toinen sovellus"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Sovellus tai organisaatio ei salli tätä toimintoa"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ohitetaanko navigointiohje?"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index b280d48..a98e9c5 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
<string name="action_split" msgid="2098009717623550676">"Partager"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toucher une autre appli pour partager l\'écran"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Quitter la sélection d\'écran divisé"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Choisir une autre application pour utiliser l\'écran partagé"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"L\'application ou votre organisation n\'autorise pas cette action"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel sur la navigation?"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 868188b..2e2e0f1 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capture d\'écran"</string>
<string name="action_split" msgid="2098009717623550676">"Partager"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Appuyez sur autre appli pour l\'écran partagé"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Quitter la sélection de l\'écran partagé"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Sélect. autre appli pour utiliser l\'écran partagé"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Cette action n\'est pas autorisée par l\'application ou par votre organisation"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorer le tutoriel de navigation ?"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 8248aa1..11479e1 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Facer captura"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Para usar a pantalla dividida, toca outra app"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Saír da selección de pantalla dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Escolle outra app para usar a pantalla dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"A aplicación ou a túa organización non permite realizar esta acción"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Queres omitir o titorial de navegación?"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index db41a1e..ef44fb9 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
<string name="action_split" msgid="2098009717623550676">"વિભાજિત કરો"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"વિભાજિત સ્ક્રીન વાપરવા, કોઈ અન્ય ઍપ પર ટૅપ કરો"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"\'સ્ક્રીનને વિભાજિત કરો\' પસંદગીમાંથી બહાર નીકળો"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"સ્ક્રીન વિભાજનનો ઉપયોગ કરવા કોઈ અન્ય ઍપ પસંદ કરો"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ઍપ કે તમારી સંસ્થા દ્વારા આ ક્રિયા કરવાની મંજૂરી નથી"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"નૅવિગેશન ટ્યૂટૉરિઅલ છોડી દઈએ?"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 6affb00..28551ad 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट लें"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट स्क्रीन मोड"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"स्प्लिट स्क्रीन के लिए दूसरे ऐप्लिकेशन पर टैप करें"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"स्प्लिट स्क्रीन मोड से बाहर निकलें"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"स्प्लिट स्क्रीन के लिए, दूसरा ऐप्लिकेशन चुनें"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ऐप्लिकेशन या आपका संगठन इस कार्रवाई की अनुमति नहीं देता"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"क्या आपको अभी नेविगेशन ट्यूटोरियल नहीं देखना है?"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 6c9172f..abad768 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snimka zaslona"</string>
<string name="action_split" msgid="2098009717623550676">"Podijeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Dodirnite drugu aplikaciju za podijeljeni zaslon"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Zatvori odabir podijeljenog zaslona"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Odaberite drugu aplikaciju za upotrebu podijeljenog zaslona"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ili vaša organizacija ne dopuštaju ovu radnju"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite li preskočiti vodič za kretanje?"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 3f4ad18..16cd5f5 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Képernyőkép"</string>
<string name="action_split" msgid="2098009717623550676">"Felosztás"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Koppintson másik appra az osztott képernyőhöz"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Kilépés az osztott képernyő elemeinek kiválasztásából"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Válasszon másik appot a képernyő felosztásához"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Az alkalmazás vagy az Ön szervezete nem engedélyezi ezt a műveletet"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Kihagyja a navigáció bemutatóját?"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 1521c53..48eecd6 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -80,7 +80,7 @@
<string name="overview_gesture_tutorial_subtitle" msgid="5253549754058973071">"Մատը սահեցրեք էկրանի ներքևից վերև, պահեք և բաց թողեք"</string>
<string name="overview_gesture_tutorial_success" msgid="1910267697807973076">"Հիանալի՛ է"</string>
<string name="gesture_tutorial_confirm_title" msgid="6201516182040074092">"Պատրաստ է"</string>
- <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Պատրաստ է"</string>
+ <string name="gesture_tutorial_action_button_label" msgid="6249846312991332122">"Ավարտել"</string>
<string name="gesture_tutorial_action_button_label_settings" msgid="2923621047916486604">"Կարգավորումներ"</string>
<string name="gesture_tutorial_try_again" msgid="65962545858556697">"Նորից փորձեք"</string>
<string name="gesture_tutorial_nice" msgid="2936275692616928280">"Գերազանց է"</string>
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Սքրինշոթ անել"</string>
<string name="action_split" msgid="2098009717623550676">"Տրոհել"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Հպեք այլ հավելվածի՝ տրոհված էկրանից օգտվելու համար"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Դուրս գալ տրոհված էկրանի ռեժիմից"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Ընտրեք այլ հավելված՝ կիսված էկրանից օգտվելու համար"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Այս գործողությունն արգելված է հավելվածի կամ ձեր կազմակերպության կողմից"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Բաց թողնե՞լ նավիգացիայի ուղեցույցը"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 02fead4..2852fc0 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Pisahkan"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ketuk aplikasi lain untuk memakai layar terpisah"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Keluar dari pemilihan layar terpisah"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pilih aplikasi lain untuk memakai layar terpisah"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak diizinkan oleh aplikasi atau organisasi Anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Lewati tutorial gestur?"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 8b840ce..998c23f 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjámynd"</string>
<string name="action_split" msgid="2098009717623550676">"Skipta"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ýttu á annað forrit til að nota skjáskiptingu"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Loka skjáskiptingu"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Veldu annað forrit til að nota skjáskiptingu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Forritið eða fyrirtækið leyfir ekki þessa aðgerð"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Sleppa flettileiðsögn?"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index f5b4c5c..3755dbb 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Dividi"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tocca un\'altra app per usare lo schermo diviso"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Esci dalla selezione dello schermo diviso"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Scegli un\'altra app per usare lo schermo diviso"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Questa azione non è consentita dall\'app o dall\'organizzazione"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Saltare il tutorial di navigazione?"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 27b053a..2ec3cbf 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"צילום מסך"</string>
<string name="action_split" msgid="2098009717623550676">"פיצול"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"צריך להקיש על אפליקציה אחרת כדי להשתמש במסך מפוצל"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"יציאה מתצוגת מסך מפוצל"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"כדי להשתמש במסך מפוצל צריך לבחור אפליקציה אחרת"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"האפליקציה או הארגון שלך אינם מתירים את הפעולה הזאת"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"לדלג על המדריך לניווט?"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index f8ad440..7517f9d 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"スクリーンショット"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"分割画面を使用するには、他のアプリをタップします"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"分割画面の選択を終了します"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"分割画面にするには、別のアプリを選択してください"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"この操作はアプリまたは組織で許可されていません"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"操作チュートリアルをスキップしますか?"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 57b8947..64aa870 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ეკრანის ანაბეჭდი"</string>
<string name="action_split" msgid="2098009717623550676">"გაყოფა"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"შეეხეთ სხვა აპს ეკრანის გასაყოფად"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ეკრანის გაყოფის არჩევანიდან გასვლა"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"აირჩიეთ სხვა აპი ეკრანის გასაყოფად"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ეს მოქმედება არ არის დაშვებული აპის ან თქვენი ორგანიზაციის მიერ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"გსურთ, გამოტოვოთ ნავიგაციის სახელმძღვანელო?"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index cfdf461..cde0dfd 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Бөлу"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Экранды бөлу режимін пайдалану үшін басқа қолданбаны түртіңіз."</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Экранды бөлу режимінен шығу"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Экранды бөлу үшін басқа қолданбаны таңдаңыз."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Бұл әрекетке қолданба не ұйым рұқсат етпейді."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Қимылдар оқулығын өткізіп жіберу керек пе?"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 4f11f16..89d8335 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"រូបថតអេក្រង់"</string>
<string name="action_split" msgid="2098009717623550676">"បំបែក"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ចុចកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ចាកចេញពីការជ្រើសរើសរបស់មុខងារបំបែកអេក្រង់"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ជ្រើសរើសកម្មវិធីផ្សេងទៀត ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"សកម្មភាពនេះមិនត្រូវបានអនុញ្ញាតដោយកម្មវិធី ឬស្ថាប័នរបស់អ្នកទេ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"រំលងមេរៀនអំពីការរុករកឬ?"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index acf66a8..6c84e6f 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್ಶಾಟ್"</string>
<string name="action_split" msgid="2098009717623550676">"ವಿಭಜಿಸಿ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಲು ಬೇರೆ ಆ್ಯಪ್ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಆಯ್ಕೆಯಿಂದ ನಿರ್ಗಮಿಸಿ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"\"ಪರದೆ ಬೇರ್ಪಡಿಸಿ\" ಬಳಸಲು ಬೇರೆ ಆ್ಯಪ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ಆ್ಯಪ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಕ್ರಿಯೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ನ್ಯಾವಿಗೇಶನ್ ಟ್ಯುಟೋರಿಯಲ್ ಸ್ಕಿಪ್ ಮಾಡಬೇಕೇ?"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 9f44a35..c00eeed 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"스크린샷"</string>
<string name="action_split" msgid="2098009717623550676">"분할"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"다른 앱을 탭하여 화면 분할 사용"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"화면 분할 선택 종료"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"화면 분할을 사용하려면 다른 앱을 선택하세요."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"이 작업은 앱 또는 조직에서 허용되지 않습니다."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"이동 방법 튜토리얼을 건너뛰시겠습니까?"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 3b3f92f..f5d8782 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Бөлүү"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Экранды бөлүү үчүн башка колдонмону таптап коюңуз"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Тандалган экранды бөлүүдөн чыгуу"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Экранды бөлүү үчүн башка колдонмону тандаңыз"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Бул аракетти аткарууга колдонмо же ишканаңыз тыюу салган"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Жаңсоолор үйрөткүчүн өткөрүп жибересизби?"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 2ab0d74..2f67c30 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ຮູບໜ້າຈໍ"</string>
<string name="action_split" msgid="2098009717623550676">"ແບ່ງ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ແຕະແອັບອື່ນເພື່ອໃຊ້ໜ້າຈໍແຍກ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ອອກຈາກາກນເລືອກການແບ່ງໜ້າຈໍ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ເລືອກແອັບອື່ນເພື່ອໃຊ້ການແບ່ງໜ້າຈໍ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ແອັບ ຫຼື ອົງການຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ໃຊ້ຄຳສັ່ງນີ້"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ຂ້າມການສອນການນຳໃຊ້ການນຳທາງບໍ?"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 5dd1a3b..8bb1252 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekrano kopija"</string>
<string name="action_split" msgid="2098009717623550676">"Išskaidymo režimas"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Išskaidyto ekrano režimas palietus kitą programą"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Išeiti iš išskaidyto ekrano pasirinkimo"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Išskaidyto ekrano režimą naudokite kita programa"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Jūsų organizacijoje arba naudojant šią programą neleidžiama atlikti šio veiksmo"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Praleisti naršymo mokymo programą?"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index a69fe5f..a8bff55 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Veikt ekrānuzņēmumu"</string>
<string name="action_split" msgid="2098009717623550676">"Sadalīt"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Lai sadalītu ekrānu, pieskarieties citai lietotnei"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Izejiet no ekrāna sadalīšanas režīma atlases."</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Izvēlieties citu lietotni, lai sadalītu ekrānu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Lietotne vai jūsu organizācija neatļauj veikt šo darbību."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vai izlaist navigācijas mācības?"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index b3ee4ea..258a544 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Слика од екранот"</string>
<string name="action_split" msgid="2098009717623550676">"Раздели"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Допрете друга аплик. за да користите поделен екран"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Излези од изборот на поделен екран"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Изберете друга апликација за да користите поделен екран"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликацијата или вашата организација не го дозволува дејствово"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Да се прескокне упатството за навигација?"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 6d81f05..fffcd54 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"സ്ക്രീൻഷോട്ട്"</string>
<string name="action_split" msgid="2098009717623550676">"വിഭജിക്കുക"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"സ്പ്ലിറ്റ് സ്ക്രീനിന് മറ്റൊരു ആപ്പിൽ ടാപ്പ് ചെയ്യൂ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"സ്ക്രീൻ വിഭജന തിരഞ്ഞെടുപ്പിൽ നിന്ന് പുറത്തുകടക്കുക"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"സ്ക്രീൻ വിഭജന മോഡിന് മറ്റൊരു ആപ്പ് തിരഞ്ഞെടുക്കൂ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ഈ നടപടി എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"നാവിഗേഷൻ ട്യൂട്ടോറിയൽ ഒഴിവാക്കണോ?"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 703bf7b..8c7ae78 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Дэлгэцийн агшин дарах"</string>
<string name="action_split" msgid="2098009717623550676">"Хуваах"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Дэлгэцийг хуваахыг ашиглахын тулд өөр аппыг товш"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Дэлгэцийг хуваах сонголтоос гарах"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Дэлгэцийг хуваах горим ашиглах өөр апп сонгоно уу"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Энэ үйлдлийг апп эсвэл танай байгууллага зөвшөөрдөггүй"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Навигацын практик хичээлийг алгасах уу?"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 8cefec4..5bf47ce 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"स्प्लिट स्क्रीन वापरण्यासाठी दुसऱ्या ॲपवर टॅप करा"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"स्प्लिट स्क्रीन निवडीतून बाहेर पडा"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"स्प्लिट स्क्रीन वापरण्यासाठी दुसरे ॲप निवडा"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"अॅप किंवा तुमच्या संस्थेद्वारे ही क्रिया करण्याची अनुमती नाही"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेव्हिगेशन ट्यूटोरियल वगळायचे आहे का?"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 9ae478b..5e61b88 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Tangkapan skrin"</string>
<string name="action_split" msgid="2098009717623550676">"Pisah"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ketik apl lain untuk menggunakan skrin pisah"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Keluar daripada pilihan skrin pisah"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pilih apl lain untuk menggunakan skrin pisah"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Tindakan ini tidak dibenarkan oleh apl atau organisasi anda"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Langkau tutorial navigasi?"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index a2927d4..61b1c58 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
<string name="action_split" msgid="2098009717623550676">"ခွဲထုတ်ရန်"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"မျက်နှာပြင် ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"မျက်နှာပြင် ခွဲ၍ပြသခြင်း ရွေးချယ်မှုမှ ထွက်ရန်"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"မျက်နှာပြင်ခွဲ၍ပြသခြင်းသုံးရန် နောက်အက်ပ်တစ်ခုရွေးပါ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ဤလုပ်ဆောင်ချက်ကို အက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"လမ်းညွှန်ခြင်း ရှင်းလင်းပို့ချချက်ကို ကျော်မလား။"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index fe679e7..d4b8de9 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skjermdump"</string>
<string name="action_split" msgid="2098009717623550676">"Del opp"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Trykk på en annen app for å bruke delt skjerm"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Avslutt valg av delt skjerm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Velg en annen app for å bruke delt skjerm"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisasjonen din tillater ikke denne handlingen"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vil du hoppe over navigeringsveiledningen?"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 01b79d4..b326cb4 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"स्क्रिनसट"</string>
<string name="action_split" msgid="2098009717623550676">"स्प्लिट गर्नुहोस्"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"स्प्लिटस्क्रिन प्रयोग गर्न अर्को एपमा ट्याप गर्नु…"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"स्प्लिट स्क्रिन मोडबाट बाहिरिनुहोस्"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"स्प्लिट स्क्रिन प्रयोग गर्न अर्को एप रोज्नुहोस्"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"यो एप वा तपाईंको सङ्गठनले यो कारबाही गर्ने अनुमति दिँदैन"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेभिगेसन ट्युटोरियल स्किप गर्ने हो?"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 774a66c..91b5551 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Splitsen"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tik op nog een app om je scherm te splitsen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Sluit de selectie voor gesplitst scherm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Kies andere app om gesplitst scherm te gebruiken"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Deze actie wordt niet toegestaan door de app of je organisatie"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatietutorial overslaan?"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index ac45415..f0a5053 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ସ୍କ୍ରିନସଟ୍"</string>
<string name="action_split" msgid="2098009717623550676">"ସ୍ପ୍ଲିଟ୍"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ସ୍ପ୍ଲିଟସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପରେ ଟାପ କର"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ଚୟନରୁ ବାହାରି ଯାଆନ୍ତୁ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବାକୁ ଅନ୍ୟ ଏକ ଆପ ବାଛନ୍ତୁ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ଆପ୍ କିମ୍ବା ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ଏହି କାର୍ଯ୍ୟକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ନାଭିଗେସନ୍ ଟ୍ୟୁଟୋରିଆଲକୁ ବାଦ୍ ଦେବେ?"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index d0f17b0..c66e26f 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
<string name="action_split" msgid="2098009717623550676">"ਸਪਲਿਟ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਨੂੰ ਵਰਤਣ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਚੋਣ ਤੋਂ ਬਾਹਰ ਜਾਓ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਰਤਣ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ ਨੂੰ ਚੁਣੋ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਕਾਰਵਾਈ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ਕੀ ਨੈਵੀਗੇਸ਼ਨ ਟਿਊਟੋਰੀਅਲ ਨੂੰ ਛੱਡਣਾ ਹੈ?"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 5f609b2..7f0600f 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Zrzut ekranu"</string>
<string name="action_split" msgid="2098009717623550676">"Podziel"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Aby podzielić ekran, kliknij drugą aplikację"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Wyjdź z wyboru podzielonego ekranu"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Wybierz drugą aplikację, aby podzielić ekran"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Nie możesz wykonać tego działania, bo nie zezwala na to aplikacja lub Twoja organizacja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pominąć samouczek nawigacji?"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index a82f29a..791a127 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Fazer captura de ecrã"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toque noutra app para usar o ecrã dividido"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Saia da seleção de ecrã dividido"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Escolher outra app para usar o ecrã dividido"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Esta ação não é permitida pela app ou a sua entidade."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ignorar o tutorial de navegação?"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 8ff0a04..81d69f9 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Capturar tela"</string>
<string name="action_split" msgid="2098009717623550676">"Dividir"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Toque em outro app para usar a tela dividida"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Sair da seleção de tela dividida"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Escolha outro app para usar na tela dividida"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Essa ação não é permitida pelo app ou pela organização"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Pular o tutorial de navegação?"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 459abee..5db7859 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Captură de ecran"</string>
<string name="action_split" msgid="2098009717623550676">"Împărțit"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Atinge altă aplicație pentru ecranul împărțit"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ieși din selecția cu ecran împărțit"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Alege altă aplicație pentru ecranul împărțit"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Această acțiune nu este permisă de aplicație sau de organizația ta"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Omiți tutorialul de navigare?"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 2cece97..a11175e 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Скриншот"</string>
<string name="action_split" msgid="2098009717623550676">"Разделить"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Для разделения экрана выберите другое приложение."</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Выйдите из режима разделения экрана."</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Выберите другое приложение для разделения экрана."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Это действие заблокировано приложением или организацией."</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустить руководство по жестам?"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index b8d5110..3722b2f 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"තිර රුව"</string>
<string name="action_split" msgid="2098009717623550676">"බෙදන්න"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"බෙදුම් තිරය භාවිතා කිරීමට තවත් යෙදුමක් තට්ටු කරන්න"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"බෙදීම් තිර තේරීමෙන් පිටවන්න"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"බෙදීම් තිරය භාවිතා කිරීමට වෙනත් යෙදුමක් තෝරා ගන්න"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"මෙම ක්රියාව යෙදුම හෝ ඔබේ සංවිධානය මගින් ඉඩ නොදේ"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"නිබන්ධනය සංචාලනය මඟ හරින්නද?"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 11b091e..aee281c 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Snímka obrazovky"</string>
<string name="action_split" msgid="2098009717623550676">"Rozdeliť"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Obrazovku rozdelíte klepnutím na inú aplikáciu"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ukončite výber rozdelenej obrazovky"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Na použitie rozd. obrazovky vyberte inú aplikáciu"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikácia alebo vaša organizácia túto akciu nepovoľuje"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Chcete preskočiť návod na navigáciu?"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index a1b2021..4787f04 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Posnetek zaslona"</string>
<string name="action_split" msgid="2098009717623550676">"Razdeli"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Za razdeljeni zaslon se dotaknite še 1 aplikacije"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Zapri izbiro razdeljenega zaslona"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Izberite drugo aplikacijo za uporabo razdeljenega zaslona."</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Aplikacija ali vaša organizacija ne dovoljuje tega dejanja"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Želite preskočiti vadnico za krmarjenje?"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 392c7fd..a9e8b94 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Pamja e ekranit"</string>
<string name="action_split" msgid="2098009717623550676">"Ndaj"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Trokit një apl. tjetër; përdor ekranin e ndarë"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Dil nga zgjedhja e ekranit të ndarë"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Zgjidh një aplikacion tjetër për të përdorur ekranin e ndarë"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ky veprim nuk lejohet nga aplikacioni ose organizata jote"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Të kapërcehet udhëzuesi i navigimit?"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index cc12985..da057d8 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Снимак екрана"</string>
<string name="action_split" msgid="2098009717623550676">"Подели"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Додирните другу апликацију за подељени екран"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Излазак из бирања подељеног екрана"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Одаберите другу апликацију за подељени екран"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Апликација или организација не дозвољавају ову радњу"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Желите да прескочите водич за кретање?"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 6164140..31853f9 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skärmbild"</string>
<string name="action_split" msgid="2098009717623550676">"Delat"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Tryck på en annan app för att använda delad skärm"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Avsluta val av delad skärm"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Välj en annan app för att använda delad skärm"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Appen eller organisationen tillåter inte den här åtgärden"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Vill du hoppa över självstudierna?"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 5dbd510..8c438f4 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Picha ya skrini"</string>
<string name="action_split" msgid="2098009717623550676">"Iliyogawanywa"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Gusa programu nyingine ili utumie kipengele cha kugawa skrini"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ondoka kwenye hali ya skrini iliyogawanywa"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Chagua programu nyingine ili utumie hali ya kugawa skrini"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Kitendo hiki hakiruhusiwi na programu au shirika lako"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Ungependa kuruka mafunzo ya usogezaji?"</string>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 6846677..ef5bd3f 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ஸ்கிரீன்ஷாட்"</string>
<string name="action_split" msgid="2098009717623550676">"பிரி"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"திரைப் பிரிப்பைப் பயன்படுத்த வேறு ஆப்ஸைத் தட்டவும்"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"திரைப் பிரிப்பு தேர்வில் இருந்து வெளியேறும்"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"திரைப் பிரிப்பை பயன்படுத்த வேறு ஆப்ஸை தேர்வுசெய்க"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ஆப்ஸோ உங்கள் நிறுவனமோ இந்த செயலை அனுமதிப்பதில்லை"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"வழிகாட்டுதல் பயிற்சியைத் தவிர்க்கவா?"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index ddebce9..a2adfe1 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్షాట్"</string>
<string name="action_split" msgid="2098009717623550676">"స్ప్లిట్ చేయండి"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"స్ప్లిట్ స్క్రీన్ కోసం మరొక యాప్ను ట్యాప్ చేయండి"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"స్ప్లిట్ స్క్రీన్ ఎంపిక నుండి ఎగ్జిట్ అవ్వండి"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"స్ప్లిట్ స్క్రీన్ ఉపయోగానికి మరొక యాప్ ఎంచుకోండి"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ఈ చర్యను యాప్ గానీ, మీ సంస్థ గానీ అనుమతించవు"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"నావిగేషన్ ట్యుటోరియల్ను స్కిప్ చేయాలా?"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 2b9906e..0339046 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"ภาพหน้าจอ"</string>
<string name="action_split" msgid="2098009717623550676">"แยก"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"แตะแอปอื่นเพื่อใช้การแยกหน้าจอ"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"ออกจากการเลือกโหมดแยกหน้าจอ"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"เลือกแอปอื่นเพื่อใช้การแยกหน้าจอ"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"แอปหรือองค์กรของคุณไม่อนุญาตการดำเนินการนี้"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ข้ามบทแนะนำการนำทางไหม"</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index f1f3d3c..7bb38c2 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
<string name="action_split" msgid="2098009717623550676">"Split"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Mag-tap ng ibang app para gamitin ang split screen"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Lumabas sa pagpili ng split screen"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Pumili ng ibang app para gamitin ang split screen"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkilos na ito"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Laktawan ang tutorial sa pag-navigate?"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 242ee0c..905183a 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Ekran görüntüsü"</string>
<string name="action_split" msgid="2098009717623550676">"Böl"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Bölünmüş ekran için başka bir uygulamaya dokunun"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Bölünmüş ekran seçiminden çıkın"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Bölünmüş ekran kullanmak için başka bir uygulama seçin"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Uygulamanız veya kuruluşunuz bu işleme izin vermiyor"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Gezinme eğitimi atlansın mı?"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 011aadb..6cbf71f 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Знімок екрана"</string>
<string name="action_split" msgid="2098009717623550676">"Розділити"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Щоб розділити екран, виберіть ще один додаток"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Вийти з режиму розділення екрана"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Щоб розділити екран, виберіть ще один додаток"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ця дія заборонена додатком або адміністратором організації"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Пропустити посібник із навігації?"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 0d58d48..2392c6c 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
<string name="action_split" msgid="2098009717623550676">"اسپلٹ"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"اسپلٹ اسکرین کا استعمال کرنے کیلئے دوسری ایپ پر تھپتھپائیں"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"اسپلٹ اسکرین کے انتخاب سے باہر نکلیں"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"اسپلٹ اسکرین کے استعمال کیلئے دوسری ایپ منتخب کریں"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"ایپ یا آپ کی تنظیم کی جانب سے اس کارروائی کی اجازت نہیں ہے"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"نیویگیشن کا ٹیوٹوریل نظر انداز کریں؟"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index b450c6f..da2d363 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Skrinshot"</string>
<string name="action_split" msgid="2098009717623550676">"Ajratish"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Ekranni ikkiga ajratish uchun boshqa ilovani bosing"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Ekranni ikkiga ajratish tanlovidan chiqish"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Ekranni ikkiga ajratish uchun boshqa ilovani tanlang"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Bu amal ilova yoki tashkilotingiz tomonidan taqiqlangan"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Navigatsiya darsi yopilsinmi?"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 2f0e0b9..dae4212 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Chụp ảnh màn hình"</string>
<string name="action_split" msgid="2098009717623550676">"Chia đôi màn hình"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Nhấn vào ứng dụng khác để chia đôi màn hình"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Thoát khỏi lựa chọn chia đôi màn hình"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Chọn một ứng dụng khác để dùng chế độ chia đôi màn hình"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Ứng dụng hoặc tổ chức của bạn không cho phép thực hiện hành động này"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Bỏ qua phần hướng dẫn thao tác?"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 5db869d..e436ec1 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
<string name="action_split" msgid="2098009717623550676">"拆分"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"点按另一个应用即可使用分屏"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"退出分屏选择模式"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"另外选择一个应用才可使用分屏模式"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"该应用或您所在的单位不允许执行此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要跳过导航教程吗?"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 523ab65..0532ae5 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"輕按其他應用程式以使用分割螢幕"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"退出分割螢幕選取頁面"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"選擇其他應用程式才能使用分割螢幕"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"應用程式或你的機構不允許此操作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 06ff8e0..214fcfd 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"螢幕截圖"</string>
<string name="action_split" msgid="2098009717623550676">"分割"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"輕觸另一個應用程式即可使用分割畫面"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"退出分割畫面選擇器"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"必須選擇另一個應用程式才能使用分割畫面"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"這個應用程式或貴機構不允許執行這個動作"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"要略過手勢操作教學課程嗎?"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index fc9385f..9655a44 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -95,6 +95,7 @@
<string name="action_screenshot" msgid="8171125848358142917">"Isithombe-skrini"</string>
<string name="action_split" msgid="2098009717623550676">"Hlukanisa"</string>
<string name="toast_split_select_app" msgid="8464310533320556058">"Thepha enye i-app ukuze usebenzise isikrini sokuhlukanisa"</string>
+ <string name="toast_split_select_cont_desc" msgid="2119685056059607602">"Phuma ekukhetheni ukuhlukaniswa kwesikrini"</string>
<string name="toast_split_app_unsupported" msgid="2360229567007828914">"Khetha enye i-app ukuze usebenzise ukuhlukanisa isikrini"</string>
<string name="blocked_by_policy" msgid="2071401072261365546">"Lesi senzo asivunyelwanga uhlelo lokusebenza noma inhlangano yakho"</string>
<string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"Yeqa isifundo sokuzulazula?"</string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index b0e91a1..902e0c3 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -50,8 +50,10 @@
<!-- Overrideable in overlay that provides the Overview Actions. -->
<dimen name="overview_actions_top_margin">24dp</dimen>
- <dimen name="overview_actions_height">48dp</dimen>
+ <dimen name="overview_actions_size">60dp</dimen>
<dimen name="overview_actions_button_spacing">36dp</dimen>
+ <!-- 12dp + 156dp floating search pill width (note this is in addition to normal 36dp) -->
+ <dimen name="overview_actions_additional_floating_search_spacing">168dp</dimen>
<!-- These speeds are in dp/s -->
<dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
@@ -361,6 +363,7 @@
<dimen name="bubblebar_stashed_size">@dimen/transient_taskbar_stashed_height</dimen>
<dimen name="bubblebar_stashed_handle_height">@dimen/taskbar_stashed_handle_height</dimen>
<dimen name="bubblebar_pointer_size">8dp</dimen>
+ <dimen name="bubblebar_elevation">1dp</dimen>
<dimen name="bubblebar_icon_size">50dp</dimen>
<dimen name="bubblebar_badge_size">24dp</dimen>
@@ -369,6 +372,13 @@
<dimen name="bubblebar_icon_spacing">3dp</dimen>
<dimen name="bubblebar_icon_elevation">1dp</dimen>
+ <!-- Bubble bar dismiss view -->
+ <dimen name="bubblebar_dismiss_target_size">96dp</dimen>
+ <dimen name="bubblebar_dismiss_target_small_size">60dp</dimen>
+ <dimen name="bubblebar_dismiss_target_icon_size">24dp</dimen>
+ <dimen name="bubblebar_dismiss_target_bottom_margin">50dp</dimen>
+ <dimen name="bubblebar_dismiss_floating_gradient_height">548dp</dimen>
+
<!-- Launcher splash screen -->
<!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
<!-- starting_surface_exit_animation_window_shift_length -->
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index fc03704..0c4e782 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -221,15 +221,10 @@
<item name="android:colorControlHighlight">?attr/workspaceTextColor</item>
</style>
- <style name="OverviewActionButton"
- parent="@android:style/Widget.DeviceDefault.Button.Borderless">
- <item name="android:paddingTop">4dp</item>
- <item name="android:paddingBottom">4dp</item>
- <item name="android:textColor">@color/overview_button</item>
+ <style name="OverviewActionButton" parent="@android:style/Widget.DeviceDefault.ImageButton">
+ <item name="android:background">@drawable/circle_btn_bg</item>
+ <item name="android:backgroundTint">?androidprv:attr/materialColorSurfaceBright</item>
<item name="android:drawableTint">@color/overview_button</item>
- <item name="android:tint">?android:attr/textColorPrimary</item>
- <item name="android:drawablePadding">8dp</item>
- <item name="android:textAllCaps">false</item>
</style>
<style name="OverviewClearAllButton" parent="@android:style/Widget.DeviceDefault.Button">
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 4489eaf..110d275 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -183,7 +183,7 @@
private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
"android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS";
- private static final long APP_LAUNCH_DURATION = 500;
+ public static final long APP_LAUNCH_DURATION = 500;
private static final long APP_LAUNCH_ALPHA_DURATION = 50;
private static final long APP_LAUNCH_ALPHA_START_DELAY = 25;
@@ -286,7 +286,7 @@
mOpeningXInterpolator = AnimationUtils.loadInterpolator(context, R.interpolator.app_open_x);
mOpeningInterpolator = AnimationUtils.loadInterpolator(context,
- R.interpolator.three_point_fast_out_extra_slow_in);
+ R.interpolator.emphasized_interpolator);
}
@Override
@@ -1050,7 +1050,7 @@
boolean allowBlurringLauncher = mLauncher.getStateManager().getState() != OVERVIEW
&& BlurUtils.supportsBlursOnWindows();
- MyDepthController depthController = new MyDepthController(mLauncher);
+ LaunchDepthController depthController = new LaunchDepthController(mLauncher);
ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController.stateDepth,
MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mLauncher))
.setDuration(APP_LAUNCH_DURATION);
@@ -2051,11 +2051,14 @@
}
}
- private static class MyDepthController extends DepthController {
- MyDepthController(Launcher l) {
- super(l);
+ private static class LaunchDepthController extends DepthController {
+ LaunchDepthController(QuickstepLauncher launcher) {
+ super(launcher);
setCrossWindowBlursEnabled(
CrossWindowBlurListeners.getInstance().isCrossWindowBlurEnabled());
+ // Make sure that the starting value matches the current depth set by the main
+ // controller.
+ stateDepth.setValue(launcher.getDepthController().stateDepth.getValue());
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 42cb290..cb9c329 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -90,6 +90,8 @@
import com.android.launcher3.taskbar.bubbles.BubbleBarView;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
+import com.android.launcher3.taskbar.bubbles.BubbleDismissController;
+import com.android.launcher3.taskbar.bubbles.BubbleDragController;
import com.android.launcher3.taskbar.bubbles.BubbleStashController;
import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
@@ -216,7 +218,9 @@
new BubbleBarController(this, bubbleBarView),
new BubbleBarViewController(this, bubbleBarView),
new BubbleStashController(this),
- new BubbleStashedHandleViewController(this, bubbleHandleView)));
+ new BubbleStashedHandleViewController(this, bubbleHandleView),
+ new BubbleDragController(this),
+ new BubbleDismissController(this, mDragLayer)));
}
// Construct controllers.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 296e0db..90f7bea 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -204,7 +204,7 @@
updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false);
// TODO(b/279514548) Cleans up bad state that can occur when user interacts with
// taskbar on top of transparent activity.
- if (finalState == LauncherState.NORMAL && mLauncher.isResumed()) {
+ if (finalState == LauncherState.NORMAL && mLauncher.hasBeenResumed()) {
updateStateForFlag(FLAG_RESUMED, true);
}
applyState();
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 012a362..24db380 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -362,10 +362,9 @@
}
if (bubbleToSelect != null) {
setSelectedBubble(bubbleToSelect);
- }
-
- if (previouslySelectedBubble == null) {
- mBubbleStashController.animateToInitialState(update.expanded);
+ if (previouslySelectedBubble == null) {
+ mBubbleStashController.animateToInitialState(update.expanded);
+ }
}
if (update.expandedChanged) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index a8e6849..ffe077b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -95,6 +95,8 @@
private View.OnClickListener mOnClickListener;
private final Rect mTempRect = new Rect();
+ private float mRelativePivotX = 1f;
+ private float mRelativePivotY = 1f;
// An animator that represents the expansion state of the bubble bar, where 0 corresponds to the
// collapsed state and 1 to the fully expanded state.
@@ -109,6 +111,9 @@
@Nullable
private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
+ @Nullable
+ private BubbleView mDraggedBubbleView;
+
public BubbleBarView(Context context) {
this(context, null);
}
@@ -181,9 +186,10 @@
mBubbleBarBounds.right = right;
mBubbleBarBounds.bottom = bottom;
- // The bubble bar handle is aligned to the bottom edge of the screen so scale towards that.
- setPivotX(getWidth());
- setPivotY(getHeight());
+ // The bubble bar handle is aligned according to the relative pivot,
+ // by default it's aligned to the bottom edge of the screen so scale towards that
+ setPivotX(mRelativePivotX * getWidth());
+ setPivotY(mRelativePivotY * getHeight());
// Position the views
updateChildrenRenderNodeProperties();
@@ -198,6 +204,32 @@
return mBubbleBarBounds;
}
+ /**
+ * Set bubble bar relative pivot value for X and Y, applied as a fraction of view width/height
+ * respectively. If the value is not in range of 0 to 1 it will be normalized.
+ * @param x relative X pivot value in range 0..1
+ * @param y relative Y pivot value in range 0..1
+ */
+ public void setRelativePivot(float x, float y) {
+ mRelativePivotX = Float.max(Float.min(x, 1), 0);
+ mRelativePivotY = Float.max(Float.min(y, 1), 0);
+ requestLayout();
+ }
+
+ /**
+ * Get current relative pivot for X axis
+ */
+ public float getRelativePivotX() {
+ return mRelativePivotX;
+ }
+
+ /**
+ * Get current relative pivot for Y axis
+ */
+ public float getRelativePivotY() {
+ return mRelativePivotY;
+ }
+
// TODO: (b/280605790) animate it
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
@@ -254,9 +286,9 @@
// where the bubble will end up when the animation ends
final float targetX = currentWidth - expandedWidth + expandedX;
bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
- // if we're fully expanded, set the z level to 0
+ // if we're fully expanded, set the z level to 0 or to bubble elevation if dragged
if (widthState == 1f) {
- bv.setZ(0);
+ bv.setZ(bv == mDraggedBubbleView ? mBubbleElevation : 0);
}
// When we're expanded, we're not stacked so we're not behind the stack
bv.setBehindStack(false, animate);
@@ -332,6 +364,14 @@
}
/**
+ * Sets the dragged bubble view to correctly apply Z order. Dragged view should appear on top
+ */
+ public void setDraggedBubble(@Nullable BubbleView view) {
+ mDraggedBubbleView = view;
+ requestLayout();
+ }
+
+ /**
* Update the arrow position to match the selected bubble.
*
* @param shouldAnimate whether or not to animate the arrow. If the bar was just expanded, this
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index f5e2ddc..20b8e3b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -24,6 +24,8 @@
import android.view.View;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.TaskbarActivityContext;
@@ -54,6 +56,7 @@
// Initialized in init.
private BubbleStashController mBubbleStashController;
private BubbleBarController mBubbleBarController;
+ private BubbleDragController mBubbleDragController;
private TaskbarStashController mTaskbarStashController;
private TaskbarInsetsController mTaskbarInsetsController;
private View.OnClickListener mBubbleClickListener;
@@ -85,6 +88,7 @@
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
mBubbleStashController = bubbleControllers.bubbleStashController;
mBubbleBarController = bubbleControllers.bubbleBarController;
+ mBubbleDragController = bubbleControllers.bubbleDragController;
mTaskbarStashController = controllers.taskbarStashController;
mTaskbarInsetsController = controllers.taskbarInsetsController;
@@ -95,6 +99,7 @@
mBubbleBarScale.updateValue(1f);
mBubbleClickListener = v -> onBubbleClicked(v);
mBubbleBarClickListener = v -> setExpanded(true);
+ mBubbleDragController.setupBubbleBarView(mBarView);
mBarView.setOnClickListener(mBubbleBarClickListener);
mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
@@ -152,6 +157,11 @@
return mBarView.getBubbleBarBounds();
}
+ /** The horizontal margin of the bubble bar from the edge of the screen. */
+ public int getHorizontalMargin() {
+ return mBarView.getHorizontalMargin();
+ }
+
/**
* When the bubble bar is not stashed, it can be collapsed (the icons are in a stack) or
* expanded (the icons are in a row). This indicates whether the bubble bar is expanded.
@@ -263,6 +273,7 @@
if (b != null) {
mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
b.getView().setOnClickListener(mBubbleClickListener);
+ mBubbleDragController.setupBubbleView(b.getView());
} else {
Log.w(TAG, "addBubble, bubble was null!");
}
@@ -314,4 +325,46 @@
mBubbleStashController.showBubbleBar(true /* expand the bubbles */);
}
}
+
+ /**
+ * Updates the dragged bubble view in the bubble bar view, and notifies SystemUI
+ * that a bubble is being dragged to dismiss.
+ * @param bubbleView dragged bubble view
+ */
+ public void onDragStart(@NonNull BubbleView bubbleView) {
+ if (bubbleView.getBubble() == null) return;
+ mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ true);
+ mBarView.setDraggedBubble(bubbleView);
+ }
+
+ /**
+ * Notifies SystemUI to expand the selected bubble when the bubble is released.
+ * @param bubbleView dragged bubble view
+ */
+ public void onDragRelease(@NonNull BubbleView bubbleView) {
+ if (bubbleView.getBubble() == null) return;
+ mSystemUiProxy.onBubbleDrag(bubbleView.getBubble().getKey(), /* isBeingDragged = */ false);
+ }
+
+ /**
+ * Removes the dragged bubble view in the bubble bar view
+ */
+ public void onDragEnd() {
+ mBarView.setDraggedBubble(null);
+ }
+
+ /**
+ * Called when bubble was dragged into the dismiss target. Notifies System
+ * @param bubble dismissed bubble item
+ */
+ public void onDismissBubbleWhileDragging(@NonNull BubbleBarItem bubble) {
+ mSystemUiProxy.removeBubble(bubble.getKey());
+ }
+
+ /**
+ * Called when bubble stack was dragged into the dismiss target
+ */
+ public void onDismissAllBubblesWhileDragging() {
+ mSystemUiProxy.removeAllBubbles();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index 6417f3c..c47427d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -27,6 +27,8 @@
public final BubbleBarViewController bubbleBarViewController;
public final BubbleStashController bubbleStashController;
public final BubbleStashedHandleViewController bubbleStashedHandleViewController;
+ public final BubbleDragController bubbleDragController;
+ public final BubbleDismissController bubbleDismissController;
private final RunnableList mPostInitRunnables = new RunnableList();
@@ -39,11 +41,15 @@
BubbleBarController bubbleBarController,
BubbleBarViewController bubbleBarViewController,
BubbleStashController bubbleStashController,
- BubbleStashedHandleViewController bubbleStashedHandleViewController) {
+ BubbleStashedHandleViewController bubbleStashedHandleViewController,
+ BubbleDragController bubbleDragController,
+ BubbleDismissController bubbleDismissController) {
this.bubbleBarController = bubbleBarController;
this.bubbleBarViewController = bubbleBarViewController;
this.bubbleStashController = bubbleStashController;
this.bubbleStashedHandleViewController = bubbleStashedHandleViewController;
+ this.bubbleDragController = bubbleDragController;
+ this.bubbleDismissController = bubbleDismissController;
}
/**
@@ -56,6 +62,8 @@
bubbleBarViewController.init(taskbarControllers, this);
bubbleStashedHandleViewController.init(taskbarControllers, this);
bubbleStashController.init(taskbarControllers, this);
+ bubbleDragController.init(/* bubbleControllers = */ this);
+ bubbleDismissController.init(/* bubbleControllers = */ this);
mPostInitRunnables.executeAllAndDestroy();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
new file mode 100644
index 0000000..0ff0469
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
@@ -0,0 +1,212 @@
+/*
+ * 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.launcher3.taskbar.bubbles;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+
+import com.android.launcher3.R;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarDragLayer;
+import com.android.wm.shell.common.bubbles.DismissView;
+import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
+
+/**
+ * Controls dismiss view presentation for the bubble bar dismiss functionality.
+ * Provides the dragged view snapping to the target dismiss area and animates it.
+ * When the dragged bubble/bubble stack is released inside of the target area, it gets dismissed.
+ *
+ * @see BubbleDragController
+ */
+public class BubbleDismissController {
+ private static final String TAG = BubbleDismissController.class.getSimpleName();
+ private static final float FLING_TO_DISMISS_MIN_VELOCITY = 6000f;
+ // LINT.IfChange
+ private static final boolean ENABLE_FLING_TO_DISMISS_BUBBLE =
+ SystemProperties.getBoolean("persist.wm.debug.fling_to_dismiss_bubble", true);
+ // LINT.ThenChange(com/android/wm/shell/bubbles/BubbleStackView.java)
+ private final TaskbarActivityContext mActivity;
+ private final TaskbarDragLayer mDragLayer;
+ @Nullable
+ private BubbleBarViewController mBubbleBarViewController;
+
+ // Dismiss view that's attached to drag layer. It consists of the scrim view and the circular
+ // dismiss view used as a dismiss target.
+ @Nullable
+ private DismissView mDismissView;
+
+ // The currently magnetized object, which is being dragged and will be attracted to the magnetic
+ // dismiss target. This is either the stack itself, or an individual bubble.
+ @Nullable
+ private MagnetizedObject<View> mMagnetizedObject;
+
+ // The MagneticTarget instance for our circular dismiss view. This is added to the
+ // MagnetizedObject instances for the stack and any dragged-out bubbles.
+ @Nullable
+ private MagnetizedObject.MagneticTarget mMagneticTarget;
+
+ // The bubble drag animator that synchronizes bubble drag and dismiss view animations
+ // A new instance is provided when the dismiss view is setup
+ @Nullable
+ private BubbleDragAnimator mAnimator;
+
+ public BubbleDismissController(TaskbarActivityContext activity, TaskbarDragLayer dragLayer) {
+ mActivity = activity;
+ mDragLayer = dragLayer;
+ }
+
+ /**
+ * Initializes dependencies when bubble controllers are created.
+ * Should be careful to only access things that were created in constructors for now, as some
+ * controllers may still be waiting for init().
+ */
+ public void init(@NonNull BubbleControllers bubbleControllers) {
+ mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
+ }
+
+ /**
+ * Setup the dismiss view and magnetized object that will be attracted to magnetic target.
+ * Should be called before handling events or showing/hiding dismiss view.
+ *
+ * @param magnetizedView the view to be pulled into target dismiss area
+ * @param animator the bubble animator to be used for the magnetized view, it syncs bubble
+ * dragging and dismiss animations with the dismiss view provided.
+ */
+ public void setupDismissView(@NonNull View magnetizedView,
+ @NonNull BubbleDragAnimator animator) {
+ setupDismissView();
+ setupMagnetizedObject(magnetizedView);
+ if (mDismissView != null) {
+ animator.setDismissView(mDismissView);
+ mAnimator = animator;
+ }
+ }
+
+ /**
+ * Handle the touch event and pass it to the magnetized object.
+ * It should be called after {@code setupDismissView}
+ */
+ public boolean handleTouchEvent(@NonNull MotionEvent event) {
+ return mMagnetizedObject != null && mMagnetizedObject.maybeConsumeMotionEvent(event);
+ }
+
+ /**
+ * Show dismiss view with animation
+ * It should be called after {@code setupDismissView}
+ */
+ public void showDismissView() {
+ if (mDismissView == null) return;
+ mDismissView.show();
+ }
+
+ /**
+ * Hide dismiss view with animation
+ * It should be called after {@code setupDismissView}
+ */
+ public void hideDismissView() {
+ if (mDismissView == null) return;
+ mDismissView.hide();
+ }
+
+ /**
+ * Dismiss magnetized object when it's released in the dismiss target area
+ */
+ private void dismissMagnetizedObject() {
+ if (mMagnetizedObject == null || mBubbleBarViewController == null) return;
+ if (mMagnetizedObject.getUnderlyingObject() instanceof BubbleView) {
+ BubbleView bubbleView = (BubbleView) mMagnetizedObject.getUnderlyingObject();
+ if (bubbleView.getBubble() != null) {
+ mBubbleBarViewController.onDismissBubbleWhileDragging(bubbleView.getBubble());
+ }
+ } else if (mMagnetizedObject.getUnderlyingObject() instanceof BubbleBarView) {
+ mBubbleBarViewController.onDismissAllBubblesWhileDragging();
+ }
+ }
+
+ private void setupDismissView() {
+ if (mDismissView != null) return;
+ mDismissView = new DismissView(mActivity.getApplicationContext());
+ BubbleDismissViewUtils.setup(mDismissView);
+ mDragLayer.addView(mDismissView, /* index = */ 0,
+ new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+ mDismissView.setElevation(mDismissView.getResources().getDimensionPixelSize(
+ R.dimen.bubblebar_elevation));
+ setupMagneticTarget(mDismissView.getCircle());
+ }
+
+ private void setupMagneticTarget(@NonNull View view) {
+ int magneticFieldRadius = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.bubblebar_dismiss_target_size);
+ mMagneticTarget = new MagnetizedObject.MagneticTarget(view, magneticFieldRadius);
+ }
+
+ private void setupMagnetizedObject(@NonNull View magnetizedView) {
+ mMagnetizedObject = new MagnetizedObject<>(mActivity.getApplicationContext(),
+ magnetizedView, DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y) {
+ @Override
+ public float getWidth(@NonNull View underlyingObject) {
+ return underlyingObject.getWidth() * underlyingObject.getScaleX();
+ }
+
+ @Override
+ public float getHeight(@NonNull View underlyingObject) {
+ return underlyingObject.getHeight() * underlyingObject.getScaleY();
+ }
+
+ @Override
+ public void getLocationOnScreen(@NonNull View underlyingObject, @NonNull int[] loc) {
+ underlyingObject.getLocationOnScreen(loc);
+ }
+ };
+
+ mMagnetizedObject.setHapticsEnabled(true);
+ mMagnetizedObject.setFlingToTargetEnabled(ENABLE_FLING_TO_DISMISS_BUBBLE);
+ mMagnetizedObject.setFlingToTargetMinVelocity(FLING_TO_DISMISS_MIN_VELOCITY);
+ if (mMagneticTarget != null) {
+ mMagnetizedObject.addTarget(mMagneticTarget);
+ } else {
+ Log.e(TAG,"Requires MagneticTarget to add target to MagnetizedObject!");
+ }
+ mMagnetizedObject.setMagnetListener(new MagnetizedObject.MagnetListener() {
+ @Override
+ public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ if (mAnimator == null) return;
+ mAnimator.animateDismissCaptured();
+ }
+
+ @Override
+ public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
+ float velX, float velY, boolean wasFlungOut) {
+ if (mAnimator == null) return;
+ mAnimator.animateDismissReleased();
+ }
+
+ @Override
+ public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ dismissMagnetizedObject();
+ }
+ });
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissViewExt.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissViewExt.kt
new file mode 100644
index 0000000..4b235a9
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissViewExt.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+@file:JvmName("BubbleDismissViewUtils")
+
+package com.android.launcher3.taskbar.bubbles
+
+import com.android.launcher3.R
+import com.android.wm.shell.common.bubbles.DismissView
+
+/**
+ * Dismiss view is shared from WMShell. It requires setup with local resources.
+ *
+ * Usage:
+ * - Kotlin `dismissView.setup()`
+ * - Java `BubbleDismissViewUtils.setup(dismissView)`
+ */
+fun DismissView.setup() {
+ setup(
+ DismissView.Config(
+ targetSizeResId = R.dimen.bubblebar_dismiss_target_size,
+ iconSizeResId = R.dimen.bubblebar_dismiss_target_icon_size,
+ bottomMarginResId = R.dimen.bubblebar_dismiss_target_bottom_margin,
+ floatingGradientHeightResId = R.dimen.bubblebar_dismiss_floating_gradient_height,
+ floatingGradientColorResId = android.R.color.system_neutral1_900,
+ backgroundResId = R.drawable.bg_bubble_dismiss_circle,
+ iconResId = R.drawable.ic_bubble_dismiss_white
+ )
+ )
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
new file mode 100644
index 0000000..24dca5e
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
@@ -0,0 +1,222 @@
+/*
+ * 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.launcher3.taskbar.bubbles;
+
+import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY;
+import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW;
+import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
+
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.FloatPropertyCompat;
+
+import com.android.launcher3.R;
+import com.android.wm.shell.animation.PhysicsAnimator;
+import com.android.wm.shell.common.bubbles.DismissCircleView;
+import com.android.wm.shell.common.bubbles.DismissView;
+
+/**
+ * The animator performs the bubble animations while dragging and coordinates bubble and dismiss
+ * view animations when it gets magnetized, released or dismissed.
+ */
+public class BubbleDragAnimator {
+ private static final float SCALE_BUBBLE_FOCUSED = 1.2f;
+ private static final float SCALE_BUBBLE_CAPTURED = 0.9f;
+ private static final float SCALE_BUBBLE_BAR_FOCUSED = 1.1f;
+
+ private final PhysicsAnimator.SpringConfig mDefaultConfig =
+ new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY);
+ private final PhysicsAnimator.SpringConfig mTranslationConfig =
+ new PhysicsAnimator.SpringConfig(STIFFNESS_MEDIUM, DAMPING_RATIO_LOW_BOUNCY);
+ @NonNull
+ private final View mView;
+ @NonNull
+ private final PhysicsAnimator<View> mBubbleAnimator;
+ @Nullable
+ private DismissView mDismissView;
+ @Nullable
+ private PhysicsAnimator<DismissCircleView> mDismissAnimator;
+ private final float mBubbleFocusedScale;
+ private final float mBubbleCapturedScale;
+ private final float mDismissCapturedScale;
+
+ /**
+ * Should be initialised for each dragged view
+ *
+ * @param view the dragged view to animate
+ */
+ public BubbleDragAnimator(@NonNull View view) {
+ mView = view;
+ mBubbleAnimator = PhysicsAnimator.getInstance(view);
+ mBubbleAnimator.setDefaultSpringConfig(mDefaultConfig);
+
+ Resources resources = view.getResources();
+ final int collapsedSize = resources.getDimensionPixelSize(
+ R.dimen.bubblebar_dismiss_target_small_size);
+ final int expandedSize = resources.getDimensionPixelSize(
+ R.dimen.bubblebar_dismiss_target_size);
+ mDismissCapturedScale = (float) collapsedSize / expandedSize;
+
+ if (view instanceof BubbleBarView) {
+ mBubbleFocusedScale = SCALE_BUBBLE_BAR_FOCUSED;
+ mBubbleCapturedScale = mDismissCapturedScale;
+ } else {
+ mBubbleFocusedScale = SCALE_BUBBLE_FOCUSED;
+ mBubbleCapturedScale = SCALE_BUBBLE_CAPTURED;
+ }
+ }
+
+ /**
+ * Sets dismiss view to be animated alongside the dragged bubble
+ */
+ public void setDismissView(@NonNull DismissView dismissView) {
+ mDismissView = dismissView;
+ mDismissAnimator = PhysicsAnimator.getInstance(dismissView.getCircle());
+ mDismissAnimator.setDefaultSpringConfig(mDefaultConfig);
+ }
+
+ /**
+ * Animates the focused state of the bubble when the dragging starts
+ */
+ public void animateFocused() {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, mBubbleFocusedScale)
+ .spring(DynamicAnimation.SCALE_Y, mBubbleFocusedScale)
+ .start();
+ }
+
+ /**
+ * Animates the dragged bubble movement back to the initial position.
+ *
+ * @param initialPosition the position to animate to
+ * @param velocity the initial velocity to use for the spring animation
+ * @param endActions gets called when the animation completes or gets cancelled
+ */
+ public void animateToInitialState(@NonNull PointF initialPosition, @NonNull PointF velocity,
+ @Nullable Runnable endActions) {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, 1f)
+ .spring(DynamicAnimation.SCALE_Y, 1f)
+ .spring(DynamicAnimation.TRANSLATION_X, initialPosition.x, velocity.x,
+ mTranslationConfig)
+ .spring(DynamicAnimation.TRANSLATION_Y, initialPosition.y, velocity.y,
+ mTranslationConfig)
+ .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property,
+ boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
+ boolean allRelevantPropertyAnimationsEnded) -> {
+ if (canceled || allRelevantPropertyAnimationsEnded) {
+ resetAnimatedViews(initialPosition);
+ if (endActions != null) {
+ endActions.run();
+ }
+ }
+ })
+ .start();
+ }
+
+ /**
+ * Animates the dragged view alongside the dismiss view when it gets captured in the dismiss
+ * target area.
+ */
+ public void animateDismissCaptured() {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, mBubbleCapturedScale)
+ .spring(DynamicAnimation.SCALE_Y, mBubbleCapturedScale)
+ .spring(DynamicAnimation.ALPHA, mDismissCapturedScale)
+ .start();
+
+ if (mDismissAnimator != null) {
+ mDismissAnimator.cancel();
+ mDismissAnimator
+ .spring(DynamicAnimation.SCALE_X, mDismissCapturedScale)
+ .spring(DynamicAnimation.SCALE_Y, mDismissCapturedScale)
+ .start();
+ }
+ }
+
+ /**
+ * Animates the dragged view alongside the dismiss view when it gets released from the dismiss
+ * target area.
+ */
+ public void animateDismissReleased() {
+ mBubbleAnimator.cancel();
+ mBubbleAnimator
+ .spring(DynamicAnimation.SCALE_X, mBubbleFocusedScale)
+ .spring(DynamicAnimation.SCALE_Y, mBubbleFocusedScale)
+ .spring(DynamicAnimation.ALPHA, 1f)
+ .start();
+
+ if (mDismissAnimator != null) {
+ mDismissAnimator.cancel();
+ mDismissAnimator
+ .spring(DynamicAnimation.SCALE_X, 1f)
+ .spring(DynamicAnimation.SCALE_Y, 1f)
+ .start();
+ }
+ }
+
+ /**
+ * Animates the dragged bubble dismiss when it's released in the dismiss target area.
+ *
+ * @param initialPosition the initial position to move the bubble too after animation finishes
+ * @param endActions gets called when the animation completes or gets cancelled
+ */
+ public void animateDismiss(@NonNull PointF initialPosition, @Nullable Runnable endActions) {
+ float dismissHeight = mDismissView != null ? mDismissView.getHeight() : 0f;
+ float translationY = mView.getTranslationY() + dismissHeight;
+ mBubbleAnimator
+ .spring(DynamicAnimation.TRANSLATION_Y, translationY)
+ .spring(DynamicAnimation.SCALE_X, 0f)
+ .spring(DynamicAnimation.SCALE_Y, 0f)
+ .spring(DynamicAnimation.ALPHA, 0f)
+ .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property,
+ boolean wasFling, boolean canceled, float finalValue, float finalVelocity,
+ boolean allRelevantPropertyAnimationsEnded) -> {
+ if (canceled || allRelevantPropertyAnimationsEnded) {
+ resetAnimatedViews(initialPosition);
+ if (endActions != null) endActions.run();
+ }
+ })
+ .start();
+ }
+
+ /**
+ * Reset the animated views to the initial state
+ *
+ * @param initialPosition position of the bubble
+ */
+ private void resetAnimatedViews(@NonNull PointF initialPosition) {
+ mView.setScaleX(1f);
+ mView.setScaleY(1f);
+ mView.setAlpha(1f);
+ mView.setTranslationX(initialPosition.x);
+ mView.setTranslationY(initialPosition.y);
+
+ if (mDismissView != null) {
+ mDismissView.getCircle().setScaleX(1f);
+ mDismissView.getCircle().setScaleY(1f);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
new file mode 100644
index 0000000..08fd681
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
@@ -0,0 +1,355 @@
+/*
+ * 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.launcher3.taskbar.bubbles;
+
+import android.annotation.SuppressLint;
+import android.graphics.PointF;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+
+/**
+ * Controls bubble bar drag to dismiss interaction.
+ * Interacts with {@link BubbleDismissController}, used by {@link BubbleBarViewController}.
+ * Supported interactions:
+ * - Drag a single bubble view into dismiss target to remove it.
+ * - Drag the bubble stack into dismiss target to remove all.
+ * Restores initial position of dragged view if released outside of the dismiss target.
+ */
+public class BubbleDragController {
+ private final TaskbarActivityContext mActivity;
+ private BubbleBarViewController mBubbleBarViewController;
+ private BubbleDismissController mBubbleDismissController;
+
+ public BubbleDragController(TaskbarActivityContext activity) {
+ mActivity = activity;
+ }
+
+ /**
+ * Initializes dependencies when bubble controllers are created.
+ * Should be careful to only access things that were created in constructors for now, as some
+ * controllers may still be waiting for init().
+ */
+ public void init(@NonNull BubbleControllers bubbleControllers) {
+ mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
+ mBubbleDismissController = bubbleControllers.bubbleDismissController;
+ }
+
+ /**
+ * Setup the bubble view for dragging and attach touch listener to it
+ */
+ @SuppressLint("ClickableViewAccessibility")
+ public void setupBubbleView(@NonNull BubbleView bubbleView) {
+ if (!(bubbleView.getBubble() instanceof BubbleBarBubble)) {
+ // Don't setup dragging for overflow bubble view
+ return;
+ }
+
+ bubbleView.setOnTouchListener(new BubbleTouchListener() {
+ @Override
+ void onDragStart() {
+ mBubbleBarViewController.onDragStart(bubbleView);
+ }
+
+ @Override
+ void onDragEnd() {
+ mBubbleBarViewController.onDragEnd();
+ }
+
+ @Override
+ protected void onDragRelease() {
+ mBubbleBarViewController.onDragRelease(bubbleView);
+ }
+ });
+ }
+
+ /**
+ * Setup the bubble bar view for dragging and attach touch listener to it
+ */
+ @SuppressLint("ClickableViewAccessibility")
+ public void setupBubbleBarView(@NonNull BubbleBarView bubbleBarView) {
+ PointF initialRelativePivot = new PointF();
+ bubbleBarView.setOnTouchListener(new BubbleTouchListener() {
+ @Override
+ protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
+ if (bubbleBarView.isExpanded()) return false;
+ return super.onTouchDown(view, event);
+ }
+
+ @Override
+ void onDragStart() {
+ initialRelativePivot.set(bubbleBarView.getRelativePivotX(),
+ bubbleBarView.getRelativePivotY());
+ // By default the bubble bar view pivot is in bottom right corner, while dragging
+ // it should be centered in order to align it with the dismiss target view
+ bubbleBarView.setRelativePivot(/* x = */ 0.5f, /* y = */ 0.5f);
+ }
+
+ @Override
+ void onDragEnd() {
+ // Restoring the initial pivot for the bubble bar view
+ bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
+ }
+ });
+ }
+
+ /**
+ * Bubble touch listener for handling a single bubble view or bubble bar view while dragging.
+ * The dragging starts after "shorter" long click (the long click duration might change):
+ * - When the touch gesture moves out of the {@code ACTION_DOWN} location the dragging
+ * interaction is cancelled.
+ * - When {@code ACTION_UP} happens before long click is registered and there was no significant
+ * movement the view will perform click.
+ * - When the listener registers long click it starts dragging interaction, all the subsequent
+ * {@code ACTION_MOVE} events will drag the view, and the interaction finishes when
+ * {@code ACTION_UP} or {@code ACTION_CANCEL} are received.
+ * Lifecycle methods can be overridden do add extra setup/clean up steps.
+ */
+ private abstract class BubbleTouchListener implements View.OnTouchListener {
+ /**
+ * The internal state of the touch listener
+ */
+ private enum State {
+ // Idle and ready for the touch events.
+ // Changes to:
+ // - TOUCHED, when the {@code ACTION_DOWN} is handled
+ IDLE,
+
+ // Touch down was handled and the lister is recognising the gestures.
+ // Changes to:
+ // - IDLE, when performs the click
+ // - DRAGGING, when registers the long click and starts dragging interaction
+ // - CANCELLED, when the touch events move out of the initial location before the long
+ // click is recognised
+
+ TOUCHED,
+
+ // The long click was registered and the view is being dragged.
+ // Changes to:
+ // - IDLE, when the gesture ends with the {@code ACTION_UP} or {@code ACTION_CANCEL}
+ DRAGGING,
+
+ // The dragging was cancelled.
+ // Changes to:
+ // - IDLE, when the current gesture completes
+ CANCELLED
+ }
+
+ private final PointF mTouchDownLocation = new PointF();
+ private final PointF mViewInitialPosition = new PointF();
+ private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
+ private final long mPressToDragTimeout = ViewConfiguration.getLongPressTimeout() / 2;
+ private State mState = State.IDLE;
+ private int mTouchSlop = -1;
+ private BubbleDragAnimator mAnimator;
+ @Nullable
+ private Runnable mLongClickRunnable;
+
+ /**
+ * Called when the dragging interaction has started
+ */
+ abstract void onDragStart();
+
+ /**
+ * Called when the dragging interaction has ended and all the animations have completed
+ */
+ abstract void onDragEnd();
+
+ /**
+ * Called when the dragged bubble is released outside of the dismiss target area and will
+ * move back to its initial position
+ */
+ protected void onDragRelease() {
+ }
+
+ /**
+ * Called when the dragged bubble is released inside of the dismiss target area and will get
+ * dismissed with animation
+ */
+ protected void onDragDismiss() {
+ }
+
+ @Override
+ @SuppressLint("ClickableViewAccessibility")
+ public boolean onTouch(@NonNull View view, @NonNull MotionEvent event) {
+ updateVelocity(event);
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ return onTouchDown(view, event);
+ case MotionEvent.ACTION_MOVE:
+ onTouchMove(view, event);
+ break;
+ case MotionEvent.ACTION_UP:
+ onTouchUp(view, event);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ onTouchCancel(view, event);
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * The touch down starts the interaction and schedules the long click handler.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ * @return true if the gesture should be intercepted and handled, false otherwise. Note if
+ * the false is returned subsequent events in the gesture won't get reported.
+ */
+ protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
+ mState = State.TOUCHED;
+ mTouchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
+ mTouchDownLocation.set(event.getRawX(), event.getRawY());
+ mViewInitialPosition.set(view.getTranslationX(), view.getTranslationY());
+ setupLongClickHandler(view);
+ return true;
+ }
+
+ /**
+ * The move event drags the view or cancels the interaction if hasn't long clicked yet.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ */
+ protected void onTouchMove(@NonNull View view, @NonNull MotionEvent event) {
+ final float dx = event.getRawX() - mTouchDownLocation.x;
+ final float dy = event.getRawY() - mTouchDownLocation.y;
+ switch (mState) {
+ case TOUCHED:
+ final boolean movedOut = Math.hypot(dx, dy) > mTouchSlop;
+ if (movedOut) {
+ // Moved out of the initial location before the long click was registered
+ mState = State.CANCELLED;
+ cleanUpLongClickHandler(view);
+ }
+ break;
+ case DRAGGING:
+ drag(view, event, dx, dy);
+ break;
+ }
+ }
+
+ /**
+ * On touch up performs click or finishes the dragging depending on the state.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ */
+ protected void onTouchUp(@NonNull View view, @NonNull MotionEvent event) {
+ switch (mState) {
+ case TOUCHED:
+ view.performClick();
+ cleanUp(view);
+ break;
+ case DRAGGING:
+ stopDragging(view, event);
+ break;
+ default:
+ cleanUp(view);
+ break;
+ }
+ }
+
+ /**
+ * The gesture is cancelled and the interaction should clean up and complete.
+ *
+ * @param view the view that received the event
+ * @param event the motion event
+ */
+ protected void onTouchCancel(@NonNull View view, @NonNull MotionEvent event) {
+ if (mState == State.DRAGGING) {
+ stopDragging(view, event);
+ } else {
+ cleanUp(view);
+ }
+ }
+
+ private void startDragging(@NonNull View view) {
+ onDragStart();
+ mActivity.setTaskbarWindowFullscreen(true);
+ mAnimator = new BubbleDragAnimator(view);
+ mAnimator.animateFocused();
+ mBubbleDismissController.setupDismissView(view, mAnimator);
+ mBubbleDismissController.showDismissView();
+ }
+
+ private void drag(@NonNull View view, @NonNull MotionEvent event, float dx, float dy) {
+ if (mBubbleDismissController.handleTouchEvent(event)) return;
+ view.setTranslationX(mViewInitialPosition.x + dx);
+ view.setTranslationY(mViewInitialPosition.y + dy);
+ }
+
+ private void stopDragging(@NonNull View view, @NonNull MotionEvent event) {
+ Runnable onComplete = () -> {
+ mActivity.setTaskbarWindowFullscreen(false);
+ cleanUp(view);
+ onDragEnd();
+ };
+
+ if (mBubbleDismissController.handleTouchEvent(event)) {
+ onDragDismiss();
+ mAnimator.animateDismiss(mViewInitialPosition, onComplete);
+ } else {
+ onDragRelease();
+ mAnimator.animateToInitialState(mViewInitialPosition, getCurrentVelocity(),
+ onComplete);
+ }
+ mBubbleDismissController.hideDismissView();
+ }
+
+ private void setupLongClickHandler(@NonNull View view) {
+ cleanUpLongClickHandler(view);
+ mLongClickRunnable = () -> {
+ // Register long click and start dragging interaction
+ mState = State.DRAGGING;
+ startDragging(view);
+ };
+ view.getHandler().postDelayed(mLongClickRunnable, mPressToDragTimeout);
+ }
+
+ private void cleanUpLongClickHandler(@NonNull View view) {
+ if (mLongClickRunnable == null || view.getHandler() == null) return;
+ view.getHandler().removeCallbacks(mLongClickRunnable);
+ mLongClickRunnable = null;
+ }
+
+ private void cleanUp(@NonNull View view) {
+ cleanUpLongClickHandler(view);
+ mVelocityTracker.clear();
+ mState = State.IDLE;
+ }
+
+ private void updateVelocity(MotionEvent event) {
+ final float deltaX = event.getRawX() - event.getX();
+ final float deltaY = event.getRawY() - event.getY();
+ event.offsetLocation(deltaX, deltaY);
+ mVelocityTracker.addMovement(event);
+ event.offsetLocation(-deltaX, -deltaY);
+ }
+
+ private PointF getCurrentVelocity() {
+ mVelocityTracker.computeCurrentVelocity(/* units = */ 1000);
+ return new PointF(mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index a267211..00c2ca1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -201,7 +201,7 @@
public void onSysuiLockedStateChange(boolean isSysuiLocked) {
if (isSysuiLocked != mIsSysuiLocked) {
mIsSysuiLocked = isSysuiLocked;
- if (!mIsSysuiLocked) {
+ if (!mIsSysuiLocked && mBarViewController.hasBubbles()) {
animateToInitialState(false /* expanding */);
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 4c197f6..fbab595 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -123,13 +123,15 @@
private void updateBounds() {
// As more bubbles get added, the icon bounds become larger. To ensure a consistent
// handle bar position, we pin it to the edge of the screen.
- Rect bubblebarRect = mBarViewController.getBubbleBarBounds();
+ final int right =
+ mActivity.getDeviceProfile().widthPx - mBarViewController.getHorizontalMargin();
+
final int stashedCenterY = mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2;
mStashedHandleBounds.set(
- bubblebarRect.right - mStashedHandleWidth,
+ right - mStashedHandleWidth,
stashedCenterY - mStashedHandleHeight / 2,
- bubblebarRect.right,
+ right,
stashedCenterY + mStashedHandleHeight / 2);
mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
@@ -240,9 +242,6 @@
*/
public Animator createRevealAnimToIsStashed(boolean isStashed) {
Rect bubbleBarBounds = new Rect(mBarViewController.getBubbleBarBounds());
- // the bubble bar may have been invisible when the bounds were previously calculated,
- // update them again to ensure they're correct.
- updateBounds();
// Account for the full visual height of the bubble bar
int heightDiff = (mBarSize - bubbleBarBounds.height()) / 2;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index ffd22b8..1e1bff3 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -664,6 +664,8 @@
@Override
public void onAnimationCancel(Animator animation) {
getDragLayer().removeView(floatingTaskView);
+ mSplitSelectStateController.getSplitAnimationController()
+ .removeSplitInstructionsView(QuickstepLauncher.this);
mSplitSelectStateController.resetState();
}
});
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 396d0ab..fecdd79 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -125,8 +125,33 @@
@Override
public int getFloatingSearchBarRestingMarginBottom(Launcher launcher) {
- return areElementsVisible(launcher, FLOATING_SEARCH_BAR) ? 0
- : super.getFloatingSearchBarRestingMarginBottom(launcher);
+ if (!areElementsVisible(launcher, FLOATING_SEARCH_BAR)) {
+ return super.getFloatingSearchBarRestingMarginBottom(launcher);
+ }
+ RecentsView recentsView = launcher.getOverviewPanel();
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int activeTaskMarginBottom = LayoutUtils.getShelfTrackingDistance(launcher, dp,
+ recentsView.getPagedOrientationHandler());
+ // Center between task bottom and bottom of the screen.
+ return (activeTaskMarginBottom - dp.overviewActionsHeight) / 2
+ - launcher.getResources().getDimensionPixelSize(R.dimen.qsb_shadow_height);
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginStart(Launcher launcher) {
+ return getFloatingSearchBarRestingMarginHorizontal(launcher);
+ }
+
+ @Override
+ public int getFloatingSearchBarRestingMarginEnd(Launcher launcher) {
+ return getFloatingSearchBarRestingMarginHorizontal(launcher);
+ }
+
+ private static int getFloatingSearchBarRestingMarginHorizontal(Launcher launcher) {
+ // Width if the search bar were to be expanded (focused).
+ int expandedWidth = launcher.getResources().getDimensionPixelSize(
+ R.dimen.overview_floating_search_width);
+ return (launcher.getDeviceProfile().widthPx - expandedWidth) / 2;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index d3ef589..6f421eb 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.uioverrides.touchcontrollers;
import static android.view.MotionEvent.ACTION_DOWN;
-import static android.view.MotionEvent.ACTION_MOVE;
import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
import static com.android.app.animation.Interpolators.DECELERATE_3;
@@ -87,6 +86,7 @@
import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
/**
* Handles quick switching to a recent task from the home screen. To give as much flexibility to
@@ -191,6 +191,9 @@
public void onDragStart(boolean start) {
mMotionPauseDetector.clear();
if (start) {
+ InteractionJankMonitorWrapper.begin(mRecentsView,
+ InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
+
mStartState = mLauncher.getStateManager().getState();
mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseDetected);
@@ -325,6 +328,7 @@
if (mMotionPauseDetector.isPaused() && noFling) {
// Going to Overview.
cancelAnimations();
+ InteractionJankMonitorWrapper.cancel(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
StateAnimationConfig config = new StateAnimationConfig();
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
@@ -441,6 +445,8 @@
RecentsView.SCROLL_VIBRATION_PRIMITIVE,
RecentsView.SCROLL_VIBRATION_PRIMITIVE_SCALE,
RecentsView.SCROLL_VIBRATION_FALLBACK);
+ } else {
+ InteractionJankMonitorWrapper.cancel(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
}
nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
@@ -462,6 +468,11 @@
: targetState.ordinal > mStartState.ordinal
? LAUNCHER_UNKNOWN_SWIPEUP
: LAUNCHER_UNKNOWN_SWIPEDOWN));
+
+ if (targetState == QUICK_SWITCH_FROM_HOME) {
+ InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
+ }
+
mLauncher.getStateManager().goToState(targetState, false, forEndCallback(this::clearState));
}
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index ab37493..c5a88bc 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -139,6 +139,7 @@
mTmpMatrix.setScale(scale, scale,
app.localBounds.exactCenterX(), app.localBounds.exactCenterY());
builder.setMatrix(mTmpMatrix).setAlpha(alpha);
+ builder.setShow();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index c18ad5a..f1660ee 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -129,7 +129,7 @@
mWindowMaxDeltaY = mLauncher.getResources().getDimensionPixelSize(
R.dimen.swipe_back_window_max_delta_y);
mCancelInterpolator =
- AnimationUtils.loadInterpolator(mLauncher, R.interpolator.back_cancel);
+ AnimationUtils.loadInterpolator(mLauncher, R.interpolator.standard_interpolator);
}
/**
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 60784f5..c9b7d5e 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -662,6 +662,31 @@
}
/**
+ * Tells SysUI to remove the bubble with the provided key.
+ * @param key the key of the bubble to show.
+ */
+ public void removeBubble(String key) {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.removeBubble(key);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call removeBubble");
+ }
+ }
+
+ /**
+ * Tells SysUI to remove all bubbles.
+ */
+ public void removeAllBubbles() {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.removeAllBubbles();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call removeAllBubbles");
+ }
+ }
+
+ /**
* Tells SysUI to collapse the bubbles.
*/
public void collapseBubbles() {
@@ -674,6 +699,21 @@
}
}
+ /**
+ * Tells SysUI when the bubble is being dragged.
+ * Should be called only when the bubble bar is expanded.
+ * @param bubbleKey the key of the bubble to collapse/expand
+ * @param isBeingDragged whether the bubble is being dragged
+ */
+ public void onBubbleDrag(@Nullable String bubbleKey, boolean isBeingDragged) {
+ if (mBubbles == null) return;
+ try {
+ mBubbles.onBubbleDrag(bubbleKey, isBeingDragged);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call onBubbleDrag");
+ }
+ }
+
//
// Splitscreen
//
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index c0684d7..6dbb5bf 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
@@ -37,6 +38,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.DisplayController;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.views.DesktopTaskView;
@@ -169,10 +171,16 @@
for (RemoteAnimationTarget compat : appearedTaskTargets) {
if (compat.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME
- && activityInterface.getCreatedActivity() instanceof RecentsActivity) {
- // When receive opening home activity while recents is running, enter home
- // and dismiss recents.
- ((RecentsActivity) activityInterface.getCreatedActivity()).startHome();
+ && activityInterface.getCreatedActivity() instanceof RecentsActivity
+ && DisplayController.getNavigationMode(mCtx) != NO_BUTTON) {
+ // The only time we get onTasksAppeared() in button navigation with a
+ // 3p launcher is if the user goes to overview first, and in this case we
+ // can immediately finish the transition
+ RecentsView recentsView =
+ activityInterface.getCreatedActivity().getOverviewPanel();
+ if (recentsView != null) {
+ recentsView.finishRecentsAnimation(true, null);
+ }
return;
}
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 1744b08..06f1f9a 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -159,6 +159,10 @@
return mActionsView;
}
+ public TaskThumbnailView getThumbnailView() {
+ return mThumbnailView;
+ }
+
/**
* Called when the current task is interactive for the user
*/
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index 56d6857..bcb9cec 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -265,6 +265,11 @@
return anim
}
+ /** Removes the split instructions view from [launcher] drag layer. */
+ fun removeSplitInstructionsView(launcher: StatefulActivity<*>) {
+ safeRemoveViewFromDragLayer(launcher, splitInstructionsView)
+ }
+
private fun safeRemoveViewFromDragLayer(launcher: StatefulActivity<*>, view: View?) {
if (view != null) {
launcher.dragLayer.removeView(view)
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index 148a45a..b36cf5f 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -169,6 +169,7 @@
private void cleanUp() {
mLauncher.getDragLayer().removeView(firstFloatingTaskView);
mLauncher.getDragLayer().removeView(secondFloatingTaskView);
+ mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher);
mController.resetState();
}
});
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 80e5a54..5e488cc 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
import static com.android.launcher3.LauncherState.EDIT_MODE;
+import static com.android.launcher3.LauncherState.FLOATING_SEARCH_BAR;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
@@ -99,6 +100,12 @@
}
@Override
+ public boolean isFloatingSearchVisible() {
+ return FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()
+ && OVERVIEW.areElementsVisible(mActivity, FLOATING_SEARCH_BAR);
+ }
+
+ @Override
protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) {
mActivity.getStateManager().moveToRestState();
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index e47c089..754d1ff 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -22,12 +22,14 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.Button;
import android.widget.FrameLayout;
+import android.widget.ImageButton;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
@@ -49,6 +51,7 @@
implements OnClickListener, Insettable {
private final Rect mInsets = new Rect();
+ private BaseDraggingActivity mActivity;
@IntDef(flag = true, value = {
HIDDEN_NON_ZERO_ROTATION,
@@ -96,7 +99,7 @@
public static final int FLAG_SINGLE_TASK = 1 << 0;
private MultiValueAlpha mMultiValueAlpha;
- private Button mSplitButton;
+ private ImageButton mSplitButton;
@ActionsHiddenFlags
private int mHiddenFlags;
@@ -132,6 +135,8 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ mActivity = BaseActivity.fromContext(getContext());
+
mMultiValueAlpha = new MultiValueAlpha(findViewById(R.id.action_buttons), NUM_ALPHAS);
mMultiValueAlpha.setUpdateVisibility(true);
@@ -273,7 +278,7 @@
LayoutParams actionParams = (LayoutParams) findViewById(
R.id.action_buttons).getLayoutParams();
actionParams.setMargins(
- actionParams.leftMargin, mDp.overviewActionsTopMarginPx,
+ actionParams.leftMargin, 0,
actionParams.rightMargin, getBottomMargin());
}
@@ -286,6 +291,11 @@
return mDp.stashedTaskbarHeight;
}
+ if (isFloatingSearchVisible()) {
+ // Center between task and bottom of the screen.
+ return (mDp.heightPx - mTaskSize.bottom - mDp.overviewActionsHeight) / 2;
+ }
+
// Align to bottom of task Rect.
return mDp.heightPx - mTaskSize.bottom - mDp.overviewActionsTopMarginPx
- mDp.overviewActionsHeight;
@@ -301,9 +311,12 @@
requestLayout();
- mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
- (dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical),
- 0, 0, 0);
+ mSplitButton.setImageResource(
+ dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical);
+ }
+
+ protected boolean isFloatingSearchVisible() {
+ return ((RecentsView) mActivity.getOverviewPanel()).isFloatingSearchVisible();
}
/**
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index a21bbe1..29d9fa6 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4823,6 +4823,8 @@
mSecondFloatingTaskView = null;
mSplitInstructionsView = null;
mSplitSelectSource = null;
+ mSplitSelectStateController.getSplitAnimationController()
+ .removeSplitInstructionsView(mActivity);
}
if (mSecondSplitHiddenView != null) {
@@ -5220,6 +5222,11 @@
});
}
+ /** @return {@code true} if floating search bar is visible in Recents. */
+ public boolean isFloatingSearchVisible() {
+ return false;
+ }
+
public RemoteTargetHandle[] getRemoteTargetHandles() {
return mRemoteTargetHandles;
}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index 59f9d5f..3a5fb04 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -16,11 +16,17 @@
package com.android.quickstep;
+import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
+
import static org.junit.Assert.assertTrue;
import android.os.SystemProperties;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Until;
+
import com.android.launcher3.Launcher;
+import com.android.launcher3.tapl.LaunchedAppState;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -76,6 +82,21 @@
}
}
+ protected void assertTestActivityIsRunning(int activityNumber, String message) {
+ assertTrue(message, mDevice.wait(
+ Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity" + activityNumber)),
+ DEFAULT_UI_TIMEOUT));
+ }
+
+ protected LaunchedAppState getAndAssertLaunchedApp() {
+ final LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
+ executeOnLauncher(launcher -> assertTrue(
+ "Launcher activity is the top activity; expecting another activity to be the top "
+ + "one",
+ isInLaunchedApp(launcher)));
+ return launchedAppState;
+ }
+
private boolean isInLiveTileMode(Launcher launcher,
LauncherInstrumentation.ContainerType expectedContainerType) {
if (expectedContainerType != LauncherInstrumentation.ContainerType.OVERVIEW) {
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index bc90db0..a67d787 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -116,7 +116,8 @@
Utilities.enableRunningInTestHarnessForTests();
}
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
+ RecentsActivity.ACTIVITY_TRACKER::getCreatedActivity);
mOrderSensitiveRules = RuleChain
.outerRule(new SamplerRule())
.around(new NavigationModeSwitchRule(mLauncher))
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index bb246c2..06ce0e5 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -241,16 +241,6 @@
isInState(() -> LauncherState.OVERVIEW));
}
- private LaunchedAppState getAndAssertLaunchedApp() {
- final LaunchedAppState launchedAppState = mLauncher.getLaunchedAppState();
- assertNotNull("Launcher.getLaunchedApp() returned null", launchedAppState);
- executeOnLauncher(launcher -> assertTrue(
- "Launcher activity is the top activity; expecting another activity to be the top "
- + "one",
- isInLaunchedApp(launcher)));
- return launchedAppState;
- }
-
private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
if (toRight) {
@@ -292,22 +282,22 @@
startTestActivity(4);
quickSwitchToPreviousAppAndAssert(true /* toRight */);
- assertTrue("The first app we should have quick switched to is not running",
- isTestActivityRunning(3));
+ assertTestActivityIsRunning(3,
+ "The first app we should have quick switched to is not running");
quickSwitchToPreviousAppAndAssert(true /* toRight */);
if (mLauncher.getNavigationModel() == NavigationModel.THREE_BUTTON) {
// 3-button mode toggles between 2 apps, rather than going back further.
- assertTrue("Second quick switch should have returned to the first app.",
- isTestActivityRunning(4));
+ assertTestActivityIsRunning(4,
+ "Second quick switch should have returned to the first app.");
} else {
- assertTrue("The second app we should have quick switched to is not running",
- isTestActivityRunning(2));
+ assertTestActivityIsRunning(2,
+ "The second app we should have quick switched to is not running");
}
quickSwitchToPreviousAppAndAssert(false /* toRight */);
- assertTrue("The 2nd app we should have quick switched to is not running",
- isTestActivityRunning(3));
+ assertTestActivityIsRunning(3,
+ "The 2nd app we should have quick switched to is not running");
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
launchedAppState.switchToOverview();
@@ -331,9 +321,9 @@
// Quick-switch to the test app with swiping to right.
quickSwitchToPreviousAppAndAssert(true /* toRight */);
- assertTrue("The first app we should have quick switched to is not running",
- isTestActivityRunning(2));
-
+ assertTestActivityIsRunning(2,
+ "The first app we should have quick switched to is not running");
+ // Expect task bar visible when the launched app was the test activity.
launchedAppState = getAndAssertLaunchedApp();
Log.e(FLAKY_QUICK_SWITCH_TO_PREVIOUS_APP,
@@ -347,12 +337,6 @@
}
}
- private boolean isTestActivityRunning(int activityNumber) {
- return mDevice.wait(Until.hasObject(By.pkg(getAppPackageName())
- .text("TestActivity" + activityNumber)),
- DEFAULT_UI_TIMEOUT);
- }
-
@Test
@NavigationModeSwitch
@PortraitLandscape
@@ -360,8 +344,8 @@
public void testQuickSwitchFromHome() throws Exception {
startTestActivity(2);
mLauncher.goHome().quickSwitchToPreviousApp();
- assertTrue("The most recent task is not running after quick switching from home",
- isTestActivityRunning(2));
+ assertTestActivityIsRunning(2,
+ "The most recent task is not running after quick switching from home");
getAndAssertLaunchedApp();
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index 7ae3f29..907dbcc 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -19,6 +19,7 @@
import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@@ -30,6 +31,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
+import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -112,4 +114,19 @@
assertNotNull("switchToAllApps() returned null",
mLauncher.getWorkspace().switchToAllApps());
}
+
+ @Test
+ @NavigationModeSwitch
+ @PortraitLandscape
+ public void testQuickSwitchFromHome() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ startTestActivity(2);
+ Workspace workspace = mLauncher.goHome();
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.FOUR_FINGER);
+ workspace.quickSwitchToPreviousApp();
+ assertTestActivityIsRunning(2,
+ "The most recent task is not running after quick switching from home");
+ getAndAssertLaunchedApp();
+ }
}
diff --git a/res/anim-v33/shared_x_axis_activity_close_enter.xml b/res/anim-v33/shared_x_axis_activity_close_enter.xml
index 94ef06c..3d7ad2b 100644
--- a/res/anim-v33/shared_x_axis_activity_close_enter.xml
+++ b/res/anim-v33/shared_x_axis_activity_close_enter.xml
@@ -25,7 +25,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_decelerate"
+ android:interpolator="@interpolator/standard_decelerate_interpolator"
android:startOffset="100"
android:duration="350" />
@@ -35,7 +35,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/anim-v33/shared_x_axis_activity_close_exit.xml b/res/anim-v33/shared_x_axis_activity_close_exit.xml
index 19eb09e..fb63602 100644
--- a/res/anim-v33/shared_x_axis_activity_close_exit.xml
+++ b/res/anim-v33/shared_x_axis_activity_close_exit.xml
@@ -24,7 +24,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_accelerate"
+ android:interpolator="@interpolator/standard_accelerate_interpolator"
android:startOffset="0"
android:duration="100" />
@@ -34,7 +34,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/anim-v33/shared_x_axis_activity_open_enter.xml b/res/anim-v33/shared_x_axis_activity_open_enter.xml
index f699cec..cba74ba 100644
--- a/res/anim-v33/shared_x_axis_activity_open_enter.xml
+++ b/res/anim-v33/shared_x_axis_activity_open_enter.xml
@@ -25,7 +25,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_decelerate"
+ android:interpolator="@interpolator/standard_decelerate_interpolator"
android:startOffset="100"
android:duration="350" />
@@ -35,7 +35,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/anim-v33/shared_x_axis_activity_open_exit.xml b/res/anim-v33/shared_x_axis_activity_open_exit.xml
index 85988ec..22e878d 100644
--- a/res/anim-v33/shared_x_axis_activity_open_exit.xml
+++ b/res/anim-v33/shared_x_axis_activity_open_exit.xml
@@ -24,7 +24,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/standard_accelerate"
+ android:interpolator="@interpolator/standard_accelerate_interpolator"
android:startOffset="0"
android:duration="100" />
@@ -34,7 +34,7 @@
android:fillEnabled="true"
android:fillBefore="true"
android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:interpolator="@interpolator/emphasized_interpolator"
android:startOffset="0"
android:duration="450" />
diff --git a/res/color/overview_button.xml b/res/color/overview_button.xml
index 1dd8da6..ccc042a 100644
--- a/res/color/overview_button.xml
+++ b/res/color/overview_button.xml
@@ -3,10 +3,10 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<item
android:alpha="1"
- android:color="?androidprv:attr/materialColorOnSurface"
+ android:color="?androidprv:attr/materialColorOnSurfaceVariant"
android:state_enabled="true" />
<item
android:alpha="?android:disabledAlpha"
- android:color="?androidprv:attr/materialColorOnSurface"
+ android:color="?androidprv:attr/materialColorOnSurfaceVariant"
android:state_enabled="false" />
</selector>
\ No newline at end of file
diff --git a/res/drawable/circle_btn_bg.xml b/res/drawable/circle_btn_bg.xml
new file mode 100644
index 0000000..ad59ea5
--- /dev/null
+++ b/res/drawable/circle_btn_bg.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/accent_ripple_color">
+ <item android:id="@android:id/mask">
+ <shape android:shape="oval">
+ <solid android:color="@android:color/white" />
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="oval">
+ <solid android:color="@android:color/white" />
+ </shape>
+ </item>
+</ripple>
diff --git a/res/drawable/ic_split_horizontal.xml b/res/drawable/ic_split_horizontal.xml
index 2efd2b9..875b1be 100644
--- a/res/drawable/ic_split_horizontal.xml
+++ b/res/drawable/ic_split_horizontal.xml
@@ -5,5 +5,5 @@
android:viewportHeight="24">
<path
android:pathData="M4,6L9,6L9,18L4,18L4,6ZM2,6L2,18C2,19.1 2.9,20 4,20L9,20C10.1,20 11,19.1 11,18L11,6C11,4.9 10.1,4 9,4L4,4C2.9,4 2,4.9 2,6ZM15,6L20,6L20,18L15,18L15,6ZM13,6L13,18C13,19.1 13.9,20 15,20L20,20C21.1,20 22,19.1 22,18L22,6C22,4.9 21.1,4 20,4L15,4C13.9,4 13,4.9 13,6Z"
- android:fillColor="#000000"/>
+ android:fillColor="@color/overview_button"/>
</vector>
diff --git a/res/drawable/ic_split_vertical.xml b/res/drawable/ic_split_vertical.xml
index 9bc9785..e73a1b2 100644
--- a/res/drawable/ic_split_vertical.xml
+++ b/res/drawable/ic_split_vertical.xml
@@ -5,5 +5,5 @@
android:viewportHeight="24">
<path
android:pathData="M18,4V9H6V4H18ZM18,2H6C4.9,2 4,2.9 4,4V9C4,10.1 4.9,11 6,11H18C19.1,11 20,10.1 20,9V4C20,2.9 19.1,2 18,2ZM18,15V20H6V15H18ZM18,13H6C4.9,13 4,13.9 4,15V20C4,21.1 4.9,22 6,22H18C19.1,22 20,21.1 20,20V15C20,13.9 19.1,13 18,13Z"
- android:fillColor="#000000"/>
+ android:fillColor="@color/overview_button"/>
</vector>
diff --git a/res/interpolator/back_cancel.xml b/res/interpolator/back_cancel.xml
deleted file mode 100644
index 2165457..0000000
--- a/res/interpolator/back_cancel.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2022, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.2"
- android:controlY1="0"
- android:controlX2="0"
- android:controlY2="1"/>
\ No newline at end of file
diff --git a/res/interpolator/fast_out_extra_slow_in.xml b/res/interpolator/fast_out_extra_slow_in.xml
deleted file mode 100644
index f296a82..0000000
--- a/res/interpolator/fast_out_extra_slow_in.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"/>
\ No newline at end of file
diff --git a/res/interpolator/folder_interpolator.xml b/res/interpolator/folder_interpolator.xml
deleted file mode 100644
index b95d454..0000000
--- a/res/interpolator/folder_interpolator.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, 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.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.2"
- android:controlY1="0"
- android:controlX2="0"
- android:controlY2="1"/>
diff --git a/res/interpolator/large_folder_preview_item_close_interpolator.xml b/res/interpolator/large_folder_preview_item_close_interpolator.xml
deleted file mode 100644
index d28af63..0000000
--- a/res/interpolator/large_folder_preview_item_close_interpolator.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, 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.
-*/
--->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.3"
- android:controlY1="0"
- android:controlX2="1"
- android:controlY2="1"/>
diff --git a/res/interpolator/standard_accelerate.xml b/res/interpolator/standard_accelerate.xml
deleted file mode 100644
index 394393d..0000000
--- a/res/interpolator/standard_accelerate.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:controlX1="0.3"
- android:controlY1="0"
- android:controlX2="1"
- android:controlY2="1"/>
\ No newline at end of file
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 39871f6..bcc626e 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="649227358658669779">"Launcher3"</string>
- <string name="work_folder_name" msgid="3753320833950115786">"ስራ"</string>
+ <string name="work_folder_name" msgid="3753320833950115786">"ሥራ"</string>
<string name="activity_not_found" msgid="8071924732094499514">"መተግበሪያ አልተጫነም።"</string>
<string name="activity_not_available" msgid="7456344436509528827">"መተግበሪያ አይገኝም"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"የወረደው መተግበሪያ ደህንነቱ በተጠበቀ ሁኔታ ውስጥ ተሰናክሏል"</string>
@@ -48,7 +48,7 @@
<string name="no_widgets_available" msgid="4337693382501046170">"መግብሮች እና አቋራጮች አይገኙም"</string>
<string name="no_search_results" msgid="3787956167293097509">"ምንም መግብሮች ወይም አቋራጮች አልተገኙም"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"የግል"</string>
- <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ስራ"</string>
+ <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ሥራ"</string>
<string name="widget_category_conversations" msgid="8894438636213590446">"ውይይቶች"</string>
<string name="widget_category_note_taking" msgid="3469689394504266039">"የማስታወሻ አያያዝ"</string>
<string name="widget_education_header" msgid="4874760613775913787">"በጣቶችዎ ጫፎች ላይ ጠቃሚ መረጃ"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 45062fc..d3841a3 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -27,7 +27,7 @@
<string name="safemode_widget_error" msgid="4863470563535682004">"ନିରାପଦ ମୋଡରେ ୱିଜେଟ୍ ଅକ୍ଷମ କରାଗଲା"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"ଶର୍ଟକଟ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="home_screen" msgid="5629429142036709174">"ହୋମ"</string>
- <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ୍ କରନ୍ତୁ"</string>
+ <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s ପାଇଁ ଆପ ସୂଚନା"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ଆପ ପେୟାର ସେଭ କରନ୍ତୁ"</string>
<string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1079e00..bea86fa 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -396,10 +396,12 @@
<dimen name="task_thumbnail_icon_drawable_size">0dp</dimen>
<dimen name="task_thumbnail_icon_drawable_size_grid">0dp</dimen>
<dimen name="overview_task_margin">0dp</dimen>
- <dimen name="overview_actions_height">0dp</dimen>
+ <dimen name="overview_actions_size">0dp</dimen>
<dimen name="overview_actions_button_spacing">0dp</dimen>
<dimen name="overview_actions_margin_gesture">0dp</dimen>
<dimen name="overview_actions_top_margin">0dp</dimen>
+ <!-- Width if the search bar were to be full-size in Overview. Note pill is 192dp smaller. -->
+ <dimen name="overview_floating_search_width">348dp</dimen>
<dimen name="overview_grid_side_margin">0dp</dimen>
<dimen name="overview_grid_row_spacing">0dp</dimen>
<dimen name="overview_page_spacing">0dp</dimen>
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 64ac841..4674401 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -2735,11 +2735,13 @@
}
public boolean isOccupied(int x, int y) {
- if (x < mCountX && y < mCountY) {
+ if (x >= 0 && x < mCountX && y >= 0 && y < mCountY) {
return mOccupied.cells[x][y];
- } else {
+ }
+ if (BuildConfig.IS_STUDIO_BUILD) {
throw new RuntimeException("Position exceeds the bound of this CellLayout");
}
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 42372f1..28e0cf2 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -584,13 +584,11 @@
overviewTaskIconDrawableSizeGridPx =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_drawable_size_grid);
overviewTaskThumbnailTopMarginPx = overviewTaskIconSizePx + overviewTaskMarginPx;
- // Don't add margin with floating search bar to minimize risk of overlapping.
- overviewActionsTopMarginPx = FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() ? 0
- : res.getDimensionPixelSize(R.dimen.overview_actions_top_margin);
+ overviewActionsTopMarginPx = res.getDimensionPixelSize(R.dimen.overview_actions_top_margin);
overviewPageSpacing = res.getDimensionPixelSize(R.dimen.overview_page_spacing);
overviewActionsButtonSpacing = res.getDimensionPixelSize(
R.dimen.overview_actions_button_spacing);
- overviewActionsHeight = res.getDimensionPixelSize(R.dimen.overview_actions_height);
+ overviewActionsHeight = res.getDimensionPixelSize(R.dimen.overview_actions_size);
overviewRowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
overviewGridSideMargin = res.getDimensionPixelSize(R.dimen.overview_grid_side_margin);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bfbd660..6df9aab 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1663,7 +1663,8 @@
if (isActionMain) {
if (!internalStateHandled) {
// In all these cases, only animate if we're already on home
- closeOpenViews(isStarted());
+ AbstractFloatingView.closeAllOpenViewsExcept(
+ this, isStarted(), AbstractFloatingView.TYPE_LISTENER);
if (!isInState(NORMAL)) {
// Only change state, if not already the same. This prevents cancelling any
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 259c5cc..82ed962 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_COUNT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
import android.animation.Animator;
@@ -462,7 +463,7 @@
updateHeaderScroll(0);
if (exitSearch) {
// Reset the search bar after transitioning home.
- mSearchUiManager.resetSearch();
+ MAIN_EXECUTOR.getHandler().post(mSearchUiManager::resetSearch);
// Animate to A-Z with 0 time to reset the animation with proper state management.
animateToSearchState(false, 0);
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 3989e7c..cabcabc 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -83,11 +83,11 @@
*/
// TODO(Block 1): Clean up flags
public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
- 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", DISABLED,
+ 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", TEAMFOOD,
"Enable option to replace decorator-based search result backgrounds with drawables");
public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
- 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", DISABLED,
+ 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", TEAMFOOD,
"Enable option to launch search results using the new view container transitions");
// TODO(Block 2): Clean up flags
@@ -129,7 +129,7 @@
// TODO(Block 5): Clean up flags
public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851,
- "ENABLE_TWOLINE_DEVICESEARCH", TEAMFOOD,
+ "ENABLE_TWOLINE_DEVICESEARCH", ENABLED,
"Enable two line label for icons with labels on device search.");
public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143,
@@ -227,7 +227,7 @@
"COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log");
public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
- "ENABLE_TWOLINE_ALLAPPS", TEAMFOOD, "Enables two line label inside all apps.");
+ "ENABLE_TWOLINE_ALLAPPS", ENABLED, "Enables two line label inside all apps.");
public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693,
"IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps");
@@ -363,7 +363,7 @@
"Enable splitting from fullscreen app with keyboard shortcuts");
public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
- 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED,
+ 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", TEAMFOOD,
"Enable initiating split screen from workspace to workspace.");
public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401,
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index b09985c..9e2e2bf 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -105,11 +105,11 @@
mDelay = res.getInteger(R.integer.config_folderDelay);
mFolderInterpolator = AnimationUtils.loadInterpolator(mContext,
- R.interpolator.folder_interpolator);
+ R.interpolator.standard_interpolator);
mLargeFolderPreviewItemOpenInterpolator = AnimationUtils.loadInterpolator(mContext,
R.interpolator.large_folder_preview_item_open_interpolator);
mLargeFolderPreviewItemCloseInterpolator = AnimationUtils.loadInterpolator(mContext,
- R.interpolator.large_folder_preview_item_close_interpolator);
+ R.interpolator.standard_accelerate_interpolator);
}
/**
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index ba1547f..9afa459 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -49,7 +49,6 @@
import com.android.launcher3.LauncherSettings.Animation;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.AllAppsContainer;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
@@ -323,9 +322,7 @@
* Returns whether this item should use the background animation.
*/
public boolean shouldUseBackgroundAnimation() {
- return animationType == LauncherSettings.Animation.VIEW_BACKGROUND
- && FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()
- && FeatureFlags.ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION.get();
+ return animationType == LauncherSettings.Animation.VIEW_BACKGROUND;
}
/**
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index c8b5a20..28688fd 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -299,6 +299,28 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
+ <activity-alias android:name="MaxShortcutsActivity"
+ android:label="TestActivityMaxShortcuts"
+ android:exported="true"
+ android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts"
+ android:resource="@xml/max_shortcuts"/>
+ </activity-alias>
+ <activity-alias android:name="SingleShortcutActivity"
+ android:label="TestActivitySingleShortcut"
+ android:exported="true"
+ android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="android.app.shortcuts"
+ android:resource="@xml/single_shortcut"/>
+ </activity-alias>
<activity
android:name="com.android.launcher3.testcomponent.DialogTestActivity"
android:label="Dialog Activity"
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
index 0ad87fb..54ade56 100644
--- a/tests/res/values/strings.xml
+++ b/tests/res/values/strings.xml
@@ -3,4 +3,5 @@
<string name="shortcut1" translatable="false">Shortcut 1</string>
<string name="shortcut2" translatable="false">Shortcut 2</string>
<string name="shortcut3" translatable="false">Shortcut 3</string>
+ <string name="shortcut4" translatable="false">Shortcut 4</string>
</resources>
diff --git a/tests/res/xml/max_shortcuts.xml b/tests/res/xml/max_shortcuts.xml
new file mode 100644
index 0000000..312a24c
--- /dev/null
+++ b/tests/res/xml/max_shortcuts.xml
@@ -0,0 +1,39 @@
+<?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.
+ -->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="max_shortcut1"
+ android:icon="@drawable/test_theme_icon"
+ android:shortcutShortLabel="@string/shortcut1">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+ <shortcut
+ android:shortcutId="max_shortcut2"
+ android:shortcutShortLabel="@string/shortcut2">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+ <shortcut
+ android:shortcutId="max_shortcut3"
+ android:shortcutShortLabel="@string/shortcut3">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+ <shortcut
+ android:shortcutId="max_shortcut4"
+ android:shortcutShortLabel="@string/shortcut4">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_max"/>
+ </shortcut>
+</shortcuts>
diff --git a/tests/res/xml/shortcuts.xml b/tests/res/xml/shortcuts.xml
index 94e8edd..2ba9d7f 100644
--- a/tests/res/xml/shortcuts.xml
+++ b/tests/res/xml/shortcuts.xml
@@ -1,4 +1,19 @@
<?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.
+ -->
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
<shortcut
android:shortcutId="shortcut1_themed"
diff --git a/tests/res/xml/single_shortcut.xml b/tests/res/xml/single_shortcut.xml
new file mode 100644
index 0000000..e8d938f
--- /dev/null
+++ b/tests/res/xml/single_shortcut.xml
@@ -0,0 +1,24 @@
+<?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.
+ -->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="single_shortcut_themed"
+ android:icon="@drawable/test_theme_icon"
+ android:shortcutShortLabel="@string/shortcut1">
+ <intent android:action="com.android.launcher3.intent.action.test_shortcut_single"/>
+ </shortcut>
+</shortcuts>
diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
index 398bd82..6489bc1 100644
--- a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
+++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java
@@ -16,6 +16,7 @@
package com.android.launcher3.celllayout;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.ui.TestViewHelpers.findWidgetProvider;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
@@ -43,9 +44,9 @@
public class TestWorkspaceBuilder {
private static final String TAG = "CellLayoutBoardBuilder";
- private static final ComponentName APP_COMPONENT_NAME = new ComponentName(
+ private static final String TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests.";
+ private ComponentName mAppComponentName = new ComponentName(
"com.google.android.calculator", "com.android.calculator2.Calculator");
-
private UserHandle mMyUser;
private Context mContext;
@@ -80,8 +81,20 @@
}
private AppInfo getApp() {
- return new AppInfo(APP_COMPONENT_NAME, "test icon", mMyUser,
- AppInfo.makeLaunchIntent(APP_COMPONENT_NAME));
+ return new AppInfo(mAppComponentName, "test icon", mMyUser,
+ AppInfo.makeLaunchIntent(mAppComponentName));
+ }
+
+ /**
+ * Helper to set the app to use for the test workspace,
+ * using activity-alias from AndroidManifest-common.
+ * @param testAppName the android:name field of the test app activity-alias to use
+ */
+ public void setTestAppActivityAlias(String testAppName) {
+ this.mAppComponentName = new ComponentName(
+ getInstrumentation().getContext().getPackageName(),
+ TEST_ACTIVITY_PACKAGE_PREFIX + testAppName
+ );
}
private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect,
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index b1b3baa..5240e6a 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -201,7 +201,8 @@
}
protected TestRule getRulesInsideActivityMonitor() {
- final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
+ final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
+ Launcher.ACTIVITY_TRACKER::getCreatedActivity);
final RuleChain inner = RuleChain
.outerRule(new PortraitLandscapeRunner(this))
.around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
diff --git a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
index 1ca4434..b4ad1f3 100644
--- a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
+++ b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
@@ -23,8 +23,11 @@
import com.android.app.viewcapture.SimpleViewCapture
import com.android.app.viewcapture.ViewCapture.MAIN_EXECUTOR
import com.android.app.viewcapture.data.ExportedData
+import com.android.launcher3.tapl.TestHelpers
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter
import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer
+import org.junit.Assert.assertTrue
+import java.util.function.Supplier
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@@ -35,7 +38,7 @@
*
* This rule will not work in OOP tests that don't have access to the activity under test.
*/
-class ViewCaptureRule : TestRule {
+class ViewCaptureRule(var alreadyOpenActivitySupplier: Supplier<Activity?>) : TestRule {
private val viewCapture = SimpleViewCapture("test-view-capture")
var viewCaptureData: ExportedData? = null
private set
@@ -46,6 +49,8 @@
viewCaptureData = null
val windowListenerCloseables = mutableListOf<SafeCloseable>()
+ startCapturingExistingActivity(windowListenerCloseables)
+
val lifecycleCallbacks =
object : ActivityLifecycleCallbacksAdapter {
override fun onActivityCreated(activity: Activity, bundle: Bundle?) {
@@ -76,7 +81,16 @@
MAIN_EXECUTOR.execute { windowListenerCloseables.onEach(SafeCloseable::close) }
}
- ViewCaptureAnalyzer.assertNoAnomalies(viewCaptureData)
+ analyzeViewCapture()
+ }
+
+ private fun startCapturingExistingActivity(
+ windowListenerCloseables: MutableCollection<SafeCloseable>
+ ) {
+ val alreadyOpenActivity = alreadyOpenActivitySupplier.get()
+ if (alreadyOpenActivity != null) {
+ startCapture(windowListenerCloseables, alreadyOpenActivity)
+ }
}
private fun startCapture(
@@ -92,4 +106,17 @@
}
}
}
+
+ private fun analyzeViewCapture() {
+ // OOP tests don't produce ViewCapture data
+ if (!TestHelpers.isInLauncherProcess()) return
+
+ ViewCaptureAnalyzer.assertNoAnomalies(viewCaptureData)
+
+ var frameCount = 0
+ for (i in 0 until viewCaptureData!!.windowDataCount) {
+ frameCount += viewCaptureData!!.getWindowData(i).frameDataCount
+ }
+ assertTrue("Empty ViewCapture data", frameCount > 0)
+ }
}
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
index 2501801..cb404b9 100644
--- a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
@@ -15,13 +15,12 @@
*/
package com.android.launcher3.util.viewcapture_analysis;
-import static com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer.diagPathFromRoot;
-
import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer.AnalysisNode;
import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer.AnomalyDetector;
-import java.util.Collection;
-import java.util.Set;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* Anomaly detector that triggers an error when alpha of a view changes too rapidly.
@@ -32,9 +31,11 @@
private static final String CONTENT = "DecorView|LinearLayout|FrameLayout:id/content|";
private static final String DRAG_LAYER =
CONTENT + "LauncherRootView:id/launcher|DragLayer:id/drag_layer|";
+ private static final String RECENTS_DRAG_LAYER =
+ CONTENT + "LauncherRootView:id/launcher|RecentsDragLayer:id/drag_layer|";
// Paths of nodes that are excluded from analysis.
- private static final Collection<String> PATHS_TO_IGNORE = Set.of(
+ private static final Iterable<String> PATHS_TO_IGNORE = List.of(
CONTENT
+ "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+ "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
@@ -112,27 +113,102 @@
DRAG_LAYER + "WidgetsFullSheet|SpringRelativeLayout:id/container",
DRAG_LAYER + "WidgetsTwoPaneSheet|SpringRelativeLayout:id/container",
CONTENT + "LauncherRootView:id/launcher|FloatingIconView",
- CONTENT
- + "LauncherRootView|RecentsDragLayer:id/drag_layer|FallbackRecentsView:id"
- + "/overview_panel",
- CONTENT
- + "LauncherRootView|RecentsDragLayer:id/drag_layer|NexusOverviewActionsView"
- + ":id/overview_actions_view|LinearLayout:id/action_buttons|Button:id"
- + "/action_screenshot",
- CONTENT
- + "LauncherRootView|RecentsDragLayer:id/drag_layer|NexusOverviewActionsView"
- + ":id/overview_actions_view|LinearLayout:id/action_buttons|Button:id"
- + "/action_select"
+ RECENTS_DRAG_LAYER + "ArrowTipView|View:id/arrow",
+ DRAG_LAYER + "FallbackRecentsView:id/overview_panel",
+ RECENTS_DRAG_LAYER + "FallbackRecentsView:id/overview_panel",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|ImageButton:id/action_screenshot",
+ RECENTS_DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|ImageButton:id/action_screenshot",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|ImageButton:id/action_select",
+ RECENTS_DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|ImageButton:id/action_select",
+ DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|ImageButton:id/action_split",
+ RECENTS_DRAG_LAYER
+ + "NexusOverviewActionsView:id/overview_actions_view"
+ + "|LinearLayout:id/action_buttons|ImageButton:id/action_split"
);
+
+ /**
+ * Element of the tree of ignored nodes.
+ * If the "children" map is empty, then this node should be ignored, i.e. alpha jumps analysis
+ * shouldn't run for it.
+ * I.e. ignored nodes correspond to the leaves in the ignored nodes tree.
+ */
+ private static class IgnoreNode {
+ // Map from child node identities to ignore-nodes for these children.
+ public final Map<String, IgnoreNode> children = new HashMap<>();
+ }
+
+ private static final IgnoreNode IGNORED_NODES_ROOT = buildIgnoreNodesTree();
+
+ // Converts the list of full paths of nodes to ignore to a more efficient tree of ignore-nodes.
+ private static IgnoreNode buildIgnoreNodesTree() {
+ final IgnoreNode root = new IgnoreNode();
+ for (String pathToIgnore : PATHS_TO_IGNORE) {
+ // Scan the diag path of an ignored node and add its elements into the tree.
+ IgnoreNode currentIgnoreNode = root;
+ for (String part : pathToIgnore.split("\\|")) {
+ // Ensure that the child of the node is added to the tree.
+ IgnoreNode child = currentIgnoreNode.children.get(part);
+ if (child == null) {
+ currentIgnoreNode.children.put(part, child = new IgnoreNode());
+ }
+ currentIgnoreNode = child;
+ }
+ }
+ return root;
+ }
+
// Minimal increase or decrease of view's alpha between frames that triggers the error.
private static final float ALPHA_JUMP_THRESHOLD = 1f;
+ // Per-AnalysisNode data that's specific to this detector.
+ private static class NodeData {
+ public boolean ignoreAlphaJumps;
+
+ // If ignoreNode is null, then this AnalysisNode node will be ignored if its parent is
+ // ignored.
+ // Otherwise, this AnalysisNode will be ignored if ignoreNode is a leaf i.e. has no
+ // children.
+ public IgnoreNode ignoreNode;
+ }
+
+ private NodeData getNodeData(AnalysisNode info) {
+ return (NodeData) info.detectorsData[detectorOrdinal];
+ }
+
@Override
void initializeNode(AnalysisNode info) {
+ final NodeData nodeData = new NodeData();
+ info.detectorsData[detectorOrdinal] = nodeData;
+
// If the parent view ignores alpha jumps, its descendants will too.
- final boolean parentIgnoreAlphaJumps = info.parent != null && info.parent.ignoreAlphaJumps;
- info.ignoreAlphaJumps = parentIgnoreAlphaJumps
- || PATHS_TO_IGNORE.contains(diagPathFromRoot(info));
+ final boolean parentIgnoresAlphaJumps = info.parent != null && getNodeData(
+ info.parent).ignoreAlphaJumps;
+ if (parentIgnoresAlphaJumps) {
+ nodeData.ignoreAlphaJumps = true;
+ return;
+ }
+
+ // Parent view doesn't ignore alpha jumps.
+ // Initialize this AnalysisNode's ignore-node with the corresponding child of the
+ // ignore-node of the parent, if present.
+ final IgnoreNode parentIgnoreNode = info.parent != null
+ ? getNodeData(info.parent).ignoreNode
+ : IGNORED_NODES_ROOT;
+ nodeData.ignoreNode = parentIgnoreNode != null
+ ? parentIgnoreNode.children.get(info.nodeIdentity) : null;
+ // AnalysisNode will be ignored if the corresponding ignore-node is a leaf.
+ nodeData.ignoreAlphaJumps =
+ nodeData.ignoreNode != null && nodeData.ignoreNode.children.isEmpty();
}
@Override
@@ -142,7 +218,7 @@
if (oldInfo != null && oldInfo.frameN != frameN) return;
final AnalysisNode latestInfo = newInfo != null ? newInfo : oldInfo;
- if (latestInfo.ignoreAlphaJumps) return;
+ if (getNodeData(latestInfo).ignoreAlphaJumps) return;
final float oldAlpha = oldInfo != null ? oldInfo.alpha : 0;
final float newAlpha = newInfo != null ? newInfo.alpha : 0;
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java
index 5a2611c..2cf3843 100644
--- a/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/ViewCaptureAnalyzer.java
@@ -40,6 +40,9 @@
* Detector of one kind of anomaly.
*/
abstract static class AnomalyDetector {
+ // Index of this detector in ViewCaptureAnalyzer.ANOMALY_DETECTORS
+ public int detectorOrdinal;
+
/**
* Initializes fields of the node that are specific to the anomaly detected by this
* detector.
@@ -64,9 +67,13 @@
}
// All detectors. They will be invoked in the order listed here.
- private static final Iterable<AnomalyDetector> ANOMALY_DETECTORS = Arrays.asList(
+ private static final AnomalyDetector[] ANOMALY_DETECTORS = {
new AlphaJumpDetector()
- );
+ };
+
+ static {
+ for (int i = 0; i < ANOMALY_DETECTORS.length; ++i) ANOMALY_DETECTORS[i].detectorOrdinal = i;
+ }
// A view from view capture data converted to a form that's convenient for detecting anomalies.
static class AnalysisNode {
@@ -86,7 +93,11 @@
public int frameN;
public ViewNode viewCaptureNode;
- public boolean ignoreAlphaJumps;
+ // Class name + resource id
+ public String nodeIdentity;
+
+ // Collection of detector-specific data for this node.
+ public final Object[] detectorsData = new Object[ANOMALY_DETECTORS.length];
@Override
public String toString() {
@@ -139,7 +150,7 @@
for (AnalysisNode info : lastSeenNodes.values()) {
if (info.frameN == frameN - 1) {
if (!info.viewCaptureNode.getWillNotDraw()) {
- ANOMALY_DETECTORS.forEach(
+ Arrays.stream(ANOMALY_DETECTORS).forEach(
detector -> detector.detectAnomalies(
/* oldInfo = */ info,
/* newInfo = */ null,
@@ -177,6 +188,8 @@
final AnalysisNode newAnalysisNode = new AnalysisNode();
newAnalysisNode.className = viewCaptureData.getClassname(classIndex);
newAnalysisNode.resourceId = viewCaptureNode.getId();
+ newAnalysisNode.nodeIdentity =
+ getNodeIdentity(newAnalysisNode.className, newAnalysisNode.resourceId);
newAnalysisNode.parent = parent;
newAnalysisNode.left = left;
newAnalysisNode.top = top;
@@ -185,12 +198,13 @@
newAnalysisNode.alpha = alpha;
newAnalysisNode.frameN = frameN;
newAnalysisNode.viewCaptureNode = viewCaptureNode;
- ANOMALY_DETECTORS.forEach(detector -> detector.initializeNode(newAnalysisNode));
+ Arrays.stream(ANOMALY_DETECTORS).forEach(
+ detector -> detector.initializeNode(newAnalysisNode));
// Detect anomalies for the view
final AnalysisNode oldAnalysisNode = lastSeenNodes.get(hashcode); // may be null
if (frameN != 0 && !viewCaptureNode.getWillNotDraw()) {
- ANOMALY_DETECTORS.forEach(
+ Arrays.stream(ANOMALY_DETECTORS).forEach(
detector -> detector.detectAnomalies(oldAnalysisNode, newAnalysisNode, frameN));
}
lastSeenNodes.put(hashcode, newAnalysisNode);
@@ -221,18 +235,18 @@
return className.substring(className.lastIndexOf(".") + 1);
}
- static String diagPathFromRoot(AnalysisNode nodeBox) {
- final StringBuilder path = new StringBuilder(diagPathElement(nodeBox));
+ private static String diagPathFromRoot(AnalysisNode nodeBox) {
+ final StringBuilder path = new StringBuilder(nodeBox.nodeIdentity);
for (AnalysisNode ancestor = nodeBox.parent; ancestor != null; ancestor = ancestor.parent) {
- path.insert(0, diagPathElement(ancestor) + "|");
+ path.insert(0, ancestor.nodeIdentity + "|");
}
return path.toString();
}
- private static String diagPathElement(AnalysisNode nodeBox) {
+ private static String getNodeIdentity(String className, String resourceId) {
final StringBuilder sb = new StringBuilder();
- sb.append(classNameToSimpleName(nodeBox.className));
- if (!"NO_ID".equals(nodeBox.resourceId)) sb.append(":" + nodeBox.resourceId);
+ sb.append(classNameToSimpleName(className));
+ if (!"NO_ID".equals(resourceId)) sb.append(":" + resourceId);
return sb.toString();
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 3dab9a8..7dd5827 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -240,76 +240,71 @@
"want to quick switch to the previous app")) {
verifyActiveContainer();
final boolean launcherWasVisible = mLauncher.isLauncherVisible();
- switch (mLauncher.getNavigationModel()) {
- case ZERO_BUTTON: {
- final int startX;
- final int startY;
- final int endX;
- final int endY;
- final int cornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
- if (toRight) {
- // Swipe from the bottom left to the bottom right of the screen.
- startX = cornerRadius;
- startY = getSwipeStartY();
- endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
- endY = startY;
- } else {
- // Swipe from the bottom right to the bottom left of the screen.
- startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
- startY = getSwipeStartY();
- endX = cornerRadius;
- endY = startY;
- }
-
- LauncherInstrumentation.GestureScope gestureScope =
- launcherWasVisible
- ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
- : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
- mLauncher.executeAndWaitForEvent(
- () -> mLauncher.linearGesture(
- startX, startY, endX, endY, 20, false, gestureScope),
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Quick switch gesture didn't change window state", "swiping");
- break;
+ if (mLauncher.getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || mLauncher.getTrackpadGestureType() == TrackpadGestureType.FOUR_FINGER) {
+ final int startX;
+ final int startY;
+ final int endX;
+ final int endY;
+ final int cornerRadius = (int) Math.ceil(mLauncher.getWindowCornerRadius());
+ if (toRight) {
+ // Swipe from the bottom left to the bottom right of the screen.
+ startX = cornerRadius;
+ startY = getSwipeStartY();
+ endX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+ endY = startY;
+ } else {
+ // Swipe from the bottom right to the bottom left of the screen.
+ startX = mLauncher.getDevice().getDisplayWidth() - cornerRadius;
+ startY = getSwipeStartY();
+ endX = cornerRadius;
+ endY = startY;
}
- case THREE_BUTTON:
- // Double press the recents button.
- UiObject2 recentsButton = mLauncher.waitForNavigationUiObject("recent_apps");
- if (mLauncher.isTablet()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_DOWN);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_UP);
- }
- if (mLauncher.isTrackpadGestureEnabled()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
- mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL,
- "clicking Recents button for the first time");
- mLauncher.getOverview();
- if (mLauncher.isTablet()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_DOWN);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_UP);
- }
- if (mLauncher.isTrackpadGestureEnabled()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
- mLauncher.executeAndWaitForEvent(
- () -> recentsButton.click(),
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Pressing recents button didn't change window state",
- "clicking Recents button for the second time");
- break;
+ LauncherInstrumentation.GestureScope gestureScope =
+ launcherWasVisible
+ ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
+ : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
+ mLauncher.executeAndWaitForEvent(
+ () -> mLauncher.linearGesture(
+ startX, startY, endX, endY, 20, false, gestureScope),
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Quick switch gesture didn't change window state", "swiping");
+ } else {
+ // Double press the recents button.
+ UiObject2 recentsButton = mLauncher.waitForNavigationUiObject("recent_apps");
+ if (mLauncher.isTablet()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+ LauncherInstrumentation.EVENT_TOUCH_DOWN);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+ LauncherInstrumentation.EVENT_TOUCH_UP);
+ }
+ if (mLauncher.isTrackpadGestureEnabled()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+ }
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL,
+ "clicking Recents button for the first time");
+ mLauncher.getOverview();
+ if (mLauncher.isTablet()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+ LauncherInstrumentation.EVENT_TOUCH_DOWN);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+ LauncherInstrumentation.EVENT_TOUCH_UP);
+ }
+ if (mLauncher.isTrackpadGestureEnabled()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+ }
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.executeAndWaitForEvent(
+ () -> recentsButton.click(),
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Pressing recents button didn't change window state",
+ "clicking Recents button for the second time");
}
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
- return;
}
}