Merge "Add Lifecycle and SavedState support in Launcher ActivityContext." into udc-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 55301ff..cebcd42 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -135,7 +135,7 @@
}
}
-// Next value 45
+// Next value 48
enum Attribute {
option allow_alias = true;
@@ -187,6 +187,11 @@
ALL_APPS_SEARCH_RESULT_SYSTEM_POINTER = 42;
ALL_APPS_SEARCH_RESULT_EDUCARD = 43;
+ // Result sources
+ DATA_SOURCE_APPSEARCH_APP_PREVIEW = 45;
+ DATA_SOURCE_APPSEARCH_APP_SRP_PREVIEW = 46;
+ DATA_SOURCE_AIAI_SEARCH_ROOT = 47;
+
// Web suggestions provided by AGA
ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39;
diff --git a/quickstep/res/color/menu_item_hover_state_color.xml b/quickstep/res/color/menu_item_hover_state_color.xml
new file mode 100644
index 0000000..269b9f1
--- /dev/null
+++ b/quickstep/res/color/menu_item_hover_state_color.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <item android:state_hovered="false" android:color="?androidprv:attr/colorSurface" />
+ <item android:state_hovered="true" android:color="?androidprv:attr/colorSurfaceVariant" />
+</selector>
\ No newline at end of file
diff --git a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml
index 4cccd09..fd14d34 100644
--- a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml
+++ b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml
@@ -17,11 +17,7 @@
android:height="67dp"
android:viewportWidth="232"
android:viewportHeight="67">
- <group>
- <clip-path
- android:pathData="M0,0h232v67h-232z"/>
- <path
- android:pathData="M180.9,0.6H51.1C22.9,0.6 0,23.4 0,51.7V67.6H232V51.7C232,23.4 209.1,0.6 180.9,0.6Z"
- android:fillColor="#4B67AE"/>
- </group>
+ <path
+ android:pathData="M180.9,0.6H51.1C22.9,0.6 0,23.4 0,51.7V67.6H232V51.7C232,23.4 209.1,0.6 180.9,0.6Z"
+ android:fillColor="#4B67AE"/>
</vector>
diff --git a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml
index 7011f6c..f271c47 100644
--- a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml
+++ b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml
@@ -17,11 +17,7 @@
android:height="94dp"
android:viewportWidth="194"
android:viewportHeight="94">
- <group>
- <clip-path
- android:pathData="M0,0h194v94.09h-194z"/>
- <path
- android:pathData="M185.56,76.95C184.79,75.3 184.3,73.56 184.21,71.81L182.85,55.81C182.46,51.34 180.13,47.27 176.45,44.65L163.25,35.44C161.8,34.37 160.54,33.11 159.47,31.65L150.16,18.46C147.54,14.77 143.47,12.45 139,12.06L123,10.6C121.25,10.41 119.51,10.02 117.86,9.24L103.31,2.45C101.27,1.49 99.04,1 96.91,1C94.77,1 92.54,1.49 90.5,2.45L75.95,9.24C74.31,10.02 72.56,10.51 70.81,10.6L54.81,11.96C50.35,12.35 46.27,14.68 43.65,18.36L34.44,31.56C33.37,33.01 32.11,34.27 30.66,35.34L17.27,44.65C13.58,47.27 11.26,51.34 10.87,55.81L9.41,71.81C9.22,73.56 8.83,75.3 8.05,76.95L1.26,91.5C0.78,92.67 0.39,93.83 0.1,94.99H193.52C193.32,93.83 192.94,92.57 192.35,91.5L185.56,76.95Z"
- android:fillColor="#7E44AD"/>
- </group>
+ <path
+ android:pathData="M185.56,76.95C184.79,75.3 184.3,73.56 184.21,71.81L182.85,55.81C182.46,51.34 180.13,47.27 176.45,44.65L163.25,35.44C161.8,34.37 160.54,33.11 159.47,31.65L150.16,18.46C147.54,14.77 143.47,12.45 139,12.06L123,10.6C121.25,10.41 119.51,10.02 117.86,9.24L103.31,2.45C101.27,1.49 99.04,1 96.91,1C94.77,1 92.54,1.49 90.5,2.45L75.95,9.24C74.31,10.02 72.56,10.51 70.81,10.6L54.81,11.96C50.35,12.35 46.27,14.68 43.65,18.36L34.44,31.56C33.37,33.01 32.11,34.27 30.66,35.34L17.27,44.65C13.58,47.27 11.26,51.34 10.87,55.81L9.41,71.81C9.22,73.56 8.83,75.3 8.05,76.95L1.26,91.5C0.78,92.67 0.39,93.83 0.1,94.99H193.52C193.32,93.83 192.94,92.57 192.35,91.5L185.56,76.95Z"
+ android:fillColor="#7E44AD"/>
</vector>
diff --git a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml
index 5becb8b..3e71a3d 100644
--- a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml
+++ b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml
@@ -17,11 +17,7 @@
android:height="73dp"
android:viewportWidth="362"
android:viewportHeight="73">
- <group>
- <clip-path
- android:pathData="M0,0h362v73h-362z"/>
- <path
- android:pathData="M282.3,0H79.7C38,0 3.7,32.1 0.3,73H361.7C358.3,32.1 324,0 282.3,0Z"
- android:fillColor="#4B67AE"/>
- </group>
+ <path
+ android:pathData="M282.3,0H79.7C38,0 3.7,32.1 0.3,73H361.7C358.3,32.1 324,0 282.3,0Z"
+ android:fillColor="#4B67AE"/>
</vector>
diff --git a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml
index 7143089..2f11192 100644
--- a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml
+++ b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml
@@ -17,11 +17,7 @@
android:height="144dp"
android:viewportWidth="297"
android:viewportHeight="144">
- <group>
- <clip-path
- android:pathData="M0,0h297v144.04h-297z"/>
- <path
- android:pathData="M284.38,116.48C283.19,113.95 282.45,111.28 282.3,108.61L280.22,84.1C279.63,77.27 276.06,71.03 270.42,67.03L250.22,52.92C247.99,51.28 246.06,49.35 244.43,47.13L230.18,26.93C226.16,21.29 219.93,17.72 213.1,17.13L188.6,14.9C185.92,14.6 183.25,14.01 180.72,12.82L158.45,2.43C155.33,0.94 151.91,0.2 148.65,0.2C145.38,0.2 141.97,0.94 138.85,2.43L116.57,12.82C114.05,14.01 111.38,14.75 108.7,14.9L84.2,16.98C77.37,17.57 71.13,21.14 67.12,26.78L53.01,46.98C51.38,49.21 49.45,51.14 47.22,52.77L26.73,67.03C21.09,71.03 17.52,77.27 16.93,84.1L14.7,108.61C14.4,111.28 13.81,113.95 12.62,116.48L2.23,138.75C1.48,140.53 0.89,142.32 0.45,144.1H296.55C296.26,142.32 295.66,140.38 294.77,138.75L284.38,116.48Z"
- android:fillColor="#7E44AD"/>
- </group>
+ <path
+ android:pathData="M284.38,116.48C283.19,113.95 282.45,111.28 282.3,108.61L280.22,84.1C279.63,77.27 276.06,71.03 270.42,67.03L250.22,52.92C247.99,51.28 246.06,49.35 244.43,47.13L230.18,26.93C226.16,21.29 219.93,17.72 213.1,17.13L188.6,14.9C185.92,14.6 183.25,14.01 180.72,12.82L158.45,2.43C155.33,0.94 151.91,0.2 148.65,0.2C145.38,0.2 141.97,0.94 138.85,2.43L116.57,12.82C114.05,14.01 111.38,14.75 108.7,14.9L84.2,16.98C77.37,17.57 71.13,21.14 67.12,26.78L53.01,46.98C51.38,49.21 49.45,51.14 47.22,52.77L26.73,67.03C21.09,71.03 17.52,77.27 16.93,84.1L14.7,108.61C14.4,111.28 13.81,113.95 12.62,116.48L2.23,138.75C1.48,140.53 0.89,142.32 0.45,144.1H296.55C296.26,142.32 295.66,140.38 294.77,138.75L284.38,116.48Z"
+ android:fillColor="#7E44AD"/>
</vector>
diff --git a/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml b/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml
index 68c5eb1..5f951e4 100644
--- a/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml
+++ b/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml
@@ -17,11 +17,7 @@
android:height="208dp"
android:viewportWidth="83"
android:viewportHeight="208">
- <group>
- <clip-path
- android:pathData="M0,0h83.95v208h-83.95z"/>
- <path
- android:pathData="M23.53,169.2L31.09,165.56C76.7,143.55 76.7,64.45 31.09,42.35L23.53,38.71C13.55,33.95 5.06,25.56 -1,14.92V193.08C5.06,182.44 13.55,174.05 23.53,169.2Z"
- android:fillColor="#217500"/>
- </group>
+ <path
+ android:pathData="M23.53,169.2L31.09,165.56C76.7,143.55 76.7,64.45 31.09,42.35L23.53,38.71C13.55,33.95 5.06,25.56 -1,14.92V193.08C5.06,182.44 13.55,174.05 23.53,169.2Z"
+ android:fillColor="#217500"/>
</vector>
diff --git a/quickstep/res/drawable/task_menu_item_bg.xml b/quickstep/res/drawable/task_menu_item_bg.xml
index 16c13eb..588fe9e 100644
--- a/quickstep/res/drawable/task_menu_item_bg.xml
+++ b/quickstep/res/drawable/task_menu_item_bg.xml
@@ -15,8 +15,7 @@
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <solid android:color="?androidprv:attr/colorSurface" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/menu_item_hover_state_color" />
<corners android:radius="@dimen/task_menu_item_corner_radius" />
</shape>
diff --git a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
index 39c7e73..d24219d 100644
--- a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
+++ b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml
@@ -28,11 +28,13 @@
android:layout_width="0dp"
android:layout_height="@dimen/gesture_tutorial_menu_button_height"
android:layout_marginEnd="@dimen/gesture_tutorial_menu_button_spacing"
+ android:layout_marginBottom="24dp"
android:background="@drawable/gesture_tutorial_menu_button_background"
android:clipToOutline="true"
android:backgroundTint="@color/gesture_home_tutorial_background"
app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_menu_back_button">
@@ -40,6 +42,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gesture_tutorial_home_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -64,11 +68,13 @@
android:layout_width="0dp"
android:layout_height="@dimen/gesture_tutorial_menu_button_height"
android:layout_marginEnd="@dimen/gesture_tutorial_menu_button_spacing"
+ android:layout_marginBottom="24dp"
android:background="@drawable/gesture_tutorial_menu_button_background"
android:clipToOutline="true"
android:backgroundTint="@color/gesture_back_tutorial_exiting_app"
app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintStart_toEndOf="@id/gesture_tutorial_menu_home_button"
app:layout_constraintEnd_toStartOf="@id/gesture_tutorial_menu_overview_button">
@@ -77,6 +83,8 @@
android:layout_height="wrap_content"
android:src="@drawable/gesture_tutorial_back_step_shape"
android:layout_marginBottom="@dimen/gesture_tutorial_menu_back_shape_bottom_margin"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
@@ -99,11 +107,13 @@
android:id="@+id/gesture_tutorial_menu_overview_button"
android:layout_width="0dp"
android:layout_height="@dimen/gesture_tutorial_menu_button_height"
+ android:layout_marginBottom="24dp"
android:background="@drawable/gesture_tutorial_menu_button_background"
android:clipToOutline="true"
android:backgroundTint="@color/gesture_overview_tutorial_background"
app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintStart_toEndOf="@id/gesture_tutorial_menu_back_button"
app:layout_constraintEnd_toEndOf="parent">
@@ -111,6 +121,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gesture_tutorial_overview_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -142,10 +154,8 @@
style="@style/TextAppearance.GestureTutorial.ButtonLabel"
android:id="@+id/gesture_tutorial_menu_done_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingVertical="16dp"
- android:paddingHorizontal="26dp"
- android:layout_marginVertical="@dimen/gesture_tutorial_menu_done_button_margin"
+ android:layout_height="40dp"
+ android:layout_marginVertical="16dp"
android:text="@string/gesture_tutorial_action_button_label"
android:background="@drawable/gesture_tutorial_action_button_background"
android:stateListAnimator="@null"
diff --git a/quickstep/res/layout/gesture_tutorial_step_menu.xml b/quickstep/res/layout/gesture_tutorial_step_menu.xml
index 2836259..cf1e4d7 100644
--- a/quickstep/res/layout/gesture_tutorial_step_menu.xml
+++ b/quickstep/res/layout/gesture_tutorial_step_menu.xml
@@ -42,6 +42,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gesture_tutorial_home_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -79,6 +81,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gesture_tutorial_back_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -116,6 +120,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/gesture_tutorial_overview_step_shape"
+ android:scaleType="fitXY"
+ android:adjustViewBounds="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -147,9 +153,8 @@
style="@style/TextAppearance.GestureTutorial.ButtonLabel"
android:id="@+id/gesture_tutorial_menu_done_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingVertical="16dp"
- android:paddingHorizontal="26dp"
+ android:layout_height="40dp"
+ android:layout_marginVertical="16dp"
android:text="@string/gesture_tutorial_action_button_label"
android:background="@drawable/gesture_tutorial_action_button_background"
android:stateListAnimator="@null"
diff --git a/quickstep/res/layout/taskbar_edu_features.xml b/quickstep/res/layout/taskbar_edu_features.xml
index 5cd7aaf..efbe7f8 100644
--- a/quickstep/res/layout/taskbar_edu_features.xml
+++ b/quickstep/res/layout/taskbar_edu_features.xml
@@ -13,29 +13,36 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
style="@style/TextAppearance.TaskbarEduTooltip.Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/taskbar_edu_tooltip_vertical_margin"
android:text="@string/taskbar_edu_features"
+
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/splitscreen_animation"/>
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/splitscreen_animation"
android:layout_width="@dimen/taskbar_edu_features_lottie_width"
android:layout_height="@dimen/taskbar_edu_features_lottie_height"
- android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/title"
+
app:lottie_autoPlay="true"
- app:lottie_loop="true" />
+ app:lottie_loop="true"
+
+ app:layout_constraintEnd_toEndOf="@id/splitscreen_text"
+ app:layout_constraintStart_toStartOf="@id/splitscreen_text"
+ app:layout_constraintTop_toBottomOf="@id/title" />
<TextView
android:id="@+id/splitscreen_text"
@@ -43,8 +50,9 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/taskbar_edu_splitscreen"
- app:layout_constraintEnd_toEndOf="@id/splitscreen_animation"
- app:layout_constraintStart_toStartOf="@id/splitscreen_animation"
+
+ app:layout_constraintEnd_toStartOf="@id/settings_text"
+ app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/splitscreen_animation" />
<androidx.constraintlayout.widget.Group
@@ -57,13 +65,14 @@
android:id="@+id/settings_animation"
android:layout_width="@dimen/taskbar_edu_features_lottie_width"
android:layout_height="@dimen/taskbar_edu_features_lottie_height"
- android:layout_marginStart="@dimen/taskbar_edu_features_horizontal_spacing"
- android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
- app:layout_constraintStart_toEndOf="@id/splitscreen_animation"
- app:layout_constraintTop_toBottomOf="@id/title"
+
app:lottie_autoPlay="true"
app:lottie_loop="true"
- app:lottie_rawRes="@raw/taskbar_edu_settings" />
+ app:lottie_rawRes="@raw/taskbar_edu_settings"
+
+ app:layout_constraintEnd_toEndOf="@id/settings_text"
+ app:layout_constraintStart_toStartOf="@id/settings_text"
+ app:layout_constraintTop_toBottomOf="@id/title" />
<TextView
android:id="@+id/settings_text"
@@ -71,21 +80,23 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/taskbar_edu_settings_persistent"
- app:layout_constraintEnd_toEndOf="@id/settings_animation"
- app:layout_constraintStart_toStartOf="@id/settings_animation"
+ android:layout_marginStart="@dimen/taskbar_edu_features_horizontal_spacing"
+
+ app:layout_constraintEnd_toStartOf="@id/suggestions_text"
+ app:layout_constraintStart_toEndOf="@id/splitscreen_text"
app:layout_constraintTop_toBottomOf="@id/settings_animation" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/suggestions_animation"
android:layout_width="@dimen/taskbar_edu_features_lottie_width"
android:layout_height="@dimen/taskbar_edu_features_lottie_height"
- android:layout_marginStart="@dimen/taskbar_edu_features_horizontal_spacing"
- android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toEndOf="@id/settings_animation"
- app:layout_constraintTop_toBottomOf="@id/title"
+
app:lottie_autoPlay="true"
- app:lottie_loop="true" />
+ app:lottie_loop="true"
+
+ app:layout_constraintEnd_toEndOf="@id/suggestions_text"
+ app:layout_constraintStart_toStartOf="@id/suggestions_text"
+ app:layout_constraintTop_toBottomOf="@id/title" />
<TextView
android:id="@+id/suggestions_text"
@@ -93,8 +104,10 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/taskbar_edu_suggestions"
- app:layout_constraintEnd_toEndOf="@id/suggestions_animation"
- app:layout_constraintStart_toStartOf="@id/suggestions_animation"
+ android:layout_marginStart="@dimen/taskbar_edu_features_horizontal_spacing"
+
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@id/settings_text"
app:layout_constraintTop_toBottomOf="@id/suggestions_animation" />
<androidx.constraintlayout.widget.Barrier
@@ -108,11 +121,12 @@
android:id="@+id/done_button"
style="@style/TaskbarEdu.Button.Done"
android:layout_width="wrap_content"
- android:layout_height="36dp"
+ android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/taskbar_edu_done"
android:textColor="?androidprv:attr/textColorOnAccent"
+
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/edu_barrier_bottom" />
-</merge>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_edu_swipe.xml b/quickstep/res/layout/taskbar_edu_swipe.xml
index ebdfbb1..3f5e819 100644
--- a/quickstep/res/layout/taskbar_edu_swipe.xml
+++ b/quickstep/res/layout/taskbar_edu_swipe.xml
@@ -13,8 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
@@ -39,4 +41,4 @@
app:lottie_loop="true"
app:lottie_rawRes="@raw/taskbar_edu_stashing" />
-</merge>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_edu_tooltip.xml b/quickstep/res/layout/taskbar_edu_tooltip.xml
index 657066c..f3da8b0 100644
--- a/quickstep/res/layout/taskbar_edu_tooltip.xml
+++ b/quickstep/res/layout/taskbar_edu_tooltip.xml
@@ -17,7 +17,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
- android:layout_marginBottom="16dp"
+ android:layout_marginHorizontal="24dp"
+ android:paddingBottom="16dp"
android:clipChildren="false"
android:clipToPadding="false"
android:focusable="true"
@@ -25,7 +26,7 @@
android:gravity="center"
android:orientation="vertical">
- <androidx.constraintlayout.widget.ConstraintLayout
+ <FrameLayout
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml
index 62c6933..bf4b811 100644
--- a/quickstep/res/layout/transient_taskbar.xml
+++ b/quickstep/res/layout/transient_taskbar.xml
@@ -38,6 +38,20 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
+ <com.android.launcher3.taskbar.bubbles.BubbleBarView
+ android:id="@+id/taskbar_bubbles"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/bubblebar_size"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="@dimen/transient_taskbar_bottom_margin"
+ android:layout_marginBottom="@dimen/transient_taskbar_bottom_margin"
+ android:paddingEnd="@dimen/taskbar_icon_spacing"
+ android:paddingStart="@dimen/taskbar_icon_spacing"
+ android:visibility="gone"
+ android:gravity="center"
+ android:clipChildren="false"
+ />
+
<FrameLayout
android:id="@+id/navbuttons_view"
android:layout_width="match_parent"
@@ -74,10 +88,20 @@
<com.android.launcher3.taskbar.StashedHandleView
android:id="@+id/stashed_handle"
tools:comment1="The actual size and shape will be set as a ViewOutlineProvider at runtime"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/taskbar_stashed_handle_dark_color"
android:clipToOutline="true"
android:layout_gravity="bottom"/>
+ <com.android.launcher3.taskbar.StashedHandleView
+ android:id="@+id/stashed_bubble_handle"
+ tools:comment1="The actual size and shape will be set as a ViewOutlineProvider at runtime"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:background="@color/taskbar_stashed_handle_dark_color"
+ android:clipToOutline="true"
+ android:layout_gravity="bottom"/>
+
</com.android.launcher3.taskbar.TaskbarDragLayer>
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index bca1e8c..2dc0a1e 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk word gewys"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is versteek"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigasiebalk"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Wys Taakbalk altyd"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Verander navigasiemodus"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taakbalkverdeler"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Skuif na links bo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Skuif na regs onder"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 50efb01..36a8bda 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"የተግባር አሞሌ ይታያል"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"የተግባር አሞሌ ተደብቋል"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"የአሰሳ አሞሌ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ሁልጊዜ የተግባር አሞሌ ያሳዩ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"የአሰሳ ሁነታን ይለውጡ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"የተግባር አሞሌ አካፋይ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ወደ ላይ/ግራ ይውሰዱ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ወደ ታች/ቀኝ ይውሰዱ"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 560f1c2..4e3cd17 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"تم إظهار شريط التطبيقات"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"تم إخفاء شريط التطبيقات"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"شريط التنقل"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"إظهار شريط التطبيقات دائمًا"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"تغيير وضع التنقل"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"مقسِّم شريط التطبيقات"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"الانتقال إلى يمين الشاشة أو أعلاها"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"الانتقال إلى يسار الشاشة أو أسفلها"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 825a396..aab660d 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"টাস্কবাৰ দেখুওৱা হৈছে"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"টাস্কবাৰ লুকুৱাই থোৱা হৈছে"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"নেভিগেশ্বনৰ দণ্ড"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"টাস্কবাৰ সদায় দেখুৱাওক"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"নেভিগেশ্বন ম’ড সলনি কৰক"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"টাস্কবাৰ বিভাজক"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ওপৰৰ বাঁওফাললৈ নিয়ক"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"তলৰ সোঁফাললৈ নিয়ক"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আৰু # টা এপ্ দেখুৱাওক।}one{আৰু # টা এপ্ দেখুৱাওক।}other{আৰু # টা এপ্ দেখুৱাওক।}}"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 0962991..d6cf4ac 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"İşləmə paneli göstərilir"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"İşləmə paneli gizlədilib"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Naviqasiya paneli"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"İşləmə paneli həmişə görünsün"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Naviqasiya rejimini dəyişin"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"İşləmə paneli ayırıcısı"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Yuxarı/sola köçürün"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Aşağı/sağa köçürün"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 23dd072..9fc7a74 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Rotirajte ekran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Uputstva na traci zadataka"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Prevucite na stranu da biste koristili 2 aplikacije odjednom"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Nakratko prevucite nagore da biste prikazali traku zadataka"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Sporo prevucite nagore da biste prikazali traku zadataka"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dobijajte predloge aplikacija na osnovu rutine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Uključite navigaciju pomoću pokreta u Podešavanjima radi automatskog skrivanja trake zadataka"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je skrivena"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Traka za navigaciju"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Uvek prikazuj traku zadataka"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Promeni režim navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdelnik trake zadataka"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premesti gore levo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premesti dole desno"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index a5c218b..685c921 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Панэль задач паказана"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панэль задач схавана"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панэль навігацыі"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Заўсёды паказваць панэль задач"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Змяніць рэжым навігацыі"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Раздзяляльнік панэлі задач"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перамясціць уверх/улева"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 1222afa..ad87573 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Лентата на задачите се показва"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Лентата на задачите е скрита"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигация"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Лентата на задачите винаги да се показва"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Промяна на режима на навигация"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделител на лентата на задачите"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Преместване горе/вляво"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Преместване долу/вдясно"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 8f9fbee..97dbeae 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"\'টাস্কবার\' দেখানো হয়েছে"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"\'টাস্কবার\' লুকানো রয়েছে"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"নেভিগেশন বার"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"সবসময় টাস্কবার দেখুন"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"\'নেভিগেশন\' মোড পরিবর্তন করুন"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"টাস্কবার ডিভাইডার"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"উপরে/বাঁদিকে সরান"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"নিচে/ডানদিকে সরান"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 691c720..fea5b6a 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je sakrivena"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigaciona traka"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdjelnik trake zadataka"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore lijevo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje desno"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 919712a..011b121 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -97,11 +97,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Omet"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Gira la pantalla"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informació sobre Barra de tasques"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrossega una app al costat per utilitzar 2 apps alhora"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Arrossega una aplicació al costat per utilitzar-ne dues alhora"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Llisca lentament cap amunt per mostrar la Barra de tasques"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtén suggeriments d\'aplicacions basats en la teva rutina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"A Configuració, activa la navegació amb gestos per amagar la Barra de tasques automàticament"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Fes més coses amb la Barra de tasques"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Treu més partit de la Barra de tasques"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Tanca"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Fet"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Inici"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Es mostra la Barra de tasques"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"S\'ha amagat la Barra de tasques"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegació"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mostra sempre Barra de tasques"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Canvia el mode de navegació"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separador de la Barra de tasques"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mou a la part superior o a l\'esquerra"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mou a la part inferior o a la dreta"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 5ac7e7e..c27585a 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -99,9 +99,9 @@
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informace o panelu aplikací"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Přetáhněte aplikaci na stranu a používejte tak dvě najednou"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Panel aplikací zobrazíte pomalým přejetím prstem nahoru"</string>
- <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Získejte návrhy aplikací na základě vašeho používání"</string>
+ <string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Dostávejte návrhy aplikací podle toho, jaké používáte"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Pokud chcete panel aplikací automaticky skrýt, zapněte v Nastavení navigaci gesty"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Pomocí panelu aplikací můžete dělat více věcí"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Více možností s panelem aplikací"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zavřít"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Domů"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikací je zobrazen"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikací je skrytý"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigační panel"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vždy zobrazovat panel aplikací"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Změnit režim navigace"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Rozdělovač panelu aplikací"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Přesunout doleva nahoru"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Přesunout doprava dolů"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index d0cea4c..bde4fe1 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Proceslinjen vises"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Proceslinjen er skjult"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationslinje"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vis altid proceslinjen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Skift navigationstilstand"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Opdeling af proceslinjen"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flyt til toppen eller venstre side"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flyt til bunden eller højre side"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 0e959a4..a5766f7 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskleiste eingeblendet"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskleiste ausgeblendet"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationsleiste"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Taskleiste immer anzeigen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigationsmodus ändern"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskleisten-Teiler"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Nach oben / Nach links verschieben"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Nach unten / Nach rechts verschieben"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# weitere App anzeigen.}other{# weitere Apps anzeigen.}}"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 0fa67fe..03774c2 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Η γραμμή εργαλείων εμφανίζεται"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Η γραμμή εργαλείων είναι κρυφή"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Γραμμή πλοήγησης"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Εμφ. πάντα σε Γραμμή εργαλείων"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Αλλαγή τρόπου πλοήγησης"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Διαχωριστικό Γραμμής εργαλείων"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Μετακίνηση επάνω/αριστερά"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Μετακίνηση κάτω/δεξιά"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index ec90faf..f5d7e73 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 01599c4..9adb0f4 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar Divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index ec90faf..f5d7e73 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index ec90faf..f5d7e73 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index c8f344e..853684d 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar hidden"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Always show Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Change navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Taskbar Divider"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Move to top/left"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index eb2a296..e31466a 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -101,7 +101,7 @@
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Desliza despacio hacia arriba para ver la Barra de tareas"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Recibe sugerencias de aplicaciones basadas en tu rutina"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activa la navegación por gestos en la Configuración y la Barra de tareas se ocultará sola"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Haz más con la Barra de tareas"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Aprovecha mejor la Barra de tareas"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Botón de inicio"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Ver siempre la Barra de tareas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor de la Barra de tareas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover a la parte superior o izquierda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover a la parte inferior o derecha"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index d8beb80..43fe5b1 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Ver siempre Barra de Tareas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor de Barra de Tareas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover arriba/a la izquierda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover abajo/a la derecha"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 1594337..0095d51 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tegumiriba on kuvatud"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tegumiriba on peidetud"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigeerimisriba"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Kuva tööriistariba alati"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigeerimisrežiimi muutmine"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Tegumiriba jagaja"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Teisalda üles/vasakule"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Teisalda alla/paremale"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 1eba2b7..9f6e8e1 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Biratu pantaila"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Zereginen barra erabiltzeko argibideak"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Bi aplikazio batera erabiltzeko, arrastatu bat albo batera"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Zereginen barra ikusteko, pasatu hatza motel gora"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Zereginen barra ikusteko, pasatu hatza gora poliki"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Jaso aplikazioen iradokizunak erabileran oinarrituta"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Zereginen barra automatikoki ezkutatzeko, aktibatu keinu bidezko nabigazioa ezarpenetan"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Egin gauza gehiago zereginen barrarekin"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Zereginen barra ikusgai dago"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Zereginen barra itxita dago"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Nabigazio-barra"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Erakutsi beti zereginen barra"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Aldatu nabigatzeko modua"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Zereginen barraren zatitzailea"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Eraman gora, ezkerretara"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Eraman behera, eskuinetara"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 1a35f9c..e520acd 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"نوار وظیفه نمایان است"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"نوار وظیفه پنهان است"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"نوار پیمایش"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"نوار وظیفه همیشه نشان داده شود"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"تغییر حالت پیمایش"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"جداکننده نوار وظیفه"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"انتقال به بالا/ چپ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"انتقال به پایین/ راست"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 428011b..5c04d68 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -97,7 +97,7 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Ohita"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Käännä näyttö"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tehtäväpalkin ohje"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Vedä sovellus sivuun, niin voit käyttää samalla 2 sellaista"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Vedä sovellus sivuun, ja voit käyttää kahta sovellusta"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Näytä tehtäväpalkki pyyhkäisemällä ylös hitaasti"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Sovellussuosituksia käytön perusteella"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Laita eleillä navigointi päälle Asetuksista Tehtäväpalkin piilottamiseksi automaattisesti"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tehtäväpalkki näkyvissä"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tehtäväpalkki piilotettu"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigointipalkki"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Näytä tehtäväpalkki aina"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Vaihda navigointitilaa"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Tehtäväpalkin jakaja"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Siirrä ylös tai vasemmalle"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Siirrä alas tai oikealle"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index af89ae5..56e5047 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Touj. afficher barre des tâches"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Changer de mode de navigation"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Séparateur de la barre des tâches"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer vers le coin supérieur gauche de l\'écran"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer vers le coin inférieur droit de l\'écran"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 3b08b89..31068f7 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -97,8 +97,8 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Passer"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Faire pivoter l\'écran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Fonctionnement de la barre des tâches"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Faites glisser une appli sur le côté pour utiliser 2 applis"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Balayez lentement vers le haut pour l\'afficher"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Faites glisser une appli sur le côté pour en utiliser 2 à la fois"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Balayez lentement vers haut pour afficher barre des tâches"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Obtenez des suggestions d\'applis basées sur vos habitudes"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Activez la navigation par gestes dans paramètres pour masquage auto de la barre des tâches"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Toujours voir barre des tâches"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Modifier le mode de navigation"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Séparateur de barre des tâches"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer en haut ou à gauche"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer en bas ou à droite"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre appli.}one{Afficher # autre appli.}other{Afficher # autre applis.}}"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index d5e7550..ebec206 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Estase mostrando a barra de tarefas"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Non se está mostrando a barra de tarefas"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Manter Barra de tarefas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar modo de navegación"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover á parte superior ou á esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover á parte inferior ou á dereita"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 0924b68..2e1c289 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ટાસ્કબાર બતાવવામાં આવ્યો"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ટાસ્કબાર છુપાવવામાં આવ્યો"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"નૅવિગેશન બાર"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"હંમેશાં ટાસ્કબાર બતાવો"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"નૅવિગેશન મોડ બદલો"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ટાસ્કબાર વિભાજક"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"સૌથી ઉપર ડાબી બાજુએ ખસેડો"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"સૌથી નીચે જમણી બાજુએ ખસેડો"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index b108371..2dc6603 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करना"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करें"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ़्रीफ़ॉर्म"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"हाल ही में इस्तेमाल किया गया कोई ऐप्लिकेशन नहीं है"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"टास्कबार दिखाया गया"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार छिपाया गया"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेविगेशन बार"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार हमेशा दिखाएं"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"नेविगेशन का मोड बदलें"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार डिवाइडर"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ऊपर/बाईं तरफ़ ले जाएं"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"नीचे/दाईं तरफ़ ले जाएं"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 1aadeea..2a18704 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -97,11 +97,11 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskoči"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Zakretanje zaslona"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Upute za traku sa zadacima"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povucite apl. u stranu radi istodobne upotrebe 2 aplikacije"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povucite aplikaciju u stranu radi istodobne upotrebe dviju aplikacija"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Polako prijeđite prstom prema gore za prikaz trake sa zadacima"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Primajte prijedloge aplikacija na temelju svoje rutine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Uključite navigaciju pokretima u postavkama da bi se traka sa zadacima automatski sakrila"</string>
- <string name="taskbar_edu_features" msgid="3320337287472848162">"Učinite više uz pomoć trake sa zadacima"</string>
+ <string name="taskbar_edu_features" msgid="3320337287472848162">"Učinite više pomoću trake sa zadacima"</string>
<string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
<string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
<string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka sa zadacima prikazana"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka sa zadacima skrivena"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigacijska traka"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdjelnik trake sa zadacima"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore/lijevo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje/desno"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži više aplikacija (još #).}one{Prikaži više aplikacija (još #).}few{Prikaži više aplikacija (još #).}other{Prikaži više aplikacija (još #).}}"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index ba75d4f..27f5efa 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Képernyő elforgatása"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Tálca használatának ismertetése"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Húzzon egy appot oldalra, ha kettőt használna egyidejűleg"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Csúsztassa ujját lassan fel a Feladatsáv megjelenítéséhez"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Lassan csúsztassa fel az ujját a Feladatsáv megjelenítéséhez"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Alkalmazásjavaslatokat kaphat a rutinja alapján"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"A Feladatsáv automatikus elrejtéséhez aktiválja a navigációs kézmozdulatokat a beállításokban"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Jobban kihasználhatja a Feladatsávot"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Feladatsáv megjelenítve"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Feladatsáv elrejtve"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigációs sáv"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mindig megjelenő feladatsáv"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigációs mód módosítása"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Feladatsáv-elválasztó"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mozgatás felülre vagy a bal oldalra"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mozgatás alulra vagy a jobb oldalra"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 43a7c5d..80e6750 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Խնդրագոտին ցուցադրվում է"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Խնդրագոտին թաքցված է"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Նավիգացիայի գոտի"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Միշտ ցուցադրել հավելվածները"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Փոխել նավիգացիայի ռեժիմը"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Հավելվածների վահանակի բաժանիչ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Տեղափոխել վերևի ձախ անկյուն"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Տեղափոխել ներքևի աջ անկյուն"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 6f9d7c6..db880b3 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ditampilkan"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar disembunyikan"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Menu navigasi"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Selalu tampilkan Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Ubah mode navigasi"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Pemisah Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pindahkan ke atas/kiri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pindahkan ke bawah/kanan"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tampilkan # aplikasi lain.}other{Tampilkan # aplikasi lain.}}"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index f58e6de..08b5e99 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Forritastika sýnd"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Forritastika falin"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Yfirlitsstika"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Alltaf sýna forritastiku"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Breyta leiðsagnarstillingu"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Skipting forritastiku"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Færa efst/til vinstri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Færa neðst/til hægri"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 17e379f..6f2f954 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra delle app visualizzata"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra delle app nascosta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra di navigazione"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mostra sempre barra delle app"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Cambia modalità di navigazione"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisore barra delle app"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sposta in alto/a sinistra"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sposta in basso/a destra"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index dc30dc6..e158869 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"סרגל האפליקציות מוצג"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"סרגל האפליקציות מוסתר"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"סרגל הניווט"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"סרגל האפליקציות מוצג תמיד"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"שינוי מצב הניווט"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"המחיצה בסרגל האפליקציות"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"העברה לפינה השמאלית/העליונה"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"העברה לפינה הימנית/התחתונה"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 75e3bf8..d55a2c0 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"タスクバー表示"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"タスクバー非表示"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ナビゲーション バー"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"常にタスクバーを表示"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ナビゲーション モードを変更"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"タスクバーの区切り"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"上 / 左に移動"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"下 / 右に移動"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 13232da..c1df53c 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ამოცანათა ზოლი ნაჩვენებია"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ამოცანათა ზოლი დამალულია"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ნავიგაციის ზოლი"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ამოცანათა ზოლის მუდამ ჩვენება"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"შეცვალეთ ნავიგაციის რეჟიმი"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ამოცანათა ზოლის გამყოფი"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ზემოთ/მარცხნივ გადატანა"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ქვემოთ/მარჯვნივ გადატანა"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 9f006a9..68141aa 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Тапсырмалар жолағы көрсетілді"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапсырмалар жолағы жасырылды"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигация жолағы"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Тапсырма жолағын үнемі көрсету"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Навигация режимін өзгерту"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Тапсырмалар жолағын бөлгіш"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жоғары/солға жылжыту"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 738e454..aa20709 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"បានបង្ហាញរបារកិច្ចការ"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"បានលាក់របារកិច្ចការ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"របាររុករក"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"បង្ហាញរបារកិច្ចការជានិច្ច"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ប្ដូរមុខងាររុករក"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"បន្ទាត់ខណ្ឌចែករបារកិច្ចការ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ផ្លាស់ទីទៅខាងលើ/ឆ្វេង"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញកម្មវិធី # ទៀត។}}"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 37e0acd..9bb18fa 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ಟಾಸ್ಕ್ಬಾರ್ ತೋರಿಸಲಾಗಿದೆ"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ಟಾಸ್ಕ್ಬಾರ್ ಮರೆಮಾಡಲಾಗಿದೆ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ಯಾವಾಗಲೂ ಟಾಸ್ಕ್ಬಾರ್ ತೋರಿಸಿ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ನ್ಯಾವಿಗೇಶನ್ ಮೋಡ್ ಬದಲಾಯಿಸಿ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ಟಾಸ್ಕ್ಬಾರ್ ಡಿವೈಡರ್"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ಮೇಲಿನ/ಎಡಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ಕೆಳಗಿನ/ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index cff87a1..4cef3ca 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"태스크 바 표시"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"태스크 바 숨김"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"탐색 메뉴"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"태스크 바 항상 표시"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"탐색 모드 변경"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"태스크 바 분할"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"상단/왼쪽으로 이동"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"하단/오른쪽으로 이동"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 4cb31fd..64a1c90 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -49,7 +49,7 @@
<string name="back_gesture_feedback_complete_with_overview_follow_up" msgid="9176400654037014471">"Артка кайтуу үчүн экранды оңдон солго карай сүрүүнү үйрөндүңүз. Эми колдонмолорду которуштурганды үйрөнүп алыңыз."</string>
<string name="back_gesture_feedback_complete_without_follow_up" msgid="6405649621667113830">"\"Артка\" жаңсоосун үйрөндүңүз."</string>
<string name="back_gesture_feedback_swipe_in_nav_bar" msgid="1148198467090405643">"Манжаңызды экрандын ылдый жагына өтө жакындатпай сүрүңүз."</string>
- <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"\"Артка\" жаң-нун сезгичтигин өзгөртүү үчүн жөндөөлөргө өтүңүз"</string>
+ <string name="back_gesture_tutorial_confirm_subtitle" msgid="5181305411668713250">"\"Артка\" жаң-нун сезгичтигин өзгөртүү үчүн параметрлерге өтүңүз"</string>
<string name="back_gesture_intro_title" msgid="19551256430224428">"Артка кайтуу үчүн сүрүңүз"</string>
<string name="back_gesture_intro_subtitle" msgid="7912576483031802797">"Акыркы экранга кайтуу үчүн экранды сол же оң жагынан ортосуна карай сүрүңүз."</string>
<string name="back_gesture_spoken_intro_subtitle" msgid="2162043199263088592">"Акыркы экранга кайтуу үчүн экранды сол же оң жагынан ортосуна карай 2 манжаңыз менен сүрүңүз."</string>
@@ -67,7 +67,7 @@
<string name="overview_gesture_feedback_swipe_too_far_from_edge" msgid="3032757898111577225">"Экранды ылдыйдан өйдө сүрүңүз."</string>
<string name="overview_gesture_feedback_home_detected" msgid="1411130969354020489">"Манжаңызды алуудан мурун экранда узагыраак кармаңыз."</string>
<string name="overview_gesture_feedback_wrong_swipe_direction" msgid="6725820500906747925">"Экранды өйдө карай сүрүп, токтоп туруңуз."</string>
- <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Жаңсоолорду колдонгонду үйрөндүңүз. Жаңсоолорду өчүрүү үчүн жөндөөлөргө өтүңүз."</string>
+ <string name="overview_gesture_feedback_complete_with_follow_up" msgid="3544611727467765026">"Жаңсоолорду колдонгонду үйрөндүңүз. Жаңсоолорду өчүрүү үчүн параметрлерге өтүңүз."</string>
<string name="overview_gesture_feedback_complete_without_follow_up" msgid="3199486203448379152">"\"Колдонмолорду которуштуруу\" жаңсоосун үйрөндүңүз."</string>
<string name="overview_gesture_intro_title" msgid="2902054412868489378">"Колдонмолорду которуштуруу үчүн сүрүңүз"</string>
<string name="overview_gesture_intro_subtitle" msgid="4968091015637850859">"Бир колдонмодон экинчисине өтүү үчүн экранды ылдыйдан өйдө карай сүрүп, бир аз коё бербей туруңуз."</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Тапшырмалар панели көрсөтүлдү"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Тапшырмалар панели жашырылды"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Чабыттоо тилкеси"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Тапшырмалар панелин ар дайым көрсөтүү"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Өтүү режимин өзгөртүү"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Тапшырмалар панелин бөлгүч"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жогорку/сол бурчка жылдыруу"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмөнкү/оң бурчка жылдыруу"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index be5d894..72201f2 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ແຖບໜ້າວຽກທີ່ສະແດງຢູ່"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ແຖບໜ້າວຽກທີ່ເຊື່ອງໄວ້ຢູ່"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ແຖບການນຳທາງ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ສະແດງແຖບໜ້າວຽກສະເໝີ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ປ່ຽນໂໝດການນຳທາງ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ເສັ້ນແບ່ງແຖບໜ້າວຽກ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ຍ້າຍໄປຊ້າຍ/ເທິງ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ຍ້າຍໄປຂວາ/ລຸ່ມ"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 06c4f79..ba0df27 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Užduočių juosta rodoma"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Užduočių juosta paslėpta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Naršymo juosta"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Visada rodyti užduočių juostą"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Keisti naršymo režimą"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Užduočių juostos daliklis"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Perkelti aukštyn, kairėn"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Perkelti žemyn, dešinėn"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 9ab8259..3992ebd 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Uzdevumu josla tiek rādīta"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Uzdevumu josla paslēpta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigācijas josla"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vienmēr rādīt uzdevumu joslu"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Mainīt navigācijas režīmu"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Uzdevumu joslas atdalītājs"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pārvietot uz augšējo/kreiso stūri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pārvietot uz apakšējo/labo stūri"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index bd6b12a..8e11a2d 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Лентата со задачи е прикажана"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Лентата со задачи е сокриена"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигација"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Секогаш прикажувај „Лента“"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Променете режим на навигација"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделник на „Лента со задачи“"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести долу десно"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 74fdd75..ab77317 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ടാസ്ക്ബാർ കാണിച്ചിരിക്കുന്നു"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ടാസ്ക്ബാർ മറച്ചിരിക്കുന്നു"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"നാവിഗേഷൻ ബാർ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ടാസ്ക്ബാർ എപ്പോഴും കാണിക്കൂ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"നാവിഗേഷൻ മോഡ് മാറ്റുക"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ടാസ്ക്ബാർ ഡിവൈഡർ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"താഴേക്കോ വലത്തേക്കോ നീക്കുക"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 7c6314e..40d14f4 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -23,7 +23,7 @@
<string name="recent_task_option_freeform" msgid="48863056265284071">"Чөлөөтэй хувьсах"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Сүүлийн үеийн зүйл алга"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Апп ашиглалтын тохиргоо"</string>
- <string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг устгах"</string>
+ <string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг арилгах"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Саяхны аппууд"</string>
<string name="task_view_closed" msgid="9170038230110856166">"Ажлыг хаасан"</string>
<string name="task_contents_description_with_remaining_time" msgid="4479688746574672685">"<xliff:g id="TASK_DESCRIPTION">%1$s</xliff:g>, <xliff:g id="REMAINING_TIME">%2$s</xliff:g>"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ажлын хэсгийг харуулсан"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ажлын хэсгийг нуусан"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигацын самбар"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Ажлын хэсгийг үргэлж харуулах"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Навигацын горимыг өөрчлөх"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Ажлын хэсгийг хуваагч"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Зүүн дээд хэсэг рүү зөөх"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Баруун доод хэсэг рүү зөөх"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index cfaf2d8..c2ddaf5 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"टास्कबार दाखवलेला आहे"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार लपवलेले आहे"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेव्हिगेशन बार"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"नेहमी टास्कबार दाखवा"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"नेव्हिगेशन मोड बदला"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार विभाजक"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सर्वात वरती/डावीकडे हलवा"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"तळाशी/उजवीकडे हलवा"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{आणखी # अॅप दाखवा.}other{आणखी # अॅप्स दाखवा.}}"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 4ed6493..129462d 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bar Tugas dipaparkan"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bar Tugas disembunyikan"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Bar navigasi"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Sentiasa paparkan Bar Tugas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Tukar mod navigasi"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Pembahagi Bar Tugas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Alihkan ke atas/kiri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Alihkan ke bawah/kanan"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 617473c..287e4a0 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ပြထားသည်"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar ဖျောက်ထားသည်"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"လမ်းညွှန်ဘား"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"‘လုပ်ဆောင်စရာဘား’ အမြဲပြပါ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ရွှေ့ကြည့်သည့်မုဒ် ပြောင်းရန်"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"လုပ်ဆောင်စရာဘား ပိုင်းခြားစနစ်"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"အပေါ်/ဘယ်ဘက်သို့ ရွှေ့ရန်"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"အောက်ခြေ/ညာဘက်သို့ ရွှေ့ရန်"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index e4d75be..064eaf3 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Oppgavelinjen vises"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Oppgavelinjen er skjult"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigasjonsrad"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Vis alltid oppgavelinjen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Endre navigasjonsmodus"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Skille for oppgavelinjen"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytt til øverst/venstre"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytt til nederst/høyre"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app til.}other{Vis # apper til.}}"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index b9e8e1c..f4df28b 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"टास्कबार देखाइएको छ"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"टास्कबार लुकाइएको छ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेभिगेसन बार"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार सधैँ देखाइयोस्"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"नेभिगेसन मोड बदल्नुहोस्"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार डिभाइडर"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सिरान/बायाँतिर सार्नुहोस्"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"फेद/दायाँतिर सार्नुहोस्"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{थप # एप देखाइयोस्।}other{थप # वटा एप देखाइयोस्।}}"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index f2a9d88..140b4ae 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Scherm draaien"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Taakbalk Onderwijs"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Sleep een app naar de zijkant om 2 apps tegelijk te gebruiken"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Swipe kort omhoog om de taakbalk te tonen"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Swipe langzaam omhoog om de taakbalk te tonen"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Krijg app-suggesties op basis van je routine"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Zet navigatie met gebaren aan bij Instellingen om de Taakbalk automatisch te verbergen"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Doe meer met de taakbalk"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk wordt getoond"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is verborgen"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigatiebalk"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Taakbalk altijd tonen"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigatiemodus wijzigen"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Scheiding voor Taakbalk"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Naar boven/links verplaatsen"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Naar beneden/rechts verplaatsen"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 2affa6f..5a04d97 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ଟାସ୍କବାର ଦେଖାଯାଇଛି"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ଟାସ୍କବାର ଲୁଚାଯାଇଛି"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ନାଭିଗେସନ ବାର"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ସର୍ବଦା ଟାସ୍କବାର ଦେଖାନ୍ତୁ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ନାଭିଗେସନ ମୋଡ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ଟାସ୍କବାର ଡିଭାଇଡର"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ଶୀର୍ଷ/ବାମକୁ ମୁଭ କରନ୍ତୁ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ନିମ୍ନ/ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index df9cc35..939f699 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ਟਾਸਕਬਾਰ ਨੂੰ ਦਿਖਾਇਆ ਗਿਆ"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ਟਾਸਕਬਾਰ ਨੂੰ ਲੁਕਾਇਆ ਗਿਆ"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ਨੈਵੀਗੇਸ਼ਨ ਵਾਲੀ ਪੱਟੀ"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਓ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"ਨੈਵੀਗੇਸ਼ਨ ਮੋਡ ਬਦਲੋ"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ਟਾਸਕਬਾਰ ਵਿਭਾਜਕ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ਸਿਖਰਲੇ/ਖੱਬੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ਹੇਠਾਂ/ਸੱਜੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index f09e412..2ee14ff 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -88,7 +88,7 @@
<string name="action_share" msgid="2648470652637092375">"Udostępnij"</string>
<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">"Kliknij drugą aplikację, aby podzielić ekran"</string>
+ <string name="toast_split_select_app" msgid="8464310533320556058">"Aby podzielić ekran, kliknij drugą aplikację"</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>
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Obróć ekran"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Informacje o pasku aplikacji"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Przeciągnij aplikację w bok, aby używać 2 aplikacji naraz"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Przesuń palcem krótko w górę, aby wyświetlić pasek aplikacji"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Aby wyświetlić pasek aplikacji, przesuń palcem krótko w górę"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Otrzymuj sugestie aplikacji na podstawie rutyny"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Włącz nawigację przy użyciu gestów w Ustawieniach, aby automatycznie ukrywać pasek aplikacji"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Wykorzystaj potencjał paska aplikacji"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Pasek aplikacji widoczny"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Pasek aplikacji ukryty"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Pasek nawigacyjny"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Zawsze pokazuj pasek aplikacji"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Zmień tryb nawigacji"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Linia dzielenia paska aplikacji"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Przesuń w górny lewy róg"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Przesuń w dolny prawy róg"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 2b287b3..c5aad16 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas apresentada"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas ocultada"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegação"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Mostr. sempre Barra de tarefas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Alterar modo de navegação"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para a parte superior esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para a part superior direita"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 4092c06..8cf6837 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas visível"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas oculta"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegação"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Sempre mostrar a Barra de tarefas"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Mudar o modo de navegação"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separador da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para cima/para a esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para baixo/para a direita"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 003b867..8559f61 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bara de activități este afișată"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bara de activități este ascunsă"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Bară de navigare"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Afișează întotdeauna bara de activități"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Schimbă modul de navigare"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separator pentru bara de activități"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mută în stânga sus"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mută în dreapta jos"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 166fe7c..0634d8b 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Панель задач показана"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панель задач скрыта"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навигации"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Всегда показывать панель задач"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Изменить режим навигации"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделитель панели задач"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Переместить вверх или влево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Переместить вниз или вправо"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 1b850ef..376427b 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"කාර්ය තීරුව පෙන්වා ඇත"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"කාර්ය තීරුව සඟවා ඇත"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"සංචලන තීරුව"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"සෑම විටම කාර්ය තීරුව පෙන්වන්න"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"සංචාලන ප්රකාරය වෙනස් කරන්න"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"කාර්ය තීරු බෙදනය"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ඉහළ/වම වෙත ගෙන යන්න"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"පහළ/දකුණ වෙත ගෙන යන්න"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index b2dff2e..1577f4a 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -97,7 +97,7 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"Preskočiť"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Otočiť obrazovku"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Panel vzdelávacích aplikácií"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Ak chcete použ. dve aplikácie naraz, presuňte aplik. nabok"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Ak chcete použiť dve aplikácie naraz, presuňte aplikáciu nabok"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"Panel aplikácií zobrazíte pomalým potiahnutím nahor"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Získavajte návrhy aplikácií na základe svojich zvykov"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Ak chcete, aby sa panel aplikácií autom. skrýval, zapnite v Nastaveniach navigáciu gestami"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikácií je zobrazený"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikácií je skrytý"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigačný panel"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Zobrazovať panel aplikácií"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Zmeniť režim navigácie"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Rozdeľovač panela aplikácií"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Presunúť hore alebo doľava"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Presunúť dole alebo doprava"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index e0f1f92..38792bd 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Sukanje zaslona"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Poučni nasveti o opravilni vrstici"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Povlecite aplikacijo na stran za uporabo 2 aplikacij hkrati."</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Počasi povlecite navzgor za prikaz opravilne vrstice."</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Počasi povlecite navzgor za prikaz opravilne vrstice"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Prejemajte predloge aplikacij na podlagi svojih navad."</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"V nastavitvah vklopite krmarjenje s potezami, da se bo opravilna vrstica samodejno skrila."</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Naredite več z opravilno vrstico"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Opravilna vrstica je prikazana"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Opravilna vrstica je skrita"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Vrstica za krmarjenje"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Stalen prikaz opravilne vrstice"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Spreminjanje načina navigacije"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdelilnik opravilne vrstice"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premakni na vrh/levo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premakni na dno/desno"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index c0d550b..ad9f951 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Shiriti i detyrave i shfaqur"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Shiriti i detyrave i fshehur"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Shiriti i navigimit"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Shfaq gjithmonë shiritin e detyrave"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Ndrysho modalitetin e navigimit"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Ndarësi i shiritit të detyrave"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Lëviz në krye/majtas"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Lëviz në fund/djathtas"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 1780283..f443a68 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -98,7 +98,7 @@
<string name="accessibility_rotate_button" msgid="4771825231336502943">"Ротирајте екран"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"Упутства на траци задатака"</string>
<string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"Превуците на страну да бисте користили 2 апликације одједном"</string>
- <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Накратко превуците нагоре да бисте приказали траку задатака"</string>
+ <string name="taskbar_edu_stashing" msgid="5645461372669217294">"Споро превуците нагоре да бисте приказали траку задатака"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"Добијајте предлоге апликација на основу рутине"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"Укључите навигацију помоћу покрета у Подешавањима ради аутоматског скривања траке задатака"</string>
<string name="taskbar_edu_features" msgid="3320337287472848162">"Урадите више помоћу траке задатака"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Трака задатака је приказана"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Трака задатака је скривена"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Трака за навигацију"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Увек приказуј траку задатака"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Промени режим навигације"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделник траке задатака"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести доле десно"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 5e84675..738b362 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fäst"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
- <string name="recents_empty_message" msgid="7040467240571714191">"Listan med de senaste åtgärderna är tom"</string>
+ <string name="recents_empty_message" msgid="7040467240571714191">"Listan är tom"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Inställningar för appanvändning"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Rensa alla"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Senaste apparna"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Aktivitetsfältet visas"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Aktivitetsfältet är dolt"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigeringsfält"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Visa alltid aktivitetsfältet"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Ändra navigeringsläge"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Avdelare för aktivitetsfältet"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytta högst upp/till vänster"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytta längst ned/till höger"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Visa # app till.}other{Visa # appar till.}}"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index bc7cfb8..c5b588d 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Upauzana umeonyeshwa"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Upauzana umefichwa"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Sehemu ya viungo muhimu"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Onyesha Upauzana kila wakati"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Badilisha hali ya usogezaji"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Kitenganishi cha Upauzana"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sogeza juu/kushoto"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sogeza chini/kulia"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}"</string>
diff --git a/quickstep/res/values-sw600dp-land/dimens.xml b/quickstep/res/values-sw600dp-land/dimens.xml
index 9853140..9cb3fec 100644
--- a/quickstep/res/values-sw600dp-land/dimens.xml
+++ b/quickstep/res/values-sw600dp-land/dimens.xml
@@ -26,6 +26,5 @@
<dimen name="gesture_tutorial_menu_button_spacing">24dp</dimen>
<dimen name="gesture_tutorial_menu_done_button_top_spacing">40dp</dimen>
<dimen name="gesture_tutorial_menu_back_shape_bottom_margin">49dp</dimen>
- <dimen name="gesture_tutorial_menu_done_button_margin">16dp</dimen>
</resources>
diff --git a/quickstep/res/values-sw720dp-land/dimens.xml b/quickstep/res/values-sw720dp-land/dimens.xml
index 1d02ab5..4634a2d 100644
--- a/quickstep/res/values-sw720dp-land/dimens.xml
+++ b/quickstep/res/values-sw720dp-land/dimens.xml
@@ -21,7 +21,5 @@
<dimen name="gesture_tutorial_menu_button_spacing">49dp</dimen>
<dimen name="gesture_tutorial_menu_done_button_top_spacing">24dp</dimen>
<dimen name="gesture_tutorial_menu_back_shape_bottom_margin">21dp</dimen>
- <dimen name="gesture_tutorial_menu_done_button_spacing">80dp</dimen>
- <dimen name="gesture_tutorial_menu_done_button_margin">0dp</dimen>
</resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 5ccbc17..ea39749 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"செயல் பட்டி காட்டப்படுகிறது"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"செயல் பட்டி மறைக்கப்பட்டுள்ளது"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"வழிசெலுத்தல் பட்டி"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"செயல் பட்டியை எப்போதும் காட்டு"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"வழிசெலுத்தல் பயன்முறையை மாற்று"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"செயல் பட்டிப் பிரிப்பான்"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"மேலே/இடதுபுறம் நகர்த்தும்"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"கீழே/வலதுபுறம் நகர்த்தும்"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index ad0c851..9fe46ef 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_pin" msgid="7929860679018978258">"పిన్ చేయి"</string>
+ <string name="recent_task_option_pin" msgid="7929860679018978258">"పిన్ చేయండి"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"సంప్రదాయేతర"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"యాప్ వినియోగ సెట్టింగ్లు"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"టాస్క్బార్ చూపబడింది"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"టాస్క్బార్ దాచబడింది"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"నావిగేషన్ బార్"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ఎప్పుడూ టాస్క్బార్ చూపించండి"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"నావిగేషన్ మోడ్ను మార్చండి"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"టాస్క్బార్ డివైడర్"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ఎగువ/ఎడమ వైపునకు తరలించండి"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"దిగువ/కుడి వైపునకు తరలించండి"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{మరో # యాప్ను చూడండి.}other{మరో # యాప్లను చూడండి.}}"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 8cba9b9..fe8e37f 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"แถบงานแสดงอยู่"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"แถบงานซ่อนอยู่"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"แถบนำทาง"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"แสดงแถบงานเสมอ"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"เปลี่ยนโหมดการนําทาง"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ตัวแบ่งแถบงาน"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ย้ายไปที่ด้านบนหรือด้านซ้าย"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ย้ายไปที่ด้านล่างหรือด้านขวา"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}"</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index ae6dd45..bf62a38 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ipinapakita ang taskbar"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Nakatago ang taskbar"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigation bar"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Palaging ipakita ang Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Magpalit ng navigation mode"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divider ng Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Ilipat sa itaas/kaliwa"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Ilipat sa ibaba/kanan"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index e5d5b6d..772ad8b 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Görev çubuğu gösteriliyor"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Görev çubuğu gizlendi"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Gezinme çubuğu"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Görev çubuğunu daima göster"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Gezinme modunu değiştir"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Görev Çubuğu Ayırıcısı"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Sol üste taşı"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sağ alta taşı"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 36c5bbb..0104798 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Панель завдань показано"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Панель завдань приховано"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навігації"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Завжди показув. панель завдань"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Змінити режим навігації"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Розділювач панелі завдань"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перемістити вгору або вліво"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перемістити вниз або вправо"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 9d1efe4..7e9b34c 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ٹاشک بار دکھایا گیا"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ٹاسک بار چھپایا گیا"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"نیویگیشن بار"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"ہمیشہ ٹاسک بار دکھائیں"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"نیویگیشن موڈ تبدیل کریں"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ٹاسک بار ڈیوائیڈر"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"اوپر/بائیں طرف منتقل کریں"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"نیچے/دائیں طرف منتقل کریں"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index cf70ebd..73ad2f3 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Vazifalar paneli ochiq"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Vazifalar paneli yopiq"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigatsiya paneli"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Doim vazifalar paneli chiqsin"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Navigatsiya rejimini oʻzgartirish"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Vazifalar panelini ajratkich"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Yuqoriga yoki chapga oʻtkazish"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pastga yoki oʻngga oʻtkazish"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index ada07bd..5b7f12e 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Đã hiện thanh thao tác"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Đã ẩn thanh thao tác"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Thanh điều hướng"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Luôn hiển thị Taskbar"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Thay đổi chế độ điều hướng"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Đường phân chia Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Chuyển lên trên cùng/sang bên trái"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Chuyển xuống dưới cùng/sang bên phải"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 1e3c4ab..b88899b 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -97,7 +97,7 @@
<string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"跳过"</string>
<string name="accessibility_rotate_button" msgid="4771825231336502943">"旋转屏幕"</string>
<string name="taskbar_edu_a11y_title" msgid="5417986057866415355">"任务栏教程"</string>
- <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"将一个应用拖动到一侧,即可一次使用两个应用"</string>
+ <string name="taskbar_edu_splitscreen" msgid="5605512479258053350">"将一个应用拖到一侧,即可一次使用两个应用"</string>
<string name="taskbar_edu_stashing" msgid="5645461372669217294">"缓慢向上滑动即可显示任务栏"</string>
<string name="taskbar_edu_suggestions" msgid="8215044496435527982">"根据您的日常安排获取应用建议"</string>
<string name="taskbar_edu_settings_persistent" msgid="1387372982791296151">"在设置中开启手势导航后,任务栏会自动隐藏"</string>
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"任务栏已显示"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"任务栏已隐藏"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"导航栏"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"始终显示任务栏"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"更改导航模式"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"任务栏分隔线"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移到顶部/左侧"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右侧"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 16b56d3..e6de624 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"顯示咗工作列"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"隱藏咗工作列"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"導覽列"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"一律顯示工作列"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"變更導覽模式"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"工作列分隔線"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移至上方/左側"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移至底部/右側"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 6926ec5..2987a87 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"已顯示工作列"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"已隱藏工作列"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"導覽列"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"一律顯示工作列"</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"變更操作模式"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"工作列分隔線"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"移到上方/左側"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右側"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 246b121..2d78ebc 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -115,6 +115,9 @@
<string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ibha yomsebenzi ibonisiwe"</string>
<string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ibha yomsebenzi ifihliwe"</string>
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Ibha yokufuna"</string>
+ <string name="always_show_taskbar" msgid="3608801276107751229">"Bonisa i-Taskbar njalo."</string>
+ <string name="change_navigation_mode" msgid="9088393078736808968">"Shintsha imodi yokufuna"</string>
+ <string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Isihlukanisi se-Taskbar"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Hamba phezulu/kwesokunxele"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Hamba phansi/kwesokudla"</string>
<string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}"</string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 959fea7..d69b155 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -134,7 +134,6 @@
<dimen name="gesture_tutorial_menu_done_button_top_spacing">0dp</dimen>
<dimen name="gesture_tutorial_menu_back_shape_bottom_margin">0dp</dimen>
<dimen name="gesture_tutorial_menu_done_button_spacing">72dp</dimen>
- <dimen name="gesture_tutorial_menu_done_button_margin">0dp</dimen>
<!-- Gesture Tutorial mock conversations -->
<dimen name="gesture_tutorial_message_icon_size">44dp</dimen>
@@ -292,6 +291,8 @@
<dimen name="taskbar_stashed_small_screen">108dp</dimen>
<dimen name="taskbar_unstash_input_area">316dp</dimen>
<dimen name="taskbar_stashed_handle_height">4dp</dimen>
+ <dimen name="taskbar_stashed_screen_edge_hover_deadzone_height">10dp</dimen>
+ <dimen name="taskbar_stashed_below_hover_deadzone_height">1dp</dimen>
<dimen name="taskbar_edu_horizontal_margin">112dp</dimen>
<dimen name="taskbar_nav_buttons_width_kids">88dp</dimen>
<dimen name="taskbar_nav_buttons_height_kids">40dp</dimen>
@@ -340,6 +341,8 @@
<dimen name="taskbar_edu_features_lottie_width">170dp</dimen>
<dimen name="taskbar_edu_features_lottie_height">106dp</dimen>
<dimen name="taskbar_edu_features_horizontal_spacing">24dp</dimen>
+ <dimen name="taskbar_edu_features_tooltip_width_persistent">624dp</dimen>
+ <dimen name="taskbar_edu_features_tooltip_width_transient">428dp</dimen>
<!--- Taskbar Pinning -->
<dimen name="taskbar_pinning_popup_menu_width">300dp</dimen>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 6c12f11..e1afb26 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -200,7 +200,7 @@
<item name="android:background">@drawable/button_taskbar_edu_colored</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:textSize">16sp</item>
- <item name="android:padding">4dp</item>
+ <item name="android:minHeight">36dp</item>
</style>
<style name="TextAppearance.TaskbarEduTooltip.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 45163cb..682fccd 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1086,7 +1086,7 @@
* Adds remote animations to a {@link RemoteAnimationDefinition}. May be overridden to add
* additional animations.
*/
- protected void addRemoteAnimations(RemoteAnimationDefinition definition) {
+ private void addRemoteAnimations(RemoteAnimationDefinition definition) {
mWallpaperOpenRunner = createWallpaperOpenRunner(false /* fromUnlock */);
definition.addRemoteAnimation(WindowManager.TRANSIT_OLD_WALLPAPER_OPEN,
WindowConfiguration.ACTIVITY_TYPE_STANDARD,
@@ -1151,7 +1151,7 @@
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
}
- protected void unregisterRemoteAnimations() {
+ private void unregisterRemoteAnimations() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
@@ -1165,7 +1165,7 @@
}
}
- private void unregisterRemoteTransitions() {
+ protected void unregisterRemoteTransitions() {
if (ENABLE_SHELL_TRANSITIONS) {
SystemUiProxy.INSTANCE.get(mLauncher).unshareTransactionQueue();
}
@@ -1448,7 +1448,6 @@
*/
private Animator getFallbackClosingWindowAnimators(RemoteAnimationTarget[] appTargets) {
final int rotationChange = getRotationChange(appTargets);
- SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
Matrix matrix = new Matrix();
Point tmpPos = new Point();
Rect tmpRect = new Rect();
@@ -1504,7 +1503,7 @@
.setAlpha(1f);
}
}
- surfaceApplier.scheduleApply(transaction);
+ transaction.getTransaction().apply();
}
});
@@ -1592,7 +1591,8 @@
boolean playFallBackAnimation = (launcherView == null
&& launcherIsForceInvisibleOrOpening)
|| mLauncher.getWorkspace().isOverlayShown()
- || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
+ || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING)
+ || mLauncher.isDestroyed();
boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
index 268024f..885afff 100644
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
@@ -47,9 +47,7 @@
mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
mAllAppsButton = LayoutInflater.from(context)
.inflate(R.layout.taskbar_all_apps_button, mStartContextualContainer, false);
- mAllAppsButton.setOnClickListener((View v) -> {
- mControllers.taskbarAllAppsController.show();
- });
+ mAllAppsButton.setOnClickListener(v -> mControllers.taskbarAllAppsController.toggle());
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 7e0530b..d94d8f7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
import static com.android.launcher3.Utilities.isRunningInTestHarness;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
@@ -83,6 +84,12 @@
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag;
import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
+import com.android.launcher3.taskbar.bubbles.BubbleBarController;
+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.BubbleStashController;
+import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -106,6 +113,7 @@
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
+import java.util.Optional;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
@@ -195,11 +203,23 @@
TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
+ BubbleBarView bubbleBarView = mDragLayer.findViewById(R.id.taskbar_bubbles);
+ StashedHandleView bubbleHandleView = mDragLayer.findViewById(R.id.stashed_bubble_handle);
mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
final boolean isDesktopMode = getPackageManager().hasSystemFeature(FEATURE_PC);
+ // If Bubble bar is present, TaskbarControllers depends on it so build it first.
+ Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
+ if (BubbleBarController.BUBBLE_BAR_ENABLED) {
+ bubbleControllersOptional = Optional.of(new BubbleControllers(
+ new BubbleBarController(this, bubbleBarView),
+ new BubbleBarViewController(this, bubbleBarView),
+ new BubbleStashController(this),
+ new BubbleStashedHandleViewController(this, bubbleHandleView)));
+ }
+
// Construct controllers.
mControllers = new TaskbarControllers(this,
new TaskbarDragController(this),
@@ -239,7 +259,8 @@
: TaskbarRecentAppsController.DEFAULT,
new TaskbarEduTooltipController(this),
new KeyboardQuickSwitchController(),
- new TaskbarDividerPopupController(this));
+ new TaskbarDividerPopupController(this),
+ bubbleControllersOptional);
}
public void init(@NonNull TaskbarSharedState sharedState) {
@@ -661,7 +682,10 @@
void onDragEndOrViewRemoved() {
boolean isDragInProgress = mControllers.taskbarDragController.isSystemDragInProgress();
- if (!isDragInProgress && !AbstractFloatingView.hasOpenView(this, TYPE_ALL)) {
+ // Overlay AFVs are in a separate window and do not require Taskbar to be fullscreen.
+ if (!isDragInProgress
+ && !AbstractFloatingView.hasOpenView(
+ this, TYPE_ALL & ~TYPE_TASKBAR_OVERLAY_PROXY)) {
// Reverts Taskbar window to its original size
setTaskbarWindowFullscreen(false);
}
@@ -773,6 +797,7 @@
}
protected void onTaskbarIconClicked(View view) {
+ boolean shouldCloseAllOpenViews = true;
Object tag = view.getTag();
if (tag instanceof Task) {
Task task = (Task) tag;
@@ -780,6 +805,7 @@
ActivityOptions.makeBasic());
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
} else if (tag instanceof FolderInfo) {
+ shouldCloseAllOpenViews = false;
FolderIcon folderIcon = (FolderIcon) view;
Folder folder = folderIcon.getFolder();
@@ -876,7 +902,9 @@
Log.e(TAG, "Unknown type clicked: " + tag);
}
- AbstractFloatingView.closeAllOpenViews(this);
+ if (shouldCloseAllOpenViews) {
+ AbstractFloatingView.closeAllOpenViews(this);
+ }
}
/**
@@ -929,6 +957,13 @@
}
/**
+ * Returns whether the taskbar is currently visually stashed.
+ */
+ public boolean isTaskbarStashed() {
+ return mControllers.taskbarStashController.isStashed();
+ }
+
+ /**
* Called when we detect a long press in the nav region before passing the gesture slop.
* @return Whether taskbar handled the long press, and thus should cancel the gesture.
*/
@@ -972,10 +1007,23 @@
/**
* Called when we detect a motion down or up/cancel in the nav region while stashed.
+ *
* @param animateForward Whether to animate towards the unstashed hint state or back to stashed.
*/
public void startTaskbarUnstashHint(boolean animateForward) {
- mControllers.taskbarStashController.startUnstashHint(animateForward);
+ // TODO(b/270395798): Clean up forceUnstash after removing long-press unstashing code.
+ startTaskbarUnstashHint(animateForward, /* forceUnstash = */ false);
+ }
+
+ /**
+ * Called when we detect a motion down or up/cancel in the nav region while stashed.
+ *
+ * @param animateForward Whether to animate towards the unstashed hint state or back to stashed.
+ * @param forceUnstash Whether we force the unstash hint.
+ */
+ public void startTaskbarUnstashHint(boolean animateForward, boolean forceUnstash) {
+ // TODO(b/270395798): Clean up forceUnstash after removing long-press unstashing code.
+ mControllers.taskbarStashController.startUnstashHint(animateForward, forceUnstash);
}
/**
@@ -1123,4 +1171,9 @@
public int getTaskbarAllAppsScroll() {
return mControllers.taskbarAllAppsController.getTaskbarAllAppsScroll();
}
+
+ @VisibleForTesting
+ public float getStashedTaskbarScale() {
+ return mControllers.stashedHandleViewController.getStashedHandleHintScale().value;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 1cd6f50..66c2eb3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -23,12 +23,14 @@
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
+import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.systemui.shared.rotation.RotationButtonController;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Hosts various taskbar controllers to facilitate passing between one another.
@@ -61,6 +63,7 @@
public final TaskbarEduTooltipController taskbarEduTooltipController;
public final KeyboardQuickSwitchController keyboardQuickSwitchController;
public final TaskbarDividerPopupController taskbarPinningController;
+ public final Optional<BubbleControllers> bubbleControllers;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
@@ -107,7 +110,8 @@
TaskbarRecentAppsController taskbarRecentAppsController,
TaskbarEduTooltipController taskbarEduTooltipController,
KeyboardQuickSwitchController keyboardQuickSwitchController,
- TaskbarDividerPopupController taskbarPinningController) {
+ TaskbarDividerPopupController taskbarPinningController,
+ Optional<BubbleControllers> bubbleControllers) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -133,6 +137,7 @@
this.taskbarEduTooltipController = taskbarEduTooltipController;
this.keyboardQuickSwitchController = keyboardQuickSwitchController;
this.taskbarPinningController = taskbarPinningController;
+ this.bubbleControllers = bubbleControllers;
}
/**
@@ -167,6 +172,7 @@
taskbarEduTooltipController.init(this);
keyboardQuickSwitchController.init(this);
taskbarPinningController.init(this);
+ bubbleControllers.ifPresent(controllers -> controllers.init(this));
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -226,6 +232,7 @@
taskbarRecentAppsController.onDestroy();
keyboardQuickSwitchController.onDestroy();
taskbarStashController.onDestroy();
+ bubbleControllers.ifPresent(controllers -> controllers.onDestroy());
mControllersToLog = null;
mBackgroundRendererControllers = null;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 41093bd..72add4f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -308,15 +308,12 @@
// Pre-drag has ended, start the global system drag.
if (mDisallowGlobalDrag) {
AbstractFloatingView.closeAllOpenViewsExcept(mActivity, TYPE_TASKBAR_ALL_APPS);
- } else {
- AbstractFloatingView.closeAllOpenViews(mActivity);
+ return;
}
-
startSystemDrag((BubbleTextView) mDragObject.originalView);
}
private void startSystemDrag(BubbleTextView btv) {
- if (mDisallowGlobalDrag) return;
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) {
@Override
@@ -412,6 +409,9 @@
.log(StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED);
}
}
+
+ // Wait to close until after system drag has started, if applicable.
+ AbstractFloatingView.closeAllOpenViews(mActivity);
}
private void onSystemDragStarted(BubbleTextView btv) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
index 7f65e41..bcae06c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltip.kt
@@ -25,7 +25,9 @@
import android.view.MotionEvent.ACTION_DOWN
import android.view.View
import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.animation.Interpolator
+import androidx.core.view.updateLayoutParams
import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
import com.android.app.animation.Interpolators.STANDARD
@@ -77,6 +79,18 @@
}
mIsOpen = true
activityContext.dragLayer.addView(this)
+
+ // Make sure we have enough height to display all of the content, which can be an issue on
+ // large text and display scaling configurations. If we run out of height, remove the width
+ // constraint to reduce the number of lines of text and hopefully free up some height.
+ activityContext.dragLayer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
+ if (
+ measuredHeight + activityContext.deviceProfile.taskbarHeight >=
+ activityContext.deviceProfile.availableHeightPx
+ ) {
+ updateLayoutParams { width = MATCH_PARENT }
+ }
+
openCloseAnimator = createOpenCloseAnimator(isOpening = true).apply { start() }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 2c686b8..e99fa50 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -19,11 +19,13 @@
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
-import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.MarginLayoutParams
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import androidx.annotation.IntDef
import androidx.annotation.LayoutRes
+import androidx.core.view.updateLayoutParams
import com.airbnb.lottie.LottieAnimationView
import com.android.launcher3.R
import com.android.launcher3.Utilities
@@ -127,11 +129,24 @@
settingsEdu.visibility = VISIBLE
}
- findViewById<View>(R.id.done_button)?.setOnClickListener { hide() }
- if (DisplayController.isTransientTaskbar(activityContext)) {
- (layoutParams as ViewGroup.MarginLayoutParams).bottomMargin +=
- activityContext.deviceProfile.taskbarHeight
+ // Set up layout parameters.
+ content.updateLayoutParams { width = MATCH_PARENT }
+ updateLayoutParams<MarginLayoutParams> {
+ if (DisplayController.isTransientTaskbar(activityContext)) {
+ width =
+ resources.getDimensionPixelSize(
+ R.dimen.taskbar_edu_features_tooltip_width_transient
+ )
+ bottomMargin += activityContext.deviceProfile.taskbarHeight
+ } else {
+ width =
+ resources.getDimensionPixelSize(
+ R.dimen.taskbar_edu_features_tooltip_width_persistent
+ )
+ }
}
+
+ findViewById<View>(R.id.done_button)?.setOnClickListener { hide() }
show()
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 19b9a18..4422fd4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -34,8 +34,6 @@
import android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD
import android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION
import com.android.internal.policy.GestureNavigationSettingsObserver
-import com.android.launcher3.AbstractFloatingView
-import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.anim.AlphaUpdateListener
@@ -190,7 +188,7 @@
/**
* Called to update the touchable insets.
*
- * @see InternalInsetsInfo.setTouchableInsets
+ * @see ViewTreeObserver.InternalInsetsInfo.setTouchableInsets
*/
fun updateInsetsTouchability(insetsInfo: ViewTreeObserver.InternalInsetsInfo) {
insetsInfo.touchableRegion.setEmpty()
@@ -205,7 +203,7 @@
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (
controllers.navbarButtonsViewController.isImeVisible &&
- controllers.taskbarStashController.isStashed()
+ controllers.taskbarStashController.isStashed
) {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (!controllers.uiController.isTaskbarTouchable) {
@@ -214,26 +212,16 @@
} else if (controllers.taskbarDragController.isSystemDragInProgress) {
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
- } else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_OVERLAY_PROXY)) {
- // Let touches pass through us if icons are hidden.
- if (controllers.taskbarViewController.areIconsVisible()) {
- insetsInfo.touchableRegion.set(touchableRegion)
- }
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
+ } else if (context.isTaskbarWindowFullscreen) {
+ // Intercept entire fullscreen window.
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME)
+ insetsIsTouchableRegion = false
} else if (
- controllers.taskbarViewController.areIconsVisible() ||
- AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL) ||
- context.isNavBarKidsModeActive
+ controllers.taskbarViewController.areIconsVisible() || context.isNavBarKidsModeActive
) {
// Taskbar has some touchable elements, take over the full taskbar area
- insetsInfo.setTouchableInsets(
- if (context.isTaskbarWindowFullscreen) {
- TOUCHABLE_INSETS_FRAME
- } else {
- insetsInfo.touchableRegion.set(touchableRegion)
- TOUCHABLE_INSETS_REGION
- }
- )
+ insetsInfo.touchableRegion.set(touchableRegion)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
insetsIsTouchableRegion = false
} else {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index ed78e2d..75cfd05 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -207,6 +207,10 @@
com.android.launcher3.taskbar.Utilities.setOverviewDragState(
mControllers, finalState.disallowTaskbarGlobalDrag(),
disallowLongClick, finalState.allowTaskbarInitialSplitSelection());
+ // LauncherTaskbarUIController depends on the state when checking whether
+ // to handle resume, so it should also be poked if current state changes
+ mLauncher.getTaskbarUIController().onLauncherResumedOrPaused(
+ mLauncher.hasBeenResumed());
}
};
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 5abeac7..a442849 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -176,9 +176,9 @@
deepShortcutCount,
mPopupDataProvider.getNotificationKeysForItem(item),
systemShortcuts);
- icon.clearAccessibilityFocus();
}
+ icon.clearAccessibilityFocus();
container.addOnAttachStateChangeListener(
new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
@Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index b2f9378..c2175f2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -856,15 +856,18 @@
/**
* Creates and starts a partial unstash animation, hinting at the new state that will trigger
* when long press is detected.
+ *
* @param animateForward Whether we are going towards the new unstashed state or returning to
* the stashed state.
+ * @param forceUnstash Whether we force the unstash hint to animate.
*/
- public void startUnstashHint(boolean animateForward) {
+ protected void startUnstashHint(boolean animateForward, boolean forceUnstash) {
if (!isStashed()) {
// Already unstashed, no need to hint in that direction.
return;
}
- if (!canCurrentlyManuallyUnstash()) {
+ // TODO(b/270395798): Clean up after removing long-press unstashing code path.
+ if (!canCurrentlyManuallyUnstash() && !forceUnstash) {
// If any other flags are causing us to be stashed, long press won't cause us to
// unstash, so don't hint that it will.
return;
@@ -931,20 +934,6 @@
}
/**
- * Resets the flag if no system gesture is in progress.
- * <p>
- * Otherwise, the reset should be deferred until after the gesture is finished.
- *
- * @see #setSystemGestureInProgress
- */
- public void resetFlagIfNoGestureInProgress(int flag) {
- if (!mIsSystemGestureInProgress) {
- updateStateForFlag(flag, false);
- applyState(mControllers.taskbarOverlayController.getCloseDuration());
- }
- }
-
- /**
* When hiding the IME, delay the unstash animation to align with the end of the transition.
*/
private long getTaskbarStashStartDelayForIme() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
index 2373142..1cc6672 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
@@ -25,7 +25,7 @@
import com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL
import com.android.launcher3.util.DisplayController
import com.android.launcher3.util.TouchController
-import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer
+import com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer
/**
* A helper [TouchController] for [TaskbarDragLayerController], specifically to handle touch events
@@ -34,7 +34,7 @@
* or [MotionEvent.ACTION_OUTSIDE].
* - Touches inside Transient Taskbar bounds will stash if it is detected as a swipe down gesture.
*
- * Note: touches to *unstash* Taskbar are handled by [TaskbarStashInputConsumer].
+ * Note: touches to *unstash* Taskbar are handled by [TaskbarUnstashInputConsumer].
*/
class TaskbarStashViaTouchController(val controllers: TaskbarControllers) : TouchController {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index a7e2daa..7429185 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -639,7 +639,7 @@
public View.OnClickListener getAllAppsButtonClickListener() {
return v -> {
mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
- mControllers.taskbarAllAppsController.show();
+ mControllers.taskbarAllAppsController.toggle();
};
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
index 623e234..b4b83f6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
@@ -19,15 +19,21 @@
import android.util.AttributeSet;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.R;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import java.util.Optional;
+
/** All apps container accessible from taskbar. */
public class TaskbarAllAppsContainerView extends
ActivityAllAppsContainerView<TaskbarOverlayContext> {
+ private @Nullable OnInvalidateHeaderListener mOnInvalidateHeaderListener;
+
public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -36,6 +42,10 @@
super(context, attrs, defStyleAttr);
}
+ void setOnInvalidateHeaderListener(OnInvalidateHeaderListener onInvalidateHeaderListener) {
+ mOnInvalidateHeaderListener = onInvalidateHeaderListener;
+ }
+
@Override
protected View inflateSearchBox() {
if (isSearchSupported()) {
@@ -54,6 +64,13 @@
}
@Override
+ public void invalidateHeader() {
+ super.invalidateHeader();
+ Optional.ofNullable(mOnInvalidateHeaderListener).ifPresent(
+ OnInvalidateHeaderListener::onInvalidateHeader);
+ }
+
+ @Override
protected boolean isSearchSupported() {
return FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get();
}
@@ -63,4 +80,8 @@
// All apps is always open
return true;
}
+
+ interface OnInvalidateHeaderListener {
+ void onInvalidateHeader();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index 4266c71..459a658 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -100,9 +100,13 @@
}
}
- /** Opens the {@link TaskbarAllAppsContainerView} in a new window. */
- public void show() {
- show(true);
+ /** Toggles visibility of {@link TaskbarAllAppsContainerView} in the overlay window. */
+ public void toggle() {
+ if (isOpen()) {
+ mSlideInView.close(true);
+ } else {
+ show(true);
+ }
}
/** Returns {@code true} if All Apps is open. */
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index f0d28df..cfa1027 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -19,6 +19,7 @@
import android.animation.PropertyValuesHolder;
import android.content.Context;
+import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -99,12 +100,13 @@
mAppsView = findViewById(R.id.apps_view);
mContent = mAppsView;
+ // Setup header protection for search bar, if enabled.
+ if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
+ mAppsView.setOnInvalidateHeaderListener(this::invalidate);
+ }
+
DeviceProfile dp = mActivityContext.getDeviceProfile();
setShiftRange(dp.allAppsShiftRange);
-
- setContentBackgroundWithParent(
- getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet),
- mAppsView.getBottomSheetBackground());
}
@Override
@@ -137,6 +139,12 @@
}
@Override
+ protected void dispatchDraw(Canvas canvas) {
+ mAppsView.drawOnScrimWithScale(canvas, mSlideInViewScale.value);
+ super.dispatchDraw(canvas);
+ }
+
+ @Override
protected void onScaleProgressChanged() {
super.onScaleProgressChanged();
mAppsView.setClipChildren(!mIsBackProgressing);
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
index 7a3b3e8..01342af 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar.allapps;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_TASKBAR_ALL_APPS;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import com.android.launcher3.AbstractFloatingView;
@@ -88,8 +87,10 @@
}
private void setUpTaskbarStashing() {
- mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, true);
- mTaskbarStashController.applyState(mOverlayController.getOpenDuration());
+ if (DisplayController.isTransientTaskbar(mContext)) {
+ mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, true);
+ mTaskbarStashController.applyState(mOverlayController.getOpenDuration());
+ }
mNavbarButtonsViewController.setSlideInViewVisible(true);
mSlideInView.setOnCloseBeginListener(() -> {
@@ -100,11 +101,6 @@
if (DisplayController.isTransientTaskbar(mContext)) {
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false);
mTaskbarStashController.applyState(mOverlayController.getCloseDuration());
- } else {
- // Post in case view is closing due to gesture navigation. If a gesture is in
- // progress, wait to unstash until after the gesture is finished.
- MAIN_EXECUTOR.post(() -> mTaskbarStashController.resetFlagIfNoGestureInProgress(
- FLAG_STASHED_IN_TASKBAR_ALL_APPS));
}
});
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
index b1633e7..3cd5f75 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
@@ -30,7 +30,5 @@
val appName: String
) {
- fun getKey(): String {
- return info.key
- }
+ val key: String = info.key
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 228aabd..6d19692 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -152,7 +152,9 @@
mContext = context;
mBarView = bubbleView; // Need the view for inflating bubble views.
- // TODO: register the listener with SysUiProxu
+ if (BUBBLE_BAR_ENABLED) {
+ SystemUiProxy.INSTANCE.get(context).setBubblesListener(this);
+ }
mMainExecutor = MAIN_EXECUTOR;
mLauncherApps = context.getSystemService(LauncherApps.class);
mIconFactory = new BubbleIconFactory(context,
@@ -164,7 +166,7 @@
}
public void onDestroy() {
- // TODO: unregister the listener with SysUiProxy
+ SystemUiProxy.INSTANCE.get(mContext).setBubblesListener(null);
}
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
@@ -358,7 +360,7 @@
Path dotPath;
int dotColor;
- boolean isImportantConvo = false; // TODO: (b/269671451) needs to be added to BubbleInfo
+ boolean isImportantConvo = b.isImportantConversation();
ShortcutRequest.QueryResult result = new ShortcutRequest(context,
new UserHandle(b.getUserId()))
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 0afc2cb..82494c6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -30,6 +30,7 @@
import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.quickstep.SystemUiProxy;
import java.util.List;
import java.util.Objects;
@@ -42,6 +43,7 @@
private static final String TAG = BubbleBarViewController.class.getSimpleName();
+ private final SystemUiProxy mSystemUiProxy;
private final TaskbarActivityContext mActivity;
private final BubbleBarView mBarView;
private final int mIconSize;
@@ -69,6 +71,7 @@
public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
mActivity = activity;
mBarView = barView;
+ mSystemUiProxy = SystemUiProxy.INSTANCE.get(mActivity);
mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */);
mBubbleBarAlpha.setUpdateVisibility(true);
mIconSize = activity.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
@@ -101,7 +104,8 @@
mBubbleStashController.stashBubbleBar();
} else {
mBubbleBarController.setSelectedBubble(bubble);
- // TODO: Tell SysUi to show the expanded view for this bubble.
+ mSystemUiProxy.showBubble(bubble.getKey(),
+ mBubbleStashController.isBubblesShowingOnHome());
}
}
@@ -270,11 +274,12 @@
if (isExpanded != mBarView.isExpanded()) {
mBarView.setExpanded(isExpanded);
if (!isExpanded) {
- // TODO: Tell SysUi to collapse the bubble
+ mSystemUiProxy.collapseBubbles();
} else {
final String selectedKey = mBubbleBarController.getSelectedBubbleKey();
if (selectedKey != null) {
- // TODO: Tell SysUi to show the bubble
+ mSystemUiProxy.showBubble(selectedKey,
+ mBubbleStashController.isBubblesShowingOnHome());
} else {
Log.w(TAG, "trying to expand bubbles when there isn't one selected");
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index 66d5918..5902912 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -80,12 +80,23 @@
return mOverlayController;
}
+ /** Returns {@code true} if overlay or Taskbar windows are handling a system drag. */
+ boolean isAnySystemDragInProgress() {
+ return mDragController.isSystemDragInProgress()
+ || mTaskbarContext.getDragController().isSystemDragInProgress();
+ }
+
@Override
public DeviceProfile getDeviceProfile() {
return mOverlayController.getLauncherDeviceProfile();
}
@Override
+ public View.AccessibilityDelegate getAccessibilityDelegate() {
+ return mTaskbarContext.getAccessibilityDelegate();
+ }
+
+ @Override
public TaskbarDragController getDragController() {
return mDragController;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
index 476e0a8..8de0e40 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
@@ -36,6 +36,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.quickstep.views.DesktopTaskView;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -65,7 +66,9 @@
@Override
public void onTaskMovedToFront(int taskId) {
- mProxyView.close(false);
+ if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+ mProxyView.close(false);
+ }
}
};
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index 2c3e1ac..b4ec682 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -112,7 +112,7 @@
@Override
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
- if (mActivity.getDragController().isSystemDragInProgress()) {
+ if (mActivity.isAnySystemDragInProgress()) {
inoutInfo.touchableRegion.setEmpty();
inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index e1ce9b1..b901a87 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -359,18 +359,6 @@
return true;
});
sandboxCategory.addPreference(launchOverviewTutorialPreference);
- Preference launchSandboxModeTutorialPreference = new Preference(context);
- launchSandboxModeTutorialPreference.setKey("launchSandboxMode");
- launchSandboxModeTutorialPreference.setTitle("Launch Sandbox Mode");
- launchSandboxModeTutorialPreference.setSummary("Practice navigation gestures");
- launchSandboxModeTutorialPreference.setOnPreferenceClickListener(preference -> {
- startActivity(launchSandboxIntent
- .putExtra("use_tutorial_menu", false)
- .putExtra("tutorial_steps", new String[] {"SANDBOX_MODE"}));
- return true;
- });
- sandboxCategory.addPreference(launchSandboxModeTutorialPreference);
-
Preference launchSecondaryDisplayPreference = new Preference(context);
launchSecondaryDisplayPreference.setKey("launchSecondaryDisplay");
launchSecondaryDisplayPreference.setTitle("Launch Secondary Display");
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 5333cbe..7d47945 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -2114,12 +2114,11 @@
}
protected void linkRecentsViewScroll() {
- SurfaceTransactionApplier.create(mRecentsView, applier -> {
- runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
- .setSyncTransactionApplier(applier));
- runOnRecentsAnimationAndLauncherBound(() ->
- mRecentsAnimationTargets.addReleaseCheck(applier));
- });
+ SurfaceTransactionApplier applier = new SurfaceTransactionApplier(mRecentsView);
+ runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
+ .setSyncTransactionApplier(applier));
+ runOnRecentsAnimationAndLauncherBound(() ->
+ mRecentsAnimationTargets.addReleaseCheck(applier));
mRecentsView.addOnScrollChangedListener(mOnRecentsScrollListener);
runOnRecentsAnimationAndLauncherBound(() ->
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 64c9295..6b189cf 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -41,6 +41,7 @@
int TYPE_ONE_HANDED = 1 << 11;
int TYPE_TASKBAR_STASH = 1 << 12;
int TYPE_STATUS_BAR = 1 << 13;
+ int TYPE_CURSOR_HOVER = 1 << 14;
String[] NAMES = new String[] {
"TYPE_NO_OP", // 0
@@ -57,6 +58,7 @@
"TYPE_ONE_HANDED", // 11
"TYPE_TASKBAR_STASH", // 12
"TYPE_STATUS_BAR", // 13
+ "TYPE_CURSOR_HOVER", // 14
};
InputConsumer NO_OP = () -> TYPE_NO_OP;
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index ab3ae9f..4c9cf8b 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -116,6 +116,16 @@
return response;
}
+ case TestProtocol.REQUEST_STASHED_TASKBAR_SCALE: {
+ runOnTISBinder(tisBinder -> {
+ response.putFloat(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+ tisBinder.getTaskbarManager()
+ .getCurrentActivityContext()
+ .getStashedTaskbarScale());
+ });
+ return response;
+ }
+
case TestProtocol.REQUEST_TASKBAR_ALL_APPS_TOP_PADDING: {
return getTISBinderUIProperty(Bundle::putInt, tisBinder ->
tisBinder.getTaskbarManager()
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index b82ff03..523a98e 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
@@ -34,6 +36,7 @@
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
@@ -105,8 +108,16 @@
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
mController::finishAnimationToApp);
} else {
- RemoteAnimationTarget[] nonAppTargets =
- mSystemUiProxy.onGoingToRecentsLegacy(appTargets);
+ RemoteAnimationTarget[] nonAppTargets;
+ if (!TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+ nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(appTargets);
+ } else {
+ final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
+ final ArrayList<RemoteAnimationTarget> nonApps = new ArrayList<>();
+ classifyTargets(appTargets, apps, nonApps);
+ appTargets = apps.toArray(new RemoteAnimationTarget[apps.size()]);
+ nonAppTargets = nonApps.toArray(new RemoteAnimationTarget[nonApps.size()]);
+ }
if (nonAppTargets == null) {
nonAppTargets = new RemoteAnimationTarget[0];
}
@@ -176,6 +187,18 @@
return mListeners.toArray(new RecentsAnimationListener[mListeners.size()]);
}
+ private void classifyTargets(RemoteAnimationTarget[] appTargets,
+ ArrayList<RemoteAnimationTarget> apps, ArrayList<RemoteAnimationTarget> nonApps) {
+ for (int i = 0; i < appTargets.length; i++) {
+ RemoteAnimationTarget target = appTargets[i];
+ if (target.windowType == TYPE_DOCK_DIVIDER) {
+ nonApps.add(target);
+ } else {
+ apps.add(target);
+ }
+ }
+ }
+
/**
* Listener for the recents animation callbacks.
*/
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 913f08f..d798e62 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -145,6 +145,9 @@
* @param filter Returns true if GroupTask should be in the list of considerations
*/
public void isTaskRemoved(int taskId, Consumer<Boolean> callback, Predicate<GroupTask> filter) {
+ // Invalidate the existing list before checking to ensure this reflects the current state in
+ // the system
+ mTaskList.onRecentTasksChanged();
mTaskList.getTasks(true /* loadKeysOnly */, (taskGroups) -> {
for (GroupTask group : taskGroups) {
if (group.containsTask(taskId)) {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 89f06f6..0549d9f 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -51,6 +51,7 @@
import android.window.TaskSnapshot;
import android.window.TransitionFilter;
+import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -58,6 +59,7 @@
import com.android.internal.util.ScreenshotRequest;
import com.android.internal.view.AppearanceRegion;
import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -69,6 +71,8 @@
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.systemui.unfold.progress.IUnfoldTransitionListener;
import com.android.wm.shell.back.IBackAnimation;
+import com.android.wm.shell.bubbles.IBubbles;
+import com.android.wm.shell.bubbles.IBubblesListener;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.draganddrop.IDragAndDrop;
import com.android.wm.shell.onehanded.IOneHanded;
@@ -101,6 +105,7 @@
private ISystemUiProxy mSystemUiProxy;
private IPip mPip;
+ private IBubbles mBubbles;
private ISysuiUnlockAnimationController mSysuiUnlockAnimationController;
private ISplitScreen mSplitScreen;
private IOneHanded mOneHanded;
@@ -119,6 +124,7 @@
// up to the caller to clear the listeners to prevent leaks as these can be held indefinitely
// in case SysUI needs to rebind.
private IPipAnimationListener mPipAnimationListener;
+ private IBubblesListener mBubblesListener;
private ISplitScreenListener mSplitScreenListener;
private IStartingWindowListener mStartingWindowListener;
private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
@@ -200,15 +206,21 @@
return null;
}
- public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen,
+ /**
+ * Sets proxy state, including death linkage, various listeners, and other configuration objects
+ */
+ @MainThread
+ public void setProxy(ISystemUiProxy proxy, IPip pip, IBubbles bubbles, ISplitScreen splitScreen,
IOneHanded oneHanded, IShellTransitions shellTransitions,
IStartingWindow startingWindow, IRecentTasks recentTasks,
ISysuiUnlockAnimationController sysuiUnlockAnimationController,
IBackAnimation backAnimation, IDesktopMode desktopMode,
IUnfoldAnimation unfoldAnimation, IDragAndDrop dragAndDrop) {
+ Preconditions.assertUIThread();
unlinkToDeath();
mSystemUiProxy = proxy;
mPip = pip;
+ mBubbles = bubbles;
mSplitScreen = splitScreen;
mOneHanded = oneHanded;
mShellTransitions = shellTransitions;
@@ -222,6 +234,7 @@
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
setPipAnimationListener(mPipAnimationListener);
+ setBubblesListener(mBubblesListener);
registerSplitScreenListener(mSplitScreenListener);
setStartingWindowListener(mStartingWindowListener);
setLauncherUnlockAnimationController(mLauncherUnlockAnimationController);
@@ -232,8 +245,12 @@
setUnfoldAnimationListener(mUnfoldAnimationListener);
}
+ /**
+ * Clear the proxy to release held resources and turn the majority of its operations into no-ops
+ */
+ @MainThread
public void clearProxy() {
- setProxy(null, null, null, null, null, null, null, null, null, null, null, null);
+ setProxy(null, null, null, null, null, null, null, null, null, null, null, null, null);
}
// TODO(141886704): Find a way to remove this
@@ -292,8 +309,10 @@
}
}
+ @MainThread
@Override
public void onStatusBarMotionEvent(MotionEvent event) {
+ Preconditions.assertUIThread();
if (mSystemUiProxy != null) {
try {
mSystemUiProxy.onStatusBarMotionEvent(event);
@@ -572,6 +591,59 @@
}
//
+ // Bubbles
+ //
+
+ /**
+ * Sets the listener to be notified of bubble state changes.
+ */
+ public void setBubblesListener(IBubblesListener listener) {
+ if (mBubbles != null) {
+ try {
+ if (mBubblesListener != null) {
+ // Clear out any previous listener
+ mBubbles.unregisterBubbleListener(mBubblesListener);
+ }
+ if (listener != null) {
+ mBubbles.registerBubbleListener(listener);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call registerBubblesListener");
+ }
+ }
+ mBubblesListener = listener;
+ }
+
+ /**
+ * Tells SysUI to show the bubble with the provided key.
+ * @param key the key of the bubble to show.
+ * @param onLauncherHome whether the bubble is showing on launcher home or not (modifies where
+ * the expanded bubble view is placed).
+ */
+ public void showBubble(String key, boolean onLauncherHome) {
+ if (mBubbles != null) {
+ try {
+ mBubbles.showBubble(key, onLauncherHome);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call showBubble");
+ }
+ }
+ }
+
+ /**
+ * Tells SysUI to collapse the bubbles.
+ */
+ public void collapseBubbles() {
+ if (mBubbles != null) {
+ try {
+ mBubbles.collapseBubbles();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call collapseBubbles");
+ }
+ }
+ }
+
+ //
// Splitscreen
//
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 6ea171e..682763f 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -29,6 +29,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.quickstep.GestureState.TrackpadGestureType.getTrackpadGestureType;
+import static com.android.quickstep.InputConsumer.TYPE_CURSOR_HOVER;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_DOWN;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_MOVE;
@@ -42,6 +43,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
+import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED;
@@ -110,7 +112,7 @@
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.quickstep.inputconsumers.StatusBarInputConsumer;
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
-import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer;
+import com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActiveGestureLog.CompoundString;
import com.android.quickstep.util.ProtoTracer;
@@ -125,6 +127,7 @@
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.wm.shell.back.IBackAnimation;
+import com.android.wm.shell.bubbles.IBubbles;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.draganddrop.IDragAndDrop;
import com.android.wm.shell.onehanded.IOneHanded;
@@ -168,6 +171,7 @@
ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
IPip pip = IPip.Stub.asInterface(bundle.getBinder(KEY_EXTRA_SHELL_PIP));
+ IBubbles bubbles = IBubbles.Stub.asInterface(bundle.getBinder(KEY_EXTRA_SHELL_BUBBLES));
ISplitScreen splitscreen = ISplitScreen.Stub.asInterface(bundle.getBinder(
KEY_EXTRA_SHELL_SPLIT_SCREEN));
IOneHanded onehanded = IOneHanded.Stub.asInterface(
@@ -191,7 +195,7 @@
bundle.getBinder(KEY_EXTRA_SHELL_DRAG_AND_DROP));
MAIN_EXECUTOR.execute(() -> {
SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
- splitscreen, onehanded, shellTransitions, startingWindow,
+ bubbles, splitscreen, onehanded, shellTransitions, startingWindow,
recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
unfoldTransition, dragAndDrop);
TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()");
@@ -641,12 +645,17 @@
TraceHelper.FLAG_ALLOW_BINDER_TRACKING);
final int action = event.getActionMasked();
- if (action == ACTION_DOWN) {
+ // Note this will create a new consumer every mouse click, as after ACTION_UP from the click
+ // an ACTION_HOVER_ENTER will fire as well.
+ boolean isHoverActionWithoutConsumer =
+ event.isHoverEvent() && (mUncheckedConsumer.getType() & TYPE_CURSOR_HOVER) == 0;
+ if (action == ACTION_DOWN || isHoverActionWithoutConsumer) {
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
- if (!mDeviceState.isOneHandedModeActive()
+ if ((!mDeviceState.isOneHandedModeActive()
&& mRotationTouchHelper.isInSwipeUpTouchRegion(event,
- mOverviewComponentObserver.getActivityInterface())) {
+ mOverviewComponentObserver.getActivityInterface()))
+ || isHoverActionWithoutConsumer) {
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
// onConsumerInactive and wipe the previous gesture state
GestureState prevGestureState = new GestureState(mGestureState);
@@ -723,6 +732,8 @@
if (action == ACTION_POINTER_DOWN) {
mGestureState.setTrackpadGestureType(getTrackpadGestureType(event));
}
+ } else if (event.isHoverEvent()) {
+ mUncheckedConsumer.onHoverEvent(event);
} else {
mUncheckedConsumer.onMotionEvent(event);
}
@@ -846,7 +857,7 @@
base = tryCreateAssistantInputConsumer(base, newGestureState, event, reasonString);
}
- // If Taskbar is present, we listen for long press to unstash it.
+ // If Taskbar is present, we listen for long press or cursor hover events to unstash it.
TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
if (tac != null) {
// Present always on large screen or on small screen w/ flag
@@ -857,8 +868,8 @@
.append(reasonPrefix)
.append(SUBSTRING_PREFIX)
.append("TaskbarActivityContext != null, "
- + "using TaskbarStashInputConsumer");
- base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat, tac);
+ + "using TaskbarUnstashInputConsumer");
+ base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac);
}
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 4b1dd43..074aedd 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -79,7 +79,7 @@
}
@Override
- public void startHome() {
+ public void startHome(boolean animated) {
mActivity.startHome();
AbstractFloatingView.closeAllOpenViews(mActivity, mActivity.isStarted());
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
similarity index 69%
rename from quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index 51c2b48..65c825c 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -19,17 +19,20 @@
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import androidx.annotation.Nullable;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.taskbar.TaskbarActivityContext;
@@ -40,9 +43,11 @@
import com.android.systemui.shared.system.InputMonitorCompat;
/**
- * Listens for a long press, and cancels the current gesture if that causes Taskbar to be unstashed.
+ * Listens for touch and hover events to unstash the Taskbar.
+ *
+ * <p>Cancels the current gesture if the long press causes the Taskbar to be unstashed.
*/
-public class TaskbarStashInputConsumer extends DelegateInputConsumer {
+public class TaskbarUnstashInputConsumer extends DelegateInputConsumer {
private final TaskbarActivityContext mTaskbarActivityContext;
private final GestureDetector mLongPressDetector;
@@ -64,9 +69,15 @@
private final boolean mIsTransientTaskbar;
+ private boolean mIsStashedTaskbarHovered = false;
+ private final Rect mStashedTaskbarHandleBounds = new Rect();
+ private final Rect mBottomEdgeBounds = new Rect();
+ private final int mBottomScreenEdge;
+ private final int mStashedTaskbarBottomEdge;
+
private final @Nullable TransitionCallback mTransitionCallback;
- public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
+ public TaskbarUnstashInputConsumer(Context context, InputConsumer delegate,
InputMonitorCompat inputMonitor, TaskbarActivityContext taskbarActivityContext) {
super(delegate, inputMonitor);
mTaskbarActivityContext = taskbarActivityContext;
@@ -90,6 +101,11 @@
}
});
+ mBottomScreenEdge = res.getDimensionPixelSize(
+ R.dimen.taskbar_stashed_screen_edge_hover_deadzone_height);
+ mStashedTaskbarBottomEdge =
+ res.getDimensionPixelSize(R.dimen.taskbar_stashed_below_hover_deadzone_height);
+
mTransitionCallback = mIsTransientTaskbar
? taskbarActivityContext.getTranslationCallbacks()
: null;
@@ -97,7 +113,7 @@
@Override
public int getType() {
- return TYPE_TASKBAR_STASH | mDelegate.getType();
+ return TYPE_TASKBAR_STASH | TYPE_CURSOR_HOVER | mDelegate.getType();
}
@Override
@@ -213,4 +229,73 @@
}
}
}
+
+ /**
+ * Listen for hover events for the stashed taskbar.
+ *
+ * <p>When hovered over the stashed taskbar handle, show the unstash hint.
+ * <p>When the cursor is touching the bottom edge below the stashed taskbar, unstash it.
+ * <p>When the cursor is within a defined threshold of the screen's bottom edge outside of
+ * the stashed taskbar, unstash it.
+ */
+ @Override
+ public void onHoverEvent(MotionEvent ev) {
+ if (!ENABLE_CURSOR_HOVER_STATES.get() || mTaskbarActivityContext == null
+ || !mTaskbarActivityContext.isTaskbarStashed()) {
+ return;
+ }
+
+ if (mIsStashedTaskbarHovered) {
+ updateHoveredTaskbarState((int) ev.getX(), (int) ev.getY());
+ } else {
+ updateUnhoveredTaskbarState((int) ev.getX(), (int) ev.getY());
+ }
+ }
+
+ private void updateHoveredTaskbarState(int x, int y) {
+ DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile();
+ mStashedTaskbarHandleBounds.set(
+ (dp.widthPx - (int) mUnstashArea) / 2,
+ dp.heightPx - dp.stashedTaskbarHeight,
+ (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea),
+ dp.heightPx);
+ mBottomEdgeBounds.set(mStashedTaskbarHandleBounds);
+ mBottomEdgeBounds.top = dp.heightPx - mStashedTaskbarBottomEdge;
+
+ if (mBottomEdgeBounds.contains(x, y)) {
+ // If hovering stashed taskbar and then hover screen bottom edge, unstash it.
+ mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ mIsStashedTaskbarHovered = false;
+ } else if (!mStashedTaskbarHandleBounds.contains(x, y)) {
+ // If exit hovering stashed taskbar, remove hint.
+ startStashedTaskbarHover(/* isHovered = */ false);
+ }
+ }
+
+ private void updateUnhoveredTaskbarState(int x, int y) {
+ DeviceProfile dp = mTaskbarActivityContext.getDeviceProfile();
+ mStashedTaskbarHandleBounds.set(
+ (dp.widthPx - (int) mUnstashArea) / 2,
+ dp.heightPx - dp.stashedTaskbarHeight,
+ (int) (((dp.widthPx - mUnstashArea) / 2) + mUnstashArea),
+ dp.heightPx);
+ mBottomEdgeBounds.set(
+ 0,
+ dp.heightPx - mBottomScreenEdge,
+ dp.widthPx,
+ dp.heightPx);
+
+ if (mStashedTaskbarHandleBounds.contains(x, y)) {
+ // If enter hovering stashed taskbar, start hint.
+ startStashedTaskbarHover(/* isHovered = */ true);
+ } else if (mBottomEdgeBounds.contains(x, y)) {
+ // If hover screen's bottom edge not below the stashed taskbar, unstash it.
+ mTaskbarActivityContext.onSwipeToUnstashTaskbar();
+ }
+ }
+
+ private void startStashedTaskbarHover(boolean isHovered) {
+ mTaskbarActivityContext.startTaskbarUnstashHint(isHovered, /* forceUnstash = */ true);
+ mIsStashedTaskbarHovered = isHovered;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 1ac0742..aeac760 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -186,7 +186,8 @@
public void launchTutorialMenu() {
mFragment = new MenuFragment();
getSupportFragmentManager().beginTransaction()
- .add(R.id.gesture_tutorial_fragment_container, mFragment)
+ .replace(R.id.gesture_tutorial_fragment_container, mFragment)
+ .runOnCommit(() -> mFragment.onAttachedToWindow())
.commit();
}
diff --git a/quickstep/src/com/android/quickstep/interaction/MenuFragment.java b/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
index ccff30d..46f79b1 100644
--- a/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
@@ -19,6 +19,7 @@
import static com.android.quickstep.interaction.GestureSandboxActivity.KEY_TUTORIAL_TYPE;
import static com.android.quickstep.interaction.GestureSandboxActivity.KEY_USE_TUTORIAL_MENU;
+import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -27,17 +28,33 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
/** Displays the gesture nav tutorial menu. */
public final class MenuFragment extends GestureSandboxFragment {
+ @NonNull private Rect mInsets = new Rect();
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mInsets = InvariantDeviceProfile.INSTANCE.get(getContext())
+ .getDeviceProfile(getContext()).getInsets();
+ }
+
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(
R.layout.gesture_tutorial_step_menu, container, false);
+ root.setPadding(
+ root.getPaddingLeft() + mInsets.left,
+ root.getPaddingTop() + mInsets.top,
+ root.getPaddingRight() + mInsets.right,
+ root.getPaddingBottom() + mInsets.bottom);
+
root.findViewById(R.id.gesture_tutorial_menu_home_button).setOnClickListener(
v -> launchTutorialStep(TutorialController.TutorialType.HOME_NAVIGATION));
root.findViewById(R.id.gesture_tutorial_menu_back_button).setOnClickListener(
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
deleted file mode 100644
index f0bd4f9..0000000
--- a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-package com.android.quickstep.interaction;
-
-import android.graphics.PointF;
-
-import com.android.launcher3.R;
-import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
-import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
-
-/** A {@link TutorialController} for the Sandbox Mode. */
-public class SandboxModeTutorialController extends SwipeUpGestureTutorialController {
-
- SandboxModeTutorialController(SandboxModeTutorialFragment fragment, TutorialType tutorialType) {
- super(fragment, tutorialType);
- }
-
- @Override
- public void onBackGestureAttempted(BackGestureResult result) {
- switch (result) {
- case BACK_COMPLETED_FROM_LEFT:
- case BACK_COMPLETED_FROM_RIGHT:
- showRippleEffect(null);
- showFeedback(R.string.sandbox_mode_back_gesture_feedback_successful);
- break;
- case BACK_CANCELLED_FROM_LEFT:
- case BACK_CANCELLED_FROM_RIGHT:
- showFeedback(R.string.back_gesture_feedback_cancelled);
- break;
- case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE:
- showFeedback(R.string.sandbox_mode_back_gesture_feedback_swipe_too_far_from_edge);
- break;
- }
- }
-
- @Override
- public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
- switch (result) {
- case HOME_GESTURE_COMPLETED:
- animateFakeTaskViewHome(finalVelocity, () -> {
- showFeedback(R.string.sandbox_mode_home_gesture_feedback_successful);
- });
- break;
- case OVERVIEW_GESTURE_COMPLETED:
- fadeOutFakeTaskView(true, true, () -> {
- showFeedback(R.string.sandbox_mode_overview_gesture_feedback_successful);
- });
- break;
- case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
- case HOME_OR_OVERVIEW_CANCELLED:
- case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
- case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
- showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge);
- break;
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java
deleted file mode 100644
index 7bd52f7..0000000
--- a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialFragment.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-package com.android.quickstep.interaction;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.logging.StatsLogManager;
-import com.android.quickstep.interaction.TutorialController.TutorialType;
-
-/** Shows the general navigation gesture sandbox environment. */
-public class SandboxModeTutorialFragment extends TutorialFragment {
-
- public SandboxModeTutorialFragment(boolean fromTutorialMenu) {
- super(fromTutorialMenu);
- }
-
- @Override
- TutorialController createController(TutorialType type) {
- return new SandboxModeTutorialController(this, type);
- }
-
- @Override
- Class<? extends TutorialController> getControllerClass() {
- return SandboxModeTutorialController.class;
- }
-
- @Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && mTutorialController != null) {
- mTutorialController.setRippleHotspot(motionEvent.getX(), motionEvent.getY());
- }
- return super.onTouch(view, motionEvent);
- }
-
- @Override
- void logTutorialStepShown(@NonNull StatsLogManager statsLogManager) {
- // No-Op: tutorial step not currently shown to users
- }
-
- @Override
- void logTutorialStepCompleted(@NonNull StatsLogManager statsLogManager) {
- // No-Op: tutorial step not currently shown to users
- }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 6efdb07..d4ff457 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -829,9 +829,6 @@
HOME_NAVIGATION,
HOME_NAVIGATION_COMPLETE,
OVERVIEW_NAVIGATION,
- OVERVIEW_NAVIGATION_COMPLETE,
- ASSISTANT,
- ASSISTANT_COMPLETE,
- SANDBOX_MODE
+ OVERVIEW_NAVIGATION_COMPLETE
}
}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 25de605..9f15e19 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -117,8 +117,6 @@
case OVERVIEW_NAVIGATION:
case OVERVIEW_NAVIGATION_COMPLETE:
return new OverviewGestureTutorialFragment(fromTutorialMenu);
- case SANDBOX_MODE:
- return new SandboxModeTutorialFragment(fromTutorialMenu);
default:
Log.e(LOG_TAG, "Failed to find an appropriate fragment for " + tutorialType.name());
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 298d49a..fbb8109 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -494,6 +494,7 @@
private long mLatencyInMillis;
private int mQueryLength = -1;
private int mSubEventType = 0;
+ private int mCardinality = -1;
@Override
public StatsLatencyLogger withInstanceId(InstanceId instanceId) {
@@ -532,6 +533,12 @@
}
@Override
+ public StatsLatencyLogger withCardinality(int cardinality) {
+ this.mCardinality = cardinality;
+ return this;
+ }
+
+ @Override
public void log(EventEnum event) {
if (IS_VERBOSE) {
String name = (event instanceof Enum) ? ((Enum) event).name() :
@@ -549,7 +556,8 @@
mLatencyInMillis, // latency_in_millis
mType.getId(), //type
mQueryLength, // query_length
- mSubEventType // sub_event_type
+ mSubEventType, // sub_event_type
+ mCardinality // cardinality
);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/BaseDepthController.java b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
index b5c582a..23cfb39 100644
--- a/quickstep/src/com/android/quickstep/util/BaseDepthController.java
+++ b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
@@ -75,7 +75,7 @@
// marking the launcher surface as opaque. Only used in certain Launcher states.
private boolean mHasContentBehindLauncher;
- /** Pause applying depth and blur, can be used when something behind the Launcher. */
+ /** Pause blur but allow transparent, can be used when launch something behind the Launcher. */
protected boolean mPauseBlurs;
/**
@@ -132,7 +132,7 @@
return;
}
boolean hasOpaqueBg = mLauncher.getScrimView().isFullyOpaque();
- boolean isSurfaceOpaque = mPauseBlurs || (!mHasContentBehindLauncher && hasOpaqueBg);
+ boolean isSurfaceOpaque = !mHasContentBehindLauncher && hasOpaqueBg && !mPauseBlurs;
mCurrentBlur = !mCrossWindowBlursEnabled || hasOpaqueBg || mPauseBlurs
? 0 : (int) (depth * mMaxBlurRadius);
diff --git a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
index ad11b7e..328a727 100644
--- a/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BaseUnfoldMoveFromCenterAnimator.java
@@ -43,6 +43,10 @@
new UnfoldMoveFromCenterRotationListener();
private boolean mAnimationInProgress = false;
+ // Save the last transition progress so we can re-apply it in case we re-register the view for
+ // the animation (by calling onPrepareViewsForAnimation)
+ private Float mLastTransitionProgress = null;
+
public BaseUnfoldMoveFromCenterAnimator(WindowManager windowManager,
RotationChangeProvider rotationChangeProvider) {
mMoveFromCenterAnimation = new UnfoldMoveFromCenterAnimator(windowManager,
@@ -63,11 +67,13 @@
@Override
public void onTransitionProgress(float progress) {
mMoveFromCenterAnimation.onTransitionProgress(progress);
+ mLastTransitionProgress = progress;
}
@CallSuper
@Override
public void onTransitionFinished() {
+ mLastTransitionProgress = null;
mAnimationInProgress = false;
mRotationChangeProvider.removeCallback(mRotationListener);
mMoveFromCenterAnimation.onTransitionFinished();
@@ -93,8 +99,11 @@
mOriginalClipToPadding.clear();
}
+ @CallSuper
protected void onPrepareViewsForAnimation() {
-
+ if (mLastTransitionProgress != null) {
+ mMoveFromCenterAnimation.onTransitionProgress(mLastTransitionProgress);
+ }
}
protected void registerViewForAnimation(View view) {
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 8fdafc6..6d15e8b 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -27,10 +27,15 @@
import androidx.core.view.OneShotPreDrawListener;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.Workspace;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.HorizontalInsettableView;
+import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.unfold.PreemptiveUnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
import com.android.systemui.unfold.updates.RotationChangeProvider;
@@ -40,7 +45,7 @@
/**
* Controls animations that are happening during unfolding foldable devices
*/
-public class LauncherUnfoldAnimationController {
+public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeListener {
// Percentage of the width of the quick search bar that will be reduced
// from the both sides of the bar when progress is 0
@@ -55,9 +60,11 @@
private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider;
private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator;
private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator;
+ private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null;
+ private Boolean mIsTablet = null;
private static final String TRACE_WAIT_TO_HANDLE_UNFOLD_TRANSITION =
- "waitingOneFrameBeforeHandlingUnfoldAnimation";
+ "LauncherUnfoldAnimationController#waitingForTheNextFrame";
@Nullable
private HorizontalInsettableView mQsbInsettable;
@@ -68,8 +75,19 @@
UnfoldTransitionProgressProvider unfoldTransitionProgressProvider,
RotationChangeProvider rotationChangeProvider) {
mLauncher = launcher;
- mProgressProvider = new ScopedUnfoldTransitionProgressProvider(
- unfoldTransitionProgressProvider);
+
+ if (FeatureFlags.PREEMPTIVE_UNFOLD_ANIMATION_START.get()) {
+ mPreemptiveProgressProvider = new PreemptiveUnfoldTransitionProgressProvider(
+ unfoldTransitionProgressProvider, launcher.getMainThreadHandler());
+ mPreemptiveProgressProvider.init();
+
+ mProgressProvider = new ScopedUnfoldTransitionProgressProvider(
+ mPreemptiveProgressProvider);
+ } else {
+ mProgressProvider = new ScopedUnfoldTransitionProgressProvider(
+ unfoldTransitionProgressProvider);
+ }
+
mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher,
windowManager, rotationChangeProvider);
mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher,
@@ -85,6 +103,8 @@
// Animated only in natural orientation
mNaturalOrientationProgressProvider.addCallback(new QsbAnimationListener());
mNaturalOrientationProgressProvider.addCallback(mUnfoldMoveFromCenterHotseatAnimator);
+
+ mLauncher.addOnDeviceProfileChangeListener(this);
}
/**
@@ -96,17 +116,21 @@
mQsbInsettable = (HorizontalInsettableView) hotseat.getQsb();
}
- handleTransitionOnNextFrame();
+ mProgressProvider.setReadyToHandleTransition(true);
}
- private void handleTransitionOnNextFrame() {
+ private void preemptivelyStartAnimationOnNextFrame() {
Trace.asyncTraceBegin(Trace.TRACE_TAG_APP,
TRACE_WAIT_TO_HANDLE_UNFOLD_TRANSITION, /* cookie= */ 0);
+
+ // Start the animation (and apply the transformations) in pre-draw listener to make sure
+ // that the views are laid out as some transformations depend on the view sizes and position
OneShotPreDrawListener.add(mLauncher.getWorkspace(),
() -> {
Trace.asyncTraceEnd(Trace.TRACE_TAG_APP,
TRACE_WAIT_TO_HANDLE_UNFOLD_TRANSITION, /* cookie= */ 0);
- mProgressProvider.setReadyToHandleTransition(true);
+ mPreemptiveProgressProvider.preemptivelyStartTransition(
+ /* initialProgress= */ 0f);
});
}
@@ -124,14 +148,34 @@
public void onDestroy() {
mProgressProvider.destroy();
mNaturalOrientationProgressProvider.destroy();
+ mLauncher.removeOnDeviceProfileChangeListener(this);
}
- /** Called when launcher finished binding its items. */
+ /**
+ * Called when launcher has finished binding its items
+ */
public void updateRegisteredViewsIfNeeded() {
mUnfoldMoveFromCenterHotseatAnimator.updateRegisteredViewsIfNeeded();
mUnfoldMoveFromCenterWorkspaceAnimator.updateRegisteredViewsIfNeeded();
}
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ if (!FeatureFlags.PREEMPTIVE_UNFOLD_ANIMATION_START.get()) {
+ return;
+ }
+
+ if (mIsTablet != null && dp.isTablet != mIsTablet) {
+ if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) {
+ // Preemptively start the unfold animation to make sure that we have drawn
+ // the first frame of the animation before the screen gets unblocked
+ preemptivelyStartAnimationOnNextFrame();
+ }
+ }
+
+ mIsTablet = dp.isTablet;
+ }
+
private class QsbAnimationListener implements TransitionProgressListener {
@Override
diff --git a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
index 95473dc..bb028a7 100644
--- a/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
+++ b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
@@ -22,13 +22,11 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
import android.view.ViewRootImpl;
import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
-import java.util.function.Consumer;
-
-
/**
* Helper class to apply surface transactions in sync with RenderThread similar to
* android.view.SyncRtSurfaceTransactionApplier
@@ -39,22 +37,47 @@
private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
- private final SurfaceControl mBarrierSurfaceControl;
- private final ViewRootImpl mTargetViewRootImpl;
private final Handler mApplyHandler;
+ private boolean mInitialized;
+ private SurfaceControl mBarrierSurfaceControl;
+ private ViewRootImpl mTargetViewRootImpl;
+
private int mLastSequenceNumber = 0;
/**
* @param targetView The view in the surface that acts as synchronization anchor.
*/
public SurfaceTransactionApplier(View targetView) {
- mTargetViewRootImpl = targetView.getViewRootImpl();
- mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
+ if (targetView.isAttachedToWindow()) {
+ initialize(targetView);
+ } else {
+ mInitialized = false;
+ targetView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (!mInitialized) {
+ targetView.removeOnAttachStateChangeListener(this);
+ initialize(targetView);
+ }
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ // Do nothing
+ }
+ });
+ }
mApplyHandler = new Handler(this::onApplyMessage);
setCanRelease(true);
}
+ private void initialize(View view) {
+ mTargetViewRootImpl = view.getViewRootImpl();
+ mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
+ mInitialized = true;
+ }
+
protected boolean onApplyMessage(Message msg) {
if (msg.what == MSG_UPDATE_SEQUENCE_NUMBER) {
setCanRelease(msg.arg1 == mLastSequenceNumber);
@@ -70,6 +93,10 @@
* this method to avoid synchronization issues.
*/
public void scheduleApply(SurfaceTransaction params) {
+ if (!mInitialized) {
+ params.getTransaction().apply();
+ return;
+ }
View view = mTargetViewRootImpl.getView();
if (view == null) {
return;
@@ -93,33 +120,4 @@
// Make sure a frame gets scheduled.
view.invalidate();
}
-
- /**
- * Creates an instance of SurfaceTransactionApplier, deferring until the target view is
- * attached if necessary.
- */
- public static void create(
- final View targetView, final Consumer<SurfaceTransactionApplier> callback) {
- if (targetView == null) {
- // No target view, no applier
- callback.accept(null);
- } else if (targetView.isAttachedToWindow()) {
- // Already attached, we're good to go
- callback.accept(new SurfaceTransactionApplier(targetView));
- } else {
- // Haven't been attached before we can get the view root
- targetView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- targetView.removeOnAttachStateChangeListener(this);
- callback.accept(new SurfaceTransactionApplier(targetView));
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- // Do nothing
- }
- });
- }
- }
}
diff --git a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
new file mode 100644
index 0000000..c22e0bc
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
@@ -0,0 +1,105 @@
+/*
+ * 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.quickstep.util;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
+import com.android.quickstep.RecentsModel;
+
+/**
+ * This class tracks the failure of a task launch through the TaskView.launchTask() call, in an
+ * edge case in which starting a new task may initially succeed (startActivity returns true), but
+ * the launch ultimately fails if the activity finishes while it is resuming.
+ *
+ * There are two signals this class checks, the launcher lifecycle and the transition completion.
+ * If we hit either of those signals and the task is no longer valid, then the registered failure
+ * callback will be notified.
+ */
+public class TaskRemovedDuringLaunchListener implements ActivityLifecycleCallbacksAdapter {
+
+ private Activity mActivity;
+ private int mLaunchedTaskId = INVALID_TASK_ID;
+ private Runnable mTaskLaunchFailedCallback = null;
+
+ /**
+ * Registers a failure listener callback if it detects a scenario in which an app launch
+ * failed before the transition finished.
+ */
+ public void register(Activity activity, int launchedTaskId,
+ @NonNull Runnable taskLaunchFailedCallback) {
+ activity.registerActivityLifecycleCallbacks(this);
+ mActivity = activity;
+ mLaunchedTaskId = launchedTaskId;
+ mTaskLaunchFailedCallback = taskLaunchFailedCallback;
+ }
+
+ /**
+ * Unregisters the failure listener.
+ */
+ private void unregister() {
+ mActivity.unregisterActivityLifecycleCallbacks(this);
+ mActivity = null;
+ mLaunchedTaskId = INVALID_TASK_ID;
+ mTaskLaunchFailedCallback = null;
+ }
+
+ /**
+ * Called when the transition finishes.
+ */
+ public void onTransitionFinished() {
+ // The transition finished and Launcher was not stopped, check if the launch failed
+ checkTaskLaunchFailed();
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ // The normal task launch case, Launcher stops and updates its state correctly
+ unregister();
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ // The transition hasn't finished but Launcher was resumed, check if the launch failed
+ checkTaskLaunchFailed();
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ // If we somehow don't get any of the above signals, then just unregister this listener
+ unregister();
+ }
+
+ private void checkTaskLaunchFailed() {
+ if (mLaunchedTaskId != INVALID_TASK_ID) {
+ final int launchedTaskId = mLaunchedTaskId;
+ final Runnable taskLaunchFailedCallback = mTaskLaunchFailedCallback;
+ RecentsModel.INSTANCE.getNoCreate().isTaskRemoved(mLaunchedTaskId, (taskRemoved) -> {
+ if (taskRemoved) {
+ ActiveGestureLog.INSTANCE.addLog("Launch failed, task (id=" + launchedTaskId
+ + ") finished mid transition");
+ taskLaunchFailedCallback.run();
+ }
+ }, (task) -> true /* filter */);
+ unregister();
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
index 70a12d6..c8141b4 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
@@ -48,6 +48,8 @@
View child = hotseatIcons.getChildAt(i);
registerViewForAnimation(child);
}
+
+ super.onPrepareViewsForAnimation();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index 7da103e..c05b38f 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -58,6 +58,8 @@
setClipChildren(workspace, false);
setClipToPadding(workspace, true);
+
+ super.onPrepareViewsForAnimation();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProvider.kt b/quickstep/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProvider.kt
new file mode 100644
index 0000000..a9cd048
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProvider.kt
@@ -0,0 +1,161 @@
+/*
+ * 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.quickstep.util.unfold
+
+import android.os.Handler
+import android.os.Trace
+import android.util.Log
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+
+/**
+ * Transition progress provider wrapper that can preemptively start the transition on demand
+ * without relying on the source provider. When the source provider has started the animation
+ * it switches to it.
+ *
+ * This might be useful when we want to synchronously start the unfold animation and render
+ * the first frame during turning on the screen. For example, this is used in Launcher where
+ * we need to render the first frame of the animation immediately after receiving a configuration
+ * change event so Window Manager will wait for this frame to be rendered before unblocking
+ * the screen. We can't rely on the original transition progress as it starts the animation
+ * after the screen fully turned on (and unblocked), at this moment it is already too late to
+ * start the animation.
+ *
+ * Using this provider we could render the first frame preemptively by sending 'transition started'
+ * and '0' transition progress before the original progress provider sends these events.
+ */
+class PreemptiveUnfoldTransitionProgressProvider(
+ private val source: UnfoldTransitionProgressProvider,
+ private val handler: Handler
+) : UnfoldTransitionProgressProvider, TransitionProgressListener {
+
+ private val timeoutRunnable = Runnable {
+ if (isRunning) {
+ listeners.forEach { it.onTransitionFinished() }
+ onPreemptiveStartFinished()
+ Log.wtf(TAG, "Timeout occurred when waiting for the source transition to start")
+ }
+ }
+
+ private val listeners = arrayListOf<TransitionProgressListener>()
+ private var isPreemptivelyRunning = false
+ private var isSourceRunning = false
+
+ private val isRunning: Boolean
+ get() = isPreemptivelyRunning || isSourceRunning
+
+ private val sourceListener =
+ object : TransitionProgressListener {
+ override fun onTransitionStarted() {
+ handler.removeCallbacks(timeoutRunnable)
+
+ if (!isRunning) {
+ listeners.forEach { it.onTransitionStarted() }
+ }
+
+ onPreemptiveStartFinished()
+ isSourceRunning = true
+ }
+
+ override fun onTransitionProgress(progress: Float) {
+ if (isRunning) {
+ listeners.forEach { it.onTransitionProgress(progress) }
+ isSourceRunning = true
+ }
+ }
+
+ override fun onTransitionFinishing() {
+ if (isRunning) {
+ listeners.forEach { it.onTransitionFinishing() }
+ isSourceRunning = true
+ }
+ }
+
+ override fun onTransitionFinished() {
+ if (isRunning) {
+ listeners.forEach { it.onTransitionFinished() }
+ }
+
+ isSourceRunning = false
+ onPreemptiveStartFinished()
+ handler.removeCallbacks(timeoutRunnable)
+ }
+ }
+
+ fun init() {
+ source.addCallback(sourceListener)
+ }
+
+ /**
+ * Starts the animation preemptively.
+ *
+ * - If the source provider is already running, this method won't change any behavior
+ * - If the source provider has not started running yet, it will call onTransitionStarted
+ * for all listeners and optionally onTransitionProgress(initialProgress) if supplied.
+ * When the source provider starts the animation it will switch to send progress and finished
+ * events from it.
+ * If the source provider won't start the animation within a timeout, the animation will be
+ * cancelled and onTransitionFinished will be delivered to the current listeners.
+ */
+ @JvmOverloads
+ fun preemptivelyStartTransition(initialProgress: Float? = null) {
+ if (!isRunning) {
+ Trace.beginAsyncSection("$TAG#startedPreemptively", 0)
+
+ listeners.forEach { it.onTransitionStarted() }
+ initialProgress?.let { progress ->
+ listeners.forEach { it.onTransitionProgress(progress) }
+ }
+
+ handler.removeCallbacks(timeoutRunnable)
+ handler.postDelayed(timeoutRunnable, PREEMPTIVE_UNFOLD_TIMEOUT_MS)
+ }
+
+ isPreemptivelyRunning = true
+ }
+
+ fun cancelPreemptiveStart() {
+ handler.removeCallbacks(timeoutRunnable)
+ if (isRunning) {
+ listeners.forEach { it.onTransitionFinished() }
+ }
+ onPreemptiveStartFinished()
+ }
+
+ private fun onPreemptiveStartFinished() {
+ if (isPreemptivelyRunning) {
+ Trace.endAsyncSection("$TAG#startedPreemptively", 0)
+ isPreemptivelyRunning = false
+ }
+ }
+
+ override fun destroy() {
+ handler.removeCallbacks(timeoutRunnable)
+ source.removeCallback(sourceListener)
+ source.destroy()
+ }
+
+ override fun addCallback(listener: TransitionProgressListener) {
+ listeners += listener
+ }
+
+ override fun removeCallback(listener: TransitionProgressListener) {
+ listeners -= listener
+ }
+}
+
+const val TAG = "PreemptiveUnfoldTransitionProgressProvider"
+const val PREEMPTIVE_UNFOLD_TIMEOUT_MS = 1700L
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 379722b..1cfaf14 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -321,7 +321,7 @@
}
@Override
- public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
+ public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
launchTasks();
callback.accept(true);
}
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 5bfd035..c6c84bd 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -237,9 +237,9 @@
}
@Override
- public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
+ public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
getRecentsView().getSplitSelectController().launchTasks(mTask.key.id, mSecondaryTask.key.id,
- SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, callback, freezeTaskList,
+ SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, callback, isQuickswitch,
getSplitRatio());
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 8ff0e9b..2008129 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -39,6 +39,7 @@
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
+import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.PendingSplitSelectInfo;
@@ -79,9 +80,11 @@
}
@Override
- public void startHome() {
- mActivity.getStateManager().goToState(NORMAL);
- AbstractFloatingView.closeAllOpenViews(mActivity, mActivity.isStarted());
+ public void startHome(boolean animated) {
+ StateManager stateManager = mActivity.getStateManager();
+ animated &= stateManager.shouldAnimateStateChange();
+ stateManager.goToState(NORMAL, animated);
+ AbstractFloatingView.closeAllOpenViews(mActivity, animated);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f0afa69..f17f074 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -213,6 +213,7 @@
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* A list of recent tasks.
@@ -1320,6 +1321,29 @@
return null;
}
+ /**
+ * Returns a {@link TaskView} that has taskIds matching {@code taskIds} or null if no match.
+ */
+ @Nullable
+ public TaskView getTaskViewByTaskIds(int[] taskIds) {
+ if (!hasAnyValidTaskIds(taskIds)) {
+ return null;
+ }
+
+ for (int i = 0; i < getTaskViewCount(); i++) {
+ TaskView taskView = requireTaskViewAt(i);
+ if (Arrays.equals(taskIds, taskView.getTaskIds())) {
+ return taskView;
+ }
+ }
+ return null;
+ }
+
+ /** Returns false if {@code taskIds} is null or contains invalid values, true otherwise */
+ private boolean hasAnyValidTaskIds(int[] taskIds) {
+ return taskIds != null && !Arrays.equals(taskIds, INVALID_TASK_IDS);
+ }
+
public void setOverviewStateEnabled(boolean enabled) {
mOverviewStateEnabled = enabled;
updateTaskStackListenerState();
@@ -1589,10 +1613,10 @@
return;
}
- int currentTaskId = INVALID_TASK_ID;
+ int[] currentTaskId = INVALID_TASK_IDS;
TaskView currentTaskView = getTaskViewAt(mCurrentPage);
if (currentTaskView != null && currentTaskView.getTask() != null) {
- currentTaskId = currentTaskView.getTask().key.id;
+ currentTaskId = currentTaskView.getTaskIds();
}
// Unload existing visible task data
@@ -1604,8 +1628,8 @@
// Save running task ID if it exists before rebinding all taskViews, otherwise the task from
// the runningTaskView currently bound could get assigned to another TaskView
- int runningTaskId = getTaskIdsForTaskViewId(mRunningTaskViewId)[0];
- int focusedTaskId = getTaskIdsForTaskViewId(mFocusedTaskViewId)[0];
+ int[] runningTaskId = getTaskIdsForTaskViewId(mRunningTaskViewId);
+ int[] focusedTaskId = getTaskIdsForTaskViewId(mFocusedTaskViewId);
// Removing views sets the currentPage to 0, so we save this and restore it after
// the new set of views are added
@@ -1699,7 +1723,7 @@
}
// Keep same previous focused task
- TaskView newFocusedTaskView = getTaskViewByTaskId(focusedTaskId);
+ TaskView newFocusedTaskView = getTaskViewByTaskIds(focusedTaskId);
// If the list changed, maybe the focused task doesn't exist anymore
if (newFocusedTaskView == null && getTaskViewCount() > 0) {
newFocusedTaskView = getTaskViewAt(0);
@@ -1716,10 +1740,10 @@
updateChildTaskOrientations();
TaskView newRunningTaskView = null;
- if (runningTaskId != INVALID_TASK_ID) {
+ if (hasAnyValidTaskIds(runningTaskId)) {
// Update mRunningTaskViewId to be the new TaskView that was assigned by binding
// the full list of tasks to taskViews
- newRunningTaskView = getTaskViewByTaskId(runningTaskId);
+ newRunningTaskView = getTaskViewByTaskIds(runningTaskId);
if (newRunningTaskView != null) {
mRunningTaskViewId = newRunningTaskView.getTaskViewId();
} else {
@@ -1731,15 +1755,15 @@
if (mNextPage != INVALID_PAGE) {
// Restore mCurrentPage but don't call setCurrentPage() as that clobbers the scroll.
mCurrentPage = previousCurrentPage;
- if (currentTaskId != INVALID_TASK_ID) {
- currentTaskView = getTaskViewByTaskId(currentTaskId);
+ if (hasAnyValidTaskIds(currentTaskId)) {
+ currentTaskView = getTaskViewByTaskIds(currentTaskId);
if (currentTaskView != null) {
targetPage = indexOfChild(currentTaskView);
}
}
} else {
// Set the current page to the running task, but not if settling on new task.
- if (runningTaskId != INVALID_TASK_ID) {
+ if (hasAnyValidTaskIds(runningTaskId)) {
targetPage = indexOfChild(newRunningTaskView);
} else if (getTaskViewCount() > 0) {
TaskView taskView = requireTaskViewAt(0);
@@ -2210,8 +2234,8 @@
// Update the task data for the in/visible children
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView taskView = requireTaskViewAt(i);
- Task task = taskView.getTask();
- if (task == null) {
+ TaskIdAttributeContainer[] containers = taskView.getTaskIdAttributeContainers();
+ if (containers[0] == null && containers[1] == null) {
continue;
}
int index = indexOfChild(taskView);
@@ -2222,34 +2246,43 @@
visible = lower <= index && index <= upper;
}
if (visible) {
- boolean skipLoadingTask = false;
+ // Default update all non-null tasks, then remove running ones
+ List<Task> tasksToUpdate = Arrays.stream(containers).filter(Objects::nonNull)
+ .map(TaskIdAttributeContainer::getTask)
+ .collect(Collectors.toCollection(ArrayList::new));
if (mTmpRunningTasks != null) {
for (Task t : mTmpRunningTasks) {
- if (task == t) {
- // Skip loading if this is the task that we are animating into
- skipLoadingTask = true;
- break;
- }
+ // Skip loading if this is the task that we are animating into
+ // TODO(b/280812109) change this equality check to use A.equals(B)
+ tasksToUpdate.removeIf(task -> task == t);
}
}
- if (skipLoadingTask) {
+ if (tasksToUpdate.isEmpty()) {
continue;
}
- if (!mHasVisibleTaskData.get(task.key.id)) {
- // Ignore thumbnail update if it's current running task during the gesture
- // We snapshot at end of gesture, it will update then
- int changes = dataChanges;
- if (taskView == getRunningTaskView() && mGestureActive) {
- changes &= ~TaskView.FLAG_UPDATE_THUMBNAIL;
+ for (Task task : tasksToUpdate) {
+ if (!mHasVisibleTaskData.get(task.key.id)) {
+ // Ignore thumbnail update if it's current running task during the gesture
+ // We snapshot at end of gesture, it will update then
+ int changes = dataChanges;
+ if (taskView == getRunningTaskView() && mGestureActive) {
+ changes &= ~TaskView.FLAG_UPDATE_THUMBNAIL;
+ }
+ taskView.onTaskListVisibilityChanged(true /* visible */, changes);
}
- taskView.onTaskListVisibilityChanged(true /* visible */, changes);
+ mHasVisibleTaskData.put(task.key.id, visible);
}
- mHasVisibleTaskData.put(task.key.id, visible);
} else {
- if (mHasVisibleTaskData.get(task.key.id)) {
- taskView.onTaskListVisibilityChanged(false /* visible */, dataChanges);
+ for (TaskIdAttributeContainer container : containers) {
+ if (container == null) {
+ continue;
+ }
+
+ if (mHasVisibleTaskData.get(container.getTask().key.id)) {
+ taskView.onTaskListVisibilityChanged(false /* visible */, dataChanges);
+ }
+ mHasVisibleTaskData.delete(container.getTask().key.id);
}
- mHasVisibleTaskData.delete(task.key.id);
}
}
}
@@ -2285,7 +2318,11 @@
}
}
- public abstract void startHome();
+ public void startHome() {
+ startHome(mActivity.isStarted());
+ }
+
+ public abstract void startHome(boolean animated);
public void reset() {
setCurrentTask(-1);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 53660b5..134ef6c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -92,6 +92,7 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
+import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
@@ -102,6 +103,7 @@
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TaskCornerRadius;
+import com.android.quickstep.util.TaskRemovedDuringLaunchListener;
import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -651,7 +653,7 @@
* index 0 will contain the taskId, index 1 will be -1 indicating a null taskID value
*/
public int[] getTaskIds() {
- return mTaskIdContainer;
+ return Arrays.copyOf(mTaskIdContainer, mTaskIdContainer.length);
}
public boolean containsMultipleTasks() {
@@ -801,6 +803,14 @@
recentsView.addSideTaskLaunchCallback(callbackList);
return callbackList;
}
+ if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+ // If the recents transition is running (ie. in live tile mode), then the start
+ // of a new task will merge into the existing transition and it currently will
+ // not be run independently, so we need to rely on the onTaskAppeared() call
+ // for the new task to trigger the side launch callback to flush this runnable
+ // list (which is usually flushed when the app launch animation finishes)
+ recentsView.addSideTaskLaunchCallback(opts.onEndCallback);
+ }
return opts.onEndCallback;
} else {
notifyTaskLaunchFailed(TAG);
@@ -815,23 +825,44 @@
* Starts the task associated with this view without any animation
*/
public void launchTask(@NonNull Consumer<Boolean> callback) {
- launchTask(callback, false /* freezeTaskList */);
+ launchTask(callback, false /* isQuickswitch */);
}
/**
* Starts the task associated with this view without any animation
*/
- public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
+ public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
if (mTask != null) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
+ final TaskRemovedDuringLaunchListener
+ failureListener = new TaskRemovedDuringLaunchListener();
+ if (isQuickswitch) {
+ // We only listen for failures to launch in quickswitch because the during this
+ // gesture launcher is in the background state, vs other launches which are in
+ // the actual overview state
+ failureListener.register(mActivity, mTask.key.id, () -> {
+ notifyTaskLaunchFailed(TAG);
+ // Disable animations for now, as it is an edge case and the app usually covers
+ // launcher and also any state transition animation also gets clobbered by
+ // QuickstepTransitionManager.createWallpaperOpenAnimations when launcher
+ // shows again
+ getRecentsView().startHome(false /* animated */);
+ });
+ }
// Indicate success once the system has indicated that the transition has started
- ActivityOptions opts = makeCustomAnimation(getContext(), 0, 0,
- () -> callback.accept(true), MAIN_EXECUTOR.getHandler());
+ ActivityOptions opts = ActivityOptions.makeCustomTaskAnimation(getContext(), 0, 0,
+ MAIN_EXECUTOR.getHandler(),
+ elapsedRealTime -> {
+ callback.accept(true);
+ },
+ elapsedRealTime -> {
+ failureListener.onTransitionFinished();
+ });
opts.setLaunchDisplayId(
getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
- if (freezeTaskList) {
+ if (isQuickswitch) {
opts.setFreezeRecentTasksReordering();
}
opts.setDisableStartingWindow(mSnapshotView.shouldShowSplashView());
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 20466ad..2c16c15 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -16,8 +16,10 @@
package com.android.launcher3.taskbar
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController
+import com.android.launcher3.taskbar.bubbles.BubbleControllers
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController
import com.android.systemui.shared.rotation.RotationButtonController
+import java.util.Optional
import org.junit.Before
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@@ -54,6 +56,7 @@
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
@Mock lateinit var taskbarPinningController: TaskbarDividerPopupController
+ @Mock lateinit var optionalBubbleControllers: Optional<BubbleControllers>
lateinit var taskbarControllers: TaskbarControllers
@@ -94,6 +97,7 @@
taskbarEduTooltipController,
keyboardQuickSwitchController,
taskbarPinningController,
+ optionalBubbleControllers,
)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
new file mode 100644
index 0000000..9c0b2bf
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import static junit.framework.TestCase.assertEquals;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.tapl.Taskbar;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.LauncherLayoutBuilder;
+import com.android.launcher3.util.TestUtil;
+
+import org.junit.After;
+import org.junit.Assume;
+
+import java.util.List;
+
+public class AbstractTaplTestsTaskbar extends AbstractQuickStepTest {
+
+ protected static final String TEST_APP_NAME = "LauncherTestApp";
+ protected static final String TEST_APP_PACKAGE =
+ getInstrumentation().getContext().getPackageName();
+ protected static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+
+ protected AutoCloseable mLauncherLayout;
+ protected boolean mTaskbarWasInTransientMode;
+
+
+ @Override
+ public void setUp() throws Exception {
+ Assume.assumeTrue(mLauncher.isTablet());
+ super.setUp();
+
+ LauncherLayoutBuilder layoutBuilder = new LauncherLayoutBuilder().atHotseat(0).putApp(
+ "com.google.android.apps.nexuslauncher.tests",
+ "com.android.launcher3.testcomponent.BaseTestingActivity");
+ mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, layoutBuilder);
+ TaplTestsLauncher3.initialize(this);
+
+ startAppFast(CALCULATOR_APP_PACKAGE);
+ mLauncher.enableBlockTimeout(true);
+ mLauncher.showTaskbarIfHidden();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ setTaskbarMode(mLauncher, mTaskbarWasInTransientMode);
+ mLauncher.enableBlockTimeout(false);
+ if (mLauncherLayout != null) {
+ mLauncherLayout.close();
+ }
+ }
+
+ protected static boolean isTaskbarInTransientMode(Context context) {
+ return DisplayController.isTransientTaskbar(context);
+ }
+
+ protected Taskbar getTaskbar() {
+ Taskbar taskbar = mLauncher.getLaunchedAppState().getTaskbar();
+ List<String> taskbarIconNames = taskbar.getIconNames();
+ List<String> hotseatIconNames = mLauncher.getHotseatIconNames();
+
+ assertEquals("Taskbar and hotseat icon counts do not match",
+ taskbarIconNames.size(), hotseatIconNames.size());
+
+ for (int i = 0; i < taskbarIconNames.size(); i++) {
+ assertEquals("Taskbar and Hotseat icons do not match",
+ taskbarIconNames, hotseatIconNames);
+ }
+
+ return taskbar;
+ }
+
+ protected static void setTaskbarMode(LauncherInstrumentation launcher,
+ boolean expectTransientTaskbar) {
+ launcher.enableTransientTaskbar(expectTransientTaskbar);
+ launcher.recreateTaskbar();
+ launcher.checkForAnomaly(true, true);
+ AbstractLauncherUiTest.checkDetectedLeaks(launcher);
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
new file mode 100644
index 0000000..ee0eeb2
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTestsPersistentTaskbar extends AbstractTaplTestsTaskbar {
+
+ @Override
+ public void setUp() throws Exception {
+ mTaskbarWasInTransientMode = isTaskbarInTransientMode(mTargetContext);
+ setTaskbarMode(mLauncher, false);
+ super.setUp();
+ }
+
+ @Test
+ @TaskbarModeSwitch(mode = PERSISTENT)
+ public void testHideShowTaskbar() {
+ getTaskbar().hide();
+ mLauncher.getLaunchedAppState().showTaskbar();
+ }
+
+ @Test
+ @TaskbarModeSwitch(mode = PERSISTENT)
+ public void testHideTaskbarPersistsOnRecreate() {
+ getTaskbar().hide();
+ mLauncher.recreateTaskbar();
+ mLauncher.getLaunchedAppState().assertTaskbarHidden();
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 4540eee..021e118 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -15,125 +15,68 @@
*/
package com.android.quickstep;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
-
-import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
-import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
-
-import static junit.framework.TestCase.assertEquals;
-
-import android.content.Intent;
+import static com.android.quickstep.TaplTestsTaskbar.TaskbarMode.PERSISTENT;
+import static com.android.quickstep.TaplTestsTaskbar.TaskbarMode.TRANSIENT;
import androidx.test.filters.LargeTest;
-import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.tapl.Overview;
-import com.android.launcher3.tapl.Taskbar;
-import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.LauncherLayoutBuilder;
-import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
-import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
-import org.junit.After;
-import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
-import java.util.List;
+import java.util.Arrays;
+import java.util.Collection;
@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class TaplTestsTaskbar extends AbstractQuickStepTest {
+@RunWith(Parameterized.class)
+public class TaplTestsTaskbar extends AbstractTaplTestsTaskbar {
- private static final String TEST_APP_NAME = "LauncherTestApp";
- private static final String TEST_APP_PACKAGE =
- getInstrumentation().getContext().getPackageName();
- private static final String CALCULATOR_APP_PACKAGE =
- resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+ private final TaplTestsTaskbar.TaskbarMode mTaskbarMode;
- private AutoCloseable mLauncherLayout;
+ public enum TaskbarMode {
+ TRANSIENT, PERSISTENT
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {PERSISTENT}, {TRANSIENT}
+ });
+ }
+
+ public TaplTestsTaskbar(TaskbarMode mode) {
+ mTaskbarMode = mode;
+ }
@Override
public void setUp() throws Exception {
- Assume.assumeTrue(mLauncher.isTablet());
+ mTaskbarWasInTransientMode = isTaskbarInTransientMode(mTargetContext);
+ setTaskbarMode(mLauncher, isTaskbarTestModeTransient());
super.setUp();
-
- LauncherLayoutBuilder layoutBuilder = new LauncherLayoutBuilder().atHotseat(0).putApp(
- "com.google.android.apps.nexuslauncher.tests",
- "com.android.launcher3.testcomponent.BaseTestingActivity");
- mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, layoutBuilder);
- TaplTestsLauncher3.initialize(this);
- Overview overview = mLauncher.getWorkspace().switchToOverview();
- if (overview.hasTasks()) {
- overview.dismissAllTasks();
- }
-
- startAppFast(CALCULATOR_APP_PACKAGE);
- mLauncher.enableBlockTimeout(true);
- mLauncher.showTaskbarIfHidden();
}
- @After
- public void tearDown() throws Exception {
- mLauncher.enableBlockTimeout(false);
- if (mLauncherLayout != null) {
- mLauncherLayout.close();
+ @Test
+ public void testLaunchApp() {
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ // We are using parameterized test runner to share code between different test cases with
+ // taskbar variants. But, sometimes we only need to assert things for particular Taskbar
+ // variants.
+ if (isTaskbarTestModeTransient() && mLauncher.getNavigationModel()
+ != LauncherInstrumentation.NavigationModel.THREE_BUTTON) {
+ mLauncher.getLaunchedAppState().assertTaskbarHidden();
}
}
@Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testHideShowTaskbar() {
- getTaskbar().hide();
- mLauncher.getLaunchedAppState().showTaskbar();
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testHideTaskbarPersistsOnRecreate() {
- getTaskbar().hide();
- mLauncher.recreateTaskbar();
- mLauncher.getLaunchedAppState().assertTaskbarHidden();
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchApp() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- }
-
- @Test
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchApp() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- mLauncher.getLaunchedAppState().assertTaskbarHidden();
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testOpenMenu() throws Exception {
+ public void testOpenMenu() {
getTaskbar().getAppIcon(TEST_APP_NAME).openMenu();
}
@Test
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientOpenMenu() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME).openMenu();
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchShortcut() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .launch(TEST_APP_PACKAGE);
- }
-
- @Test
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchShortcut() throws Exception {
+ public void testLaunchShortcut() {
getTaskbar().getAppIcon(TEST_APP_NAME)
.openDeepShortcutMenu()
.getMenuItem("Shortcut 1")
@@ -143,145 +86,67 @@
@Test
@ScreenRecord // b/231615831
@PortraitLandscape
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchAppInSplitscreen() throws Exception {
+ public void testLaunchAppInSplitscreen() {
getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchAppInSplitscreen() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
- TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- mLauncher.getLaunchedAppState().assertTaskbarHidden();
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchShortcutInSplitscreen() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchShortcutInSplitscreen() throws Exception {
- getTaskbar().getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchApp_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- }
-
- @Test
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchApp_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testOpenMenu_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
- }
-
- @Test
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientOpenMenu_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
- }
-
- @Test
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchShortcut_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps()
- .getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .launch(TEST_APP_PACKAGE);
- }
-
- @Test
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchShortcut_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps()
- .getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .launch(TEST_APP_PACKAGE);
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps()
- .getAppIcon(TEST_APP_NAME)
- .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchAppInSplitscreen_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps()
- .getAppIcon(TEST_APP_NAME)
- .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = PERSISTENT)
- public void testLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps()
- .getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- @Test
- @ScreenRecord // b/231615831
- @PortraitLandscape
- @TaskbarModeSwitch(mode = TRANSIENT)
- public void testTransientLaunchShortcutInSplitscreen_FromTaskbarAllApps() throws Exception {
- getTaskbar().openAllApps()
- .getAppIcon(TEST_APP_NAME)
- .openDeepShortcutMenu()
- .getMenuItem("Shortcut 1")
- .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
- }
-
- private Taskbar getTaskbar() {
- Taskbar taskbar = mLauncher.getLaunchedAppState().getTaskbar();
- List<String> taskbarIconNames = taskbar.getIconNames();
- List<String> hotseatIconNames = mLauncher.getHotseatIconNames();
-
- assertEquals("Taskbar and hotseat icon counts do not match",
- taskbarIconNames.size(), hotseatIconNames.size());
-
- for (int i = 0; i < taskbarIconNames.size(); i++) {
- assertEquals("Taskbar and Hotseat icons do not match",
- taskbarIconNames, hotseatIconNames);
+ // We are using parameterized test runner to share code between different test cases with
+ // taskbar variants. But, sometimes we only need to assert things for particular Taskbar
+ // variants.
+ if (isTaskbarTestModeTransient()) {
+ mLauncher.getLaunchedAppState().assertTaskbarHidden();
}
+ }
- return taskbar;
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchShortcutInSplitscreen() {
+ getTaskbar().getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ public void testLaunchApp_fromTaskbarAllApps() {
+ getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ }
+
+ @Test
+ public void testOpenMenu_fromTaskbarAllApps() {
+ getTaskbar().openAllApps().getAppIcon(TEST_APP_NAME).openMenu();
+ }
+
+ @Test
+ public void testLaunchShortcut_fromTaskbarAllApps() {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .launch(TEST_APP_PACKAGE);
+ }
+
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchAppInSplitscreen_fromTaskbarAllApps() {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ @Test
+ @ScreenRecord // b/231615831
+ @PortraitLandscape
+ public void testLaunchShortcutInSplitscreen_fromTaskbarAllApps() {
+ getTaskbar().openAllApps()
+ .getAppIcon(TEST_APP_NAME)
+ .openDeepShortcutMenu()
+ .getMenuItem("Shortcut 1")
+ .dragToSplitscreen(TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ }
+
+ private boolean isTaskbarTestModeTransient() {
+ return TRANSIENT == mTaskbarMode;
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
new file mode 100644
index 0000000..6b61f18
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.config.FeatureFlags.ENABLE_CURSOR_HOVER_STATES;
+import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
+
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.util.TestUtil;
+import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplTestsTransientTaskbar extends AbstractTaplTestsTaskbar {
+
+ @Override
+ public void setUp() throws Exception {
+ mTaskbarWasInTransientMode = isTaskbarInTransientMode(mTargetContext);
+ setTaskbarMode(mLauncher, true);
+ super.setUp();
+ }
+
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testShowTaskbarUnstashHintOnHover() {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverToShowTaskbarUnstashHint();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testUnstashTaskbarOnScreenBottomEdgeHover() {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverScreenBottomEdgeToUnstashTaskbar();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ @TaskbarModeSwitch(mode = TRANSIENT)
+ public void testHoverBelowHintedTaskbarToUnstash() {
+ try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_CURSOR_HOVER_STATES, true)) {
+ getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().hoverBelowHintedTaskbarToUnstash();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index acfd54c..65542cf 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -33,14 +33,10 @@
import com.android.launcher3.statemanager.StateManager
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
-import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
-import com.android.launcher3.util.mock
import com.android.launcher3.util.withArgCaptor
import com.android.quickstep.RecentsModel
import com.android.quickstep.SystemUiProxy
import com.android.systemui.shared.recents.model.Task
-import java.util.ArrayList
-import java.util.function.Consumer
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
@@ -50,7 +46,9 @@
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import java.util.function.Consumer
@RunWith(AndroidJUnit4::class)
class SplitSelectStateControllerTest {
@@ -355,6 +353,7 @@
@Test
fun secondPendingIntentSet() {
val itemInfo = ItemInfo()
+ `when`(pendingIntent.creatorUserHandle).thenReturn(primaryUserHandle)
splitSelectStateController.setInitialTaskSelect(null, 0, itemInfo, null, 1)
splitSelectStateController.setSecondTask(pendingIntent)
assertTrue(splitSelectStateController.isBothSplitAppsConfirmed)
diff --git a/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt b/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt
new file mode 100644
index 0000000..f73be72
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/util/unfold/PreemptiveUnfoldTransitionProgressProviderTest.kt
@@ -0,0 +1,261 @@
+/*
+ * 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.quickstep.util.unfold
+
+import android.os.Handler
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import android.util.Log
+import androidx.test.filters.SmallTest
+import com.android.launcher3.util.any
+import com.android.launcher3.util.mock
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class PreemptiveUnfoldTransitionProgressProviderTest {
+
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var source: TransitionProgressListener
+ private lateinit var handler: Handler
+ private lateinit var oldWtfHandler: Log.TerribleFailureHandler
+ private val listener: TransitionProgressListener = mock()
+ private val testWtfHandler: Log.TerribleFailureHandler = mock()
+
+ private lateinit var provider: PreemptiveUnfoldTransitionProgressProvider
+
+ @Before
+ fun before() {
+ testableLooper = TestableLooper.get(this)
+ handler = Handler(testableLooper.looper)
+
+ val testSource = createSource()
+ source = testSource as TransitionProgressListener
+
+ oldWtfHandler = Log.setWtfHandler(testWtfHandler)
+
+ provider = PreemptiveUnfoldTransitionProgressProvider(testSource, handler)
+ provider.init()
+ provider.addCallback(listener)
+ }
+
+ @After
+ fun after() {
+ Log.setWtfHandler(oldWtfHandler)
+ }
+
+ @Test
+ fun preemptiveStartInitialProgressNull_transitionStarts() {
+ provider.preemptivelyStartTransition(initialProgress = null)
+
+ verify(listener).onTransitionStarted()
+ verify(listener, never()).onTransitionProgress(anyFloat())
+ }
+
+ @Test
+ fun preemptiveStartWithInitialProgress_startsAnimationAndSendsProgress() {
+ provider.preemptivelyStartTransition(initialProgress = 0.5f)
+
+ verify(listener).onTransitionStarted()
+ verify(listener).onTransitionProgress(0.5f)
+ }
+
+ @Test
+ fun preemptiveStartAndCancel_finishesAnimation() {
+ provider.preemptivelyStartTransition()
+ provider.cancelPreemptiveStart()
+
+ with(inOrder(listener)) {
+ verify(listener).onTransitionStarted()
+ verify(listener).onTransitionFinished()
+ }
+ }
+
+ @Test
+ fun preemptiveStartAndThenSourceStartsTransition_transitionStarts() {
+ provider.preemptivelyStartTransition()
+ source.onTransitionStarted()
+
+ verify(listener).onTransitionStarted()
+ }
+
+ @Test
+ fun preemptiveStartAndThenSourceStartsAndFinishesTransition_transitionFinishes() {
+ provider.preemptivelyStartTransition()
+
+ source.onTransitionStarted()
+ source.onTransitionFinished()
+
+ with(inOrder(listener)) {
+ verify(listener).onTransitionStarted()
+ verify(listener).onTransitionFinished()
+ }
+ }
+
+ @Test
+ fun preemptiveStartAndThenSourceStartsAnimationAndSendsProgress_sendsProgress() {
+ provider.preemptivelyStartTransition()
+
+ source.onTransitionStarted()
+ source.onTransitionProgress(0.4f)
+
+ verify(listener).onTransitionProgress(0.4f)
+ }
+
+ @Test
+ fun preemptiveStartAndThenSourceSendsProgress_sendsProgress() {
+ provider.preemptivelyStartTransition()
+
+ source.onTransitionProgress(0.4f)
+
+ verify(listener).onTransitionProgress(0.4f)
+ }
+
+ @Test
+ fun preemptiveStartAfterTransitionRunning_transitionStarted() {
+ source.onTransitionStarted()
+
+ provider.preemptivelyStartTransition()
+
+ verify(listener).onTransitionStarted()
+ }
+
+ @Test
+ fun preemptiveStartAfterTransitionRunningAndThenFinished_transitionFinishes() {
+ source.onTransitionStarted()
+
+ provider.preemptivelyStartTransition()
+ source.onTransitionFinished()
+
+ with(inOrder(listener)) {
+ verify(listener).onTransitionStarted()
+ verify(listener).onTransitionFinished()
+ }
+ }
+
+ @Test
+ fun preemptiveStart_transitionDoesNotFinishAfterTimeout_finishesTransition() {
+ provider.preemptivelyStartTransition()
+
+ testableLooper.moveTimeForward(PREEMPTIVE_UNFOLD_TIMEOUT_MS + 1)
+ testableLooper.processAllMessages()
+
+ with(inOrder(listener)) {
+ verify(listener).onTransitionStarted()
+ verify(listener).onTransitionFinished()
+ }
+ }
+
+ @Test
+ fun preemptiveStart_transitionFinishAfterTimeout_logsWtf() {
+ provider.preemptivelyStartTransition()
+
+ testableLooper.moveTimeForward(PREEMPTIVE_UNFOLD_TIMEOUT_MS + 1)
+ testableLooper.processAllMessages()
+
+ verify(testWtfHandler).onTerribleFailure(any(), any(), anyBoolean())
+ }
+
+ @Test
+ fun preemptiveStart_transitionDoesNotFinishBeforeTimeout_doesNotFinishTransition() {
+ provider.preemptivelyStartTransition()
+
+ testableLooper.moveTimeForward(PREEMPTIVE_UNFOLD_TIMEOUT_MS - 1)
+ testableLooper.processAllMessages()
+
+ verify(listener).onTransitionStarted()
+ }
+
+ @Test
+ fun preemptiveStart_transitionStarted_timeoutHappened_doesNotFinishTransition() {
+ provider.preemptivelyStartTransition()
+
+ source.onTransitionStarted()
+ testableLooper.moveTimeForward(PREEMPTIVE_UNFOLD_TIMEOUT_MS + 1)
+ testableLooper.processAllMessages()
+
+ verify(listener).onTransitionStarted()
+ }
+
+ @Test
+ fun noPreemptiveStart_transitionStarted_startsTransition() {
+ source.onTransitionStarted()
+
+ verify(listener).onTransitionStarted()
+ }
+
+ @Test
+ fun noPreemptiveStart_transitionProgress_sendsProgress() {
+ source.onTransitionStarted()
+
+ source.onTransitionProgress(0.5f)
+
+ verify(listener).onTransitionProgress(0.5f)
+ }
+
+ @Test
+ fun noPreemptiveStart_transitionFinishes_finishesTransition() {
+ source.onTransitionStarted()
+ source.onTransitionProgress(0.5f)
+
+ source.onTransitionFinished()
+
+ with(inOrder(listener)) {
+ verify(listener).onTransitionStarted()
+ verify(listener).onTransitionFinished()
+ }
+ }
+
+ private fun createSource(): UnfoldTransitionProgressProvider =
+ object : TransitionProgressListener, UnfoldTransitionProgressProvider {
+
+ private val listeners = arrayListOf<TransitionProgressListener>()
+
+ override fun addCallback(listener: TransitionProgressListener) {
+ listeners += listener
+ }
+
+ override fun removeCallback(listener: TransitionProgressListener) {
+ listeners -= listener
+ }
+
+ override fun destroy() {}
+
+ override fun onTransitionStarted() =
+ listeners.forEach(TransitionProgressListener::onTransitionStarted)
+
+ override fun onTransitionFinishing() =
+ listeners.forEach(TransitionProgressListener::onTransitionFinishing)
+
+ override fun onTransitionFinished() =
+ listeners.forEach(TransitionProgressListener::onTransitionFinished)
+
+ override fun onTransitionProgress(progress: Float) =
+ listeners.forEach { it.onTransitionProgress(progress) }
+ }
+}
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index 3f61aaa..6db4fb5 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -24,6 +24,7 @@
android:layout_weight="1"
android:importantForAccessibility="noHideDescendants"
android:hapticFeedbackEnabled="false"
+ android:clipChildren="false"
android:layout_marginVertical="8dp">
<!-- The image of the widget. This view does not support padding. Any placement adjustment
should be done using margins. Width & height are set at runtime after scaling the
diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml
index b76eef7..065c2ed 100644
--- a/res/layout/widgets_bottom_sheet_content.xml
+++ b/res/layout/widgets_bottom_sheet_content.xml
@@ -42,7 +42,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false"
- android:layout_marginVertical="16dp">
+ android:layout_marginTop="16dp">
<include layout="@layout/widgets_table_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 58a447d..9e73453 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -75,7 +75,6 @@
<color name="text_color_tertiary_dark">#CCFFFFFF</color>
<color name="wallpaper_popup_scrim">?android:attr/colorAccent</color>
- <color name="wallpaper_scrim_color">#0D878787</color>
<color name="workspace_accent_color_light">#ff8df5e3</color>
<color name="workspace_accent_color_dark">#ff3d665f</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1aa1871..786088e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -32,12 +32,6 @@
<dimen name="dynamic_grid_hotseat_bottom_tall_padding">0dp</dimen>
<dimen name="spring_loaded_hotseat_top_margin">76dp</dimen>
- <!-- Qsb -->
- <!-- Used for adjusting the position of QSB when placed in hotseat. This is a ratio and a higher
- number signifies that the QSB is close to the hotseat icons and a lower number signifies that
- it is close to the bottom of the screen -->
- <item name="qsb_center_factor" format="float" type="dimen">0.325</item>
-
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
<!-- Scalable Grid -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0714863..11861b9 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -314,6 +314,7 @@
<style name="DropTargetButtonBase" parent="@android:style/TextAppearance.DeviceDefault.Medium">
<item name="android:drawablePadding">@dimen/drop_target_button_drawable_padding</item>
<item name="android:padding">14dp</item>
+ <item name="android:includeFontPadding">false</item>
<item name="android:textColor">@color/drop_target_text</item>
<item name="android:textSize">@dimen/drop_target_text_size</item>
<item name="android:singleLine">true</item>
diff --git a/res/xml/dynamic_resources.xml b/res/xml/dynamic_resources.xml
index 3a3e239..f7a631b 100644
--- a/res/xml/dynamic_resources.xml
+++ b/res/xml/dynamic_resources.xml
@@ -4,6 +4,5 @@
<entry id="@color/delete_target_hover_tint" />
<entry id="@color/delete_target_hover_tint" />
<entry id="@color/delete_target_hover_tint" />
- <entry id="@color/wallpaper_scrim_color" />
</DynamicResources>
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index bc4a5c3..7131452 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -1,7 +1,5 @@
package com.android.launcher3;
-import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
-
import static com.android.launcher3.CellLayout.SPRING_LOADED_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
@@ -77,8 +75,6 @@
private DragLayer mDragLayer;
private ImageButton mReconfigureButton;
- private Rect mWidgetPadding;
-
private final int mBackgroundPadding;
private final int mTouchTargetWidth;
@@ -218,9 +214,6 @@
mMaxHSpan = info.maxSpanX;
mMaxVSpan = info.maxSpanY;
- mWidgetPadding = getDefaultPaddingForWidget(getContext(),
- widgetView.getAppWidgetInfo().provider, null);
-
// Only show resize handles for the directions in which resizing is possible.
InvariantDeviceProfile idp = LauncherAppState.getIDP(cellLayout.getContext());
mVerticalResizeActive = (info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0
@@ -517,16 +510,12 @@
*/
private void getSnappedRectRelativeToDragLayer(Rect out) {
float scale = mWidgetView.getScaleToFit();
-
mDragLayer.getViewRectRelativeToSelf(mWidgetView, out);
- int width = 2 * mBackgroundPadding
- + (int) (scale * (out.width() - mWidgetPadding.left - mWidgetPadding.right));
- int height = 2 * mBackgroundPadding
- + (int) (scale * (out.height() - mWidgetPadding.top - mWidgetPadding.bottom));
-
- int x = (int) (out.left - mBackgroundPadding + scale * mWidgetPadding.left);
- int y = (int) (out.top - mBackgroundPadding + scale * mWidgetPadding.top);
+ int width = 2 * mBackgroundPadding + Math.round(scale * out.width());
+ int height = 2 * mBackgroundPadding + Math.round(scale * out.height());
+ int x = out.left - mBackgroundPadding;
+ int y = out.top - mBackgroundPadding;
out.left = x;
out.top = y;
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index 5fbd48c..f041ffb 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -16,8 +16,8 @@
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.LoaderTask;
-import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.pm.UserCache;
@@ -52,7 +52,7 @@
* Updates the app widgets whose id has changed during the restore process.
*/
@WorkerThread
- public static void restoreAppWidgetIds(Context context, ModelDbController controller,
+ public static void restoreAppWidgetIds(Context context, DatabaseHelper helper,
int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
if (WidgetsModel.GO_DISABLE_WIDGETS) {
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
@@ -92,12 +92,12 @@
final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
int result = new ContentWriter(context,
- new ContentWriter.CommitParams(controller, where, args))
+ new ContentWriter.CommitParams(helper, where, args))
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
.put(LauncherSettings.Favorites.RESTORED, state)
.commit();
if (result == 0) {
- Cursor cursor = controller.getDb().query(
+ Cursor cursor = helper.getWritableDatabase().query(
Favorites.TABLE_NAME,
new String[] {Favorites.APPWIDGET_ID},
"appWidgetId=?", new String[] { oldWidgetId }, null, null, null);
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index fc7f614..1a86009 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.InputType;
@@ -58,8 +59,6 @@
public static final int TOOLTIP_LEFT = 1;
public static final int TOOLTIP_RIGHT = 2;
- private final Rect mTempRect = new Rect();
-
protected final ActivityContext mActivityContext;
protected final DropTargetHandler mDropTargetHandler;
protected DropTargetBar mDropTargetBar;
@@ -417,15 +416,11 @@
*/
@VisibleForTesting
protected boolean isTextClippedVertically(int availableHeight) {
- availableHeight -= getPaddingTop() + getPaddingBottom();
- if (availableHeight <= 0) {
- return true;
- }
+ Paint.FontMetricsInt fontMetricsInt = getPaint().getFontMetricsInt();
+ int lineCount = (getLineCount() <= 0) ? 1 : getLineCount();
+ int textHeight = lineCount * (fontMetricsInt.bottom - fontMetricsInt.top);
- getPaint().getTextBounds(mText.toString(), 0, mText.length(), mTempRect);
- // Add bounds bottom to height, as text bounds height measures from the text baseline and
- // above, which characters can descend below
- return mTempRect.bottom + mTempRect.height() >= availableHeight;
+ return textHeight + getPaddingTop() + getPaddingBottom() >= availableHeight;
}
/**
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 86c9f16..8675226 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -67,14 +67,12 @@
private static final int DEFAULT_DOT_SIZE = 100;
private static final float ALL_APPS_TABLET_MAX_ROWS = 5.5f;
private static final float MIN_FOLDER_TEXT_SIZE_SP = 16f;
+ private static final float MIN_WIDGET_PADDING_DP = 6f;
public static final PointF DEFAULT_SCALE = new PointF(1.0f, 1.0f);
public static final ViewScaleProvider DEFAULT_PROVIDER = itemInfo -> DEFAULT_SCALE;
public static final Consumer<DeviceProfile> DEFAULT_DIMENSION_PROVIDER = dp -> {};
- // Ratio of empty space, qsb should take up to appear visually centered.
- private final float mQsbCenterFactor;
-
public final InvariantDeviceProfile inv;
private final Info mInfo;
private final DisplayMetrics mMetrics;
@@ -252,6 +250,10 @@
// Insets
private final Rect mInsets = new Rect();
public final Rect workspacePadding = new Rect();
+ // Additional padding added to the widget inside its cellSpace. It is applied outside
+ // the widgetView, such that the actual view size is same as the widget size.
+ public final Rect widgetPadding = new Rect();
+
// When true, nav bar is on the left side of the screen.
private boolean mIsSeascape;
@@ -314,9 +316,6 @@
availableHeightPx = windowBounds.availableSize.y;
aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
- boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
- mQsbCenterFactor = res.getFloat(R.dimen.qsb_center_factor);
-
if (isTwoPanels) {
if (isLandscape) {
mTypeIndex = INDEX_TWO_PANEL_LANDSCAPE;
@@ -730,22 +729,6 @@
return mInfo;
}
- /**
- * We inset the widget padding added by the system and instead rely on the border spacing
- * between cells to create reliable consistency between widgets
- */
- public boolean shouldInsetWidgets() {
- Rect widgetPadding = inv.defaultWidgetPadding;
-
- // Check all sides to ensure that the widget won't overlap into another cell, or into
- // status bar.
- return workspaceTopPadding > widgetPadding.top
- && cellLayoutBorderSpacePx.x > widgetPadding.left
- && cellLayoutBorderSpacePx.y > widgetPadding.top
- && cellLayoutBorderSpacePx.x > widgetPadding.right
- && cellLayoutBorderSpacePx.y > widgetPadding.bottom;
- }
-
public Builder toBuilder(Context context) {
WindowBounds bounds = new WindowBounds(
widthPx, heightPx, availableWidthPx, availableHeightPx, rotationHint);
@@ -999,6 +982,18 @@
// Folder icon
folderIconSizePx = IconNormalizer.getNormalizedCircleSize(iconSizePx);
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
+
+ // Update widget padding:
+ float minSpacing = pxFromDp(MIN_WIDGET_PADDING_DP, mMetrics);
+ if (cellLayoutBorderSpacePx.x < minSpacing
+ || cellLayoutBorderSpacePx.y < minSpacing) {
+ widgetPadding.left = widgetPadding.right =
+ Math.round(Math.max(0, minSpacing - cellLayoutBorderSpacePx.x));
+ widgetPadding.top = widgetPadding.bottom =
+ Math.round(Math.max(0, minSpacing - cellLayoutBorderSpacePx.y));
+ } else {
+ widgetPadding.setEmpty();
+ }
}
/**
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index bb6d8b0..addcac9 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -152,6 +152,7 @@
firstButton.setTextVisible(true);
firstButton.setIconVisible(true);
firstButton.measure(widthSpec, heightSpec);
+ firstButton.resizeTextToFit();
} else if (visibleCount == 2) {
DeviceProfile dp = mLauncher.getDeviceProfile();
int verticalPadding = dp.dropTargetVerticalPaddingPx;
diff --git a/src/com/android/launcher3/DropTargetHandler.kt b/src/com/android/launcher3/DropTargetHandler.kt
index 277f8b3..6560e16 100644
--- a/src/com/android/launcher3/DropTargetHandler.kt
+++ b/src/com/android/launcher3/DropTargetHandler.kt
@@ -6,7 +6,6 @@
import com.android.launcher3.SecondaryDropTarget.DeferredOnComplete
import com.android.launcher3.dragndrop.DragLayer
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
-import com.android.launcher3.model.ModelWriter
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.model.data.LauncherAppWidgetInfo
import com.android.launcher3.util.IntSet
@@ -22,8 +21,6 @@
class DropTargetHandler(launcher: Launcher) {
val mLauncher: Launcher = launcher
- val modelWriter: ModelWriter = mLauncher.modelWriter
-
fun onDropAnimationComplete() {
mLauncher.stateManager.goToState(LauncherState.NORMAL)
}
@@ -87,7 +84,7 @@
else mLauncher.workspace.currentPageScreenIds
val onUndoClicked = Runnable {
mLauncher.setPagesToBindSynchronously(pageIds)
- modelWriter.abortDelete()
+ mLauncher.modelWriter.abortDelete()
mLauncher.statsLogManager.logger().log(LauncherEvent.LAUNCHER_UNDO)
}
@@ -95,7 +92,7 @@
mLauncher,
R.string.item_removed,
R.string.undo,
- modelWriter::commitDelete,
+ mLauncher.modelWriter::commitDelete,
onUndoClicked
)
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 5e07a3c..3aa582d 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -26,8 +26,6 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.annotation.TargetApi;
-import android.appwidget.AppWidgetHostView;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -35,7 +33,6 @@
import android.content.res.XmlResourceParser;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -192,7 +189,6 @@
public List<DeviceProfile> supportedProfiles = Collections.EMPTY_LIST;
public Point defaultWallpaperSize;
- public Rect defaultWidgetPadding;
private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
@@ -443,9 +439,6 @@
deviceProfile.numShownHotseatIcons = numMinShownHotseatIconsForTablet;
deviceProfile.recalculateHotseatWidthAndBorderSpace();
});
-
- ComponentName cn = new ComponentName(context.getPackageName(), getClass().getName());
- defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);
}
public void addOnChangeListener(OnIDPChangeListener listener) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6e98bda..ffd56cc 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1624,6 +1624,9 @@
return mModel;
}
+ /**
+ * Returns the ModelWriter writer, make sure to call the function every time you want to use it.
+ */
public ModelWriter getModelWriter() {
return mModelWriter;
}
@@ -3163,6 +3166,16 @@
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
+ // Close any open floating views.
+ closeOpenViews();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
// KEYCODE_MENU is sent by some tests, for example
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 9abec50..0df4bd4 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -263,6 +263,18 @@
getModelDbController().refreshHotseatRestoreTable();
return null;
}
+ case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
+ Bundle result = new Bundle();
+ result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
+ getModelDbController().updateCurrentOpenHelper(arg /* dbFile */));
+ return result;
+ }
+ case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: {
+ Bundle result = new Bundle();
+ result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
+ getModelDbController().prepareForPreview(arg /* dbFile */));
+ return result;
+ }
}
return null;
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 7fda326..b65e96b 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -148,6 +148,11 @@
public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup";
/**
+ * Temporary table used specifically for grid migrations during wallpaper preview
+ */
+ public static final String PREVIEW_TABLE_NAME = "favorites_preview";
+
+ /**
* Temporary table used specifically for multi-db grid migrations
*/
public static final String TMP_TABLE = "favorites_tmp";
@@ -159,6 +164,18 @@
+ LauncherProvider.AUTHORITY + "/" + TABLE_NAME);
/**
+ * The content:// style URL for "favorites_preview" table
+ */
+ public static final Uri PREVIEW_CONTENT_URI = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME);
+
+ /**
+ * The content:// style URL for "favorites_tmp" table
+ */
+ public static final Uri TMP_CONTENT_URI = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + TMP_TABLE);
+
+ /**
* The content:// style URL for a given row, identified by its id.
*
* @param id The row id.
@@ -359,6 +376,10 @@
public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
+ public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper";
+
+ public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview";
+
public static final String EXTRA_VALUE = "value";
public static final String EXTRA_DB_NAME = "db_name";
@@ -372,8 +393,11 @@
}
public static Bundle call(ContentResolver cr, String method, String arg) {
- return cr.call(CONTENT_URI, method, arg, null);
+ return call(cr, method, arg, null /* extras */);
}
+ public static Bundle call(ContentResolver cr, String method, String arg, Bundle extras) {
+ return cr.call(CONTENT_URI, method, arg, extras);
+ }
}
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index b00199f..a0ceefb 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -46,8 +46,6 @@
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private final int[] mTmpCellXY = new int[2];
- private final Rect mTempRect = new Rect();
-
@ContainerType
private final int mContainerType;
private final WallpaperManager mWallpaperManager;
@@ -124,13 +122,12 @@
CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
if (child instanceof NavigableAppWidgetHostView) {
DeviceProfile profile = mActivity.getDeviceProfile();
- ((NavigableAppWidgetHostView) child).getWidgetInset(profile, mTempRect);
final PointF appWidgetScale = profile.getAppWidgetScale((ItemInfo) child.getTag());
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- appWidgetScale.x, appWidgetScale.y, mBorderSpace, mTempRect);
+ appWidgetScale.x, appWidgetScale.y, mBorderSpace, profile.widgetPadding);
} else {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- mBorderSpace, null);
+ mBorderSpace);
}
}
@@ -149,13 +146,12 @@
final DeviceProfile dp = mActivity.getDeviceProfile();
if (child instanceof NavigableAppWidgetHostView) {
- ((NavigableAppWidgetHostView) child).getWidgetInset(dp, mTempRect);
final PointF appWidgetScale = dp.getAppWidgetScale((ItemInfo) child.getTag());
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- appWidgetScale.x, appWidgetScale.y, mBorderSpace, mTempRect);
+ appWidgetScale.x, appWidgetScale.y, mBorderSpace, dp.widgetPadding);
} else {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- mBorderSpace, null);
+ mBorderSpace);
// Center the icon/folder
int cHeight = getCellContentHeight();
int cellPaddingY = dp.isScalableGrid && mContainerType == WORKSPACE
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 6e6f1ac..98016f6 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2912,9 +2912,8 @@
Rect r = estimateItemPosition(layout, targetCell[0], targetCell[1], spanX, spanY);
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
DeviceProfile profile = mLauncher.getDeviceProfile();
- if (profile.shouldInsetWidgets() && finalView instanceof NavigableAppWidgetHostView) {
- Rect widgetPadding = new Rect();
- ((NavigableAppWidgetHostView) finalView).getWidgetInset(profile, widgetPadding);
+ if (finalView instanceof NavigableAppWidgetHostView) {
+ Rect widgetPadding = profile.widgetPadding;
r.left -= widgetPadding.left;
r.right += widgetPadding.right;
r.top -= widgetPadding.top;
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 01a4876..21dfbe1 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -871,8 +871,8 @@
boolean visible = deviceProfile.isTablet || mForceBottomSheetVisible;
mBottomSheetBackground.setVisibility(visible ? View.VISIBLE : View.GONE);
// Note: For tablets, the opaque background and header protection are added in drawOnScrim.
- // For the taskbar entrypoint, the scrim is drawn differently, so a static background is
- // added in TaskbarAllAppsContainerView and header protection is not yet supported.
+ // For the taskbar entrypoint, the scrim is drawn by its abstract slide in view container,
+ // so its header protection is derived from this scrim instead.
}
private void setBottomSheetAlpha(float alpha) {
diff --git a/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java b/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java
index 4b6a062..bdf7643 100644
--- a/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java
+++ b/src/com/android/launcher3/celllayout/CellLayoutLayoutParams.java
@@ -113,13 +113,13 @@
* full/invariant device profile sizes.
*/
public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount,
- int rowCount, Point borderSpace, @Nullable Rect inset) {
+ int rowCount, Point borderSpace) {
setup(cellWidth, cellHeight, invertHorizontally, colCount, rowCount, 1.0f, 1.0f,
- borderSpace, inset);
+ borderSpace, null);
}
/**
- * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, Point, Rect)},
+ * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, Point)},
* if the view needs to be scaled.
*
* ie. In multi-window mode, we setup widgets so that they are measured and laid out
@@ -150,10 +150,10 @@
y = topMargin + (myCellY * cellHeight) + (myCellY * borderSpace.y);
if (inset != null) {
- x -= inset.left;
- y -= inset.top;
- width += inset.left + inset.right;
- height += inset.top + inset.bottom;
+ x += inset.left;
+ y += inset.top;
+ width -= inset.left + inset.right;
+ height -= inset.top + inset.bottom;
}
}
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 331ae5d..8250a99 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -253,7 +253,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", DISABLED, "Enables two line label inside all apps.");
+ "ENABLE_TWOLINE_ALLAPPS", TEAMFOOD, "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");
@@ -314,6 +314,12 @@
"Enables receiving unfold animation events from sysui instead of calculating "
+ "them in launcher process using hinge sensor values.");
+ public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209,
+ "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED,
+ "Enables starting the unfold animation preemptively when unfolding, without"
+ + "waiting for SystemUI and then merging the SystemUI progress whenever we "
+ + "start receiving the events");
+
// TODO(Block 23): Clean up flags
public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
"ENABLE_GRID_ONLY_OVERVIEW", DISABLED,
@@ -366,10 +372,6 @@
"ENABLE_ENFORCED_ROUNDED_CORNERS", ENABLED,
"Enforce rounded corners on all App Widgets");
- public static final BooleanFlag ENABLE_WALLPAPER_SCRIM = getDebugFlag(270393604,
- "ENABLE_WALLPAPER_SCRIM", DISABLED,
- "Enables scrim over wallpaper for text protection.");
-
public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(270393294,
"ENABLE_ICON_LABEL_AUTO_SCALING", ENABLED,
"Enables scaling/spacing for icon labels to make more characters visible");
@@ -409,7 +411,7 @@
// TODO(Block 31)
public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(279494325,
- "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED,
+ "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", ENABLED,
"Use refactored split launching code path");
// TODO(Block 32): Empty block
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 4906c1d..00f4285 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -304,7 +304,8 @@
mWidgetOptions = pendingInfo.getDefaultSizeOptions(this);
mWidgetCell.getWidgetView().setTag(pendingInfo);
- applyWidgetItemAsync(() -> new WidgetItem(widgetInfo, mIdp, mApp.getIconCache()));
+ applyWidgetItemAsync(() -> new WidgetItem(
+ widgetInfo, mIdp, mApp.getIconCache(), mApp.getContext()));
return WidgetsModel.newPendingItemInfo(this, widgetInfo.getComponent(),
widgetInfo.getUser());
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 48239ae..2c1100f 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -74,7 +74,6 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.Thunk;
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 7f49aa9..b438e86 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -451,26 +451,8 @@
final Size origSize = WidgetSizes.getWidgetSizePx(mDpOrig,
launcherWidgetSize.getWidth(), launcherWidgetSize.getHeight());
final Size newSize = WidgetSizes.getWidgetSizePx(mDp, info.spanX, info.spanY);
- final Rect previewInset = new Rect();
- final Rect origInset = new Rect();
- // When the setup() is called for the LayoutParams, insets are added to the width
- // and height of the view. This is not accounted for in WidgetSizes and is handled
- // here.
- if (mDp.shouldInsetWidgets()) {
- previewInset.set(mDp.inv.defaultWidgetPadding);
- } else {
- previewInset.setEmpty();
- }
- if (mDpOrig.shouldInsetWidgets()) {
- origInset.set(mDpOrig.inv.defaultWidgetPadding);
- } else {
- origInset.setEmpty();
- }
-
- return new PointF((float) newSize.getWidth() / (origSize.getWidth()
- + origInset.left + origInset.right),
- (float) newSize.getHeight() / (origSize.getHeight()
- + origInset.top + origInset.bottom));
+ return new PointF((float) newSize.getWidth() / origSize.getWidth(),
+ (float) newSize.getHeight() / origSize.getHeight());
}
private void inflateAndAddPredictedIcon(WorkspaceItemInfo info) {
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 8f0b8ec..372e9bf 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -16,7 +16,6 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -53,8 +52,6 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.GridSizeMigrationUtil;
import com.android.launcher3.model.LoaderTask;
-import com.android.launcher3.model.ModelDbController;
-import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
@@ -148,9 +145,7 @@
final String query = LauncherSettings.Favorites.ITEM_TYPE + " = "
+ LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
- ModelDbController mainController =
- LauncherAppState.getInstance(mContext).getModel().getModelDbController();
- try (Cursor c = mainController.query(TABLE_NAME,
+ try (Cursor c = context.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[] {
LauncherSettings.Favorites.APPWIDGET_ID,
LauncherSettings.Favorites.SPANX,
@@ -195,6 +190,8 @@
@WorkerThread
private void loadModelData() {
+ final boolean migrated = doGridMigrationIfNecessary();
+
final Context inflationContext;
if (mWallpaperColors != null) {
// Create a themed context, without affecting the main application context
@@ -212,20 +209,8 @@
Themes.getActivityThemeRes(mContext));
}
- if (GridSizeMigrationUtil.needsToMigrate(inflationContext, mIdp)) {
- // Start the migration
+ if (migrated) {
PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
- // Copy existing data to preview DB
- LauncherDbUtils.copyTable(LauncherAppState.getInstance(mContext)
- .getModel().getModelDbController().getDb(),
- TABLE_NAME,
- LauncherAppState.getInstance(previewContext)
- .getModel().getModelDbController().getDb(),
- TABLE_NAME,
- mContext);
- LauncherAppState.getInstance(previewContext)
- .getModel().getModelDbController().clearEmptyDbFlag();
-
new LoaderTask(
LauncherAppState.getInstance(previewContext),
/* bgAllAppsList= */ null,
@@ -244,7 +229,8 @@
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
+ Workspace.SECOND_SCREEN_ID;
}
- loadWorkspace(new ArrayList<>(), query, null);
+ loadWorkspaceForPreviewSurfaceRenderer(new ArrayList<>(),
+ LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query);
final SparseArray<Size> spanInfo =
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
@@ -267,6 +253,14 @@
}
}
+ @WorkerThread
+ private boolean doGridMigrationIfNecessary() {
+ if (!GridSizeMigrationUtil.needsToMigrate(mContext, mIdp)) {
+ return false;
+ }
+ return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, mIdp);
+ }
+
@UiThread
private void renderView(Context inflationContext, BgDataModel dataModel,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap,
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index be995bc..21ebc98 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -36,13 +36,10 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.testing.shared.ResourceUtils;
-import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
import com.android.launcher3.util.Themes;
-import com.android.systemui.plugins.ResourceProvider;
/**
* View scrim which draws behind hotseat and workspace
@@ -100,10 +97,8 @@
private static final int ALPHA_MASK_BITMAP_DP = 200;
private static final int ALPHA_MASK_WIDTH_DP = 2;
- private boolean mDrawTopScrim, mDrawBottomScrim, mDrawWallpaperScrim;
+ private boolean mDrawTopScrim, mDrawBottomScrim;
- private final RectF mWallpaperScrimRect = new RectF();
- private final Paint mWallpaperScrimPaint = new Paint();
private final RectF mFinalMaskRect = new RectF();
private final Paint mBottomMaskPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
private final Bitmap mBottomMask;
@@ -118,7 +113,6 @@
private boolean mAnimateScrimOnNextDraw = false;
private float mSysUiAnimMultiplier = 1;
- private int mWallpaperScrimMaxAlpha;
public SysUiScrim(View view) {
mRoot = view;
@@ -135,14 +129,6 @@
mHideSysUiScrim = true;
}
- mDrawWallpaperScrim = FeatureFlags.ENABLE_WALLPAPER_SCRIM.get()
- && !Themes.getAttrBoolean(view.getContext(), R.attr.isMainColorDark)
- && !Themes.getAttrBoolean(view.getContext(), R.attr.isWorkspaceDarkText);
- ResourceProvider rp = DynamicResource.provider(view.getContext());
- int wallpaperScrimColor = rp.getColor(R.color.wallpaper_scrim_color);
- mWallpaperScrimMaxAlpha = Color.alpha(wallpaperScrimColor);
- mWallpaperScrimPaint.setColor(wallpaperScrimColor);
-
view.addOnAttachStateChangeListener(this);
}
@@ -167,9 +153,6 @@
mAnimateScrimOnNextDraw = false;
}
- if (mDrawWallpaperScrim) {
- canvas.drawRect(mWallpaperScrimRect, mWallpaperScrimPaint);
- }
if (mDrawTopScrim) {
mTopScrim.draw(canvas);
}
@@ -228,7 +211,6 @@
mTopScrim.setBounds(0, 0, w, h);
mFinalMaskRect.set(0, h - mMaskHeight, w, h);
}
- mWallpaperScrimRect.set(0, 0, w, h);
}
private void setSysUiProgress(float progress) {
@@ -251,7 +233,6 @@
if (mTopScrim != null) {
mTopScrim.setAlpha(Math.round(255 * factor));
}
- mWallpaperScrimPaint.setAlpha(Math.round(mWallpaperScrimMaxAlpha * factor));
}
private Bitmap createDitheredAlphaMask() {
diff --git a/src/com/android/launcher3/logging/StartupLatencyLogger.kt b/src/com/android/launcher3/logging/StartupLatencyLogger.kt
index 435f798..93e9de5 100644
--- a/src/com/android/launcher3/logging/StartupLatencyLogger.kt
+++ b/src/com/android/launcher3/logging/StartupLatencyLogger.kt
@@ -21,11 +21,14 @@
const val UNSET_LONG = -1L
}
- @VisibleForTesting val startTimeByEvent = SparseLongArray()
- @VisibleForTesting val endTimeByEvent = SparseLongArray()
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ val startTimeByEvent = SparseLongArray()
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ val endTimeByEvent = SparseLongArray()
- @VisibleForTesting var cardinality: Int = UNSET_INT
- @VisibleForTesting var workspaceLoadStartTime: Long = UNSET_LONG
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) var cardinality: Int = UNSET_INT
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ var workspaceLoadStartTime: Long = UNSET_LONG
private var isInTest = false
@@ -116,7 +119,7 @@
return true
}
if (startTimeByEvent.contains(event.id)) {
- Log.e(TAG, String.format("Cannot restart same %s event", event.name))
+ Log.e(TAG, "Cannot restart same ${event.name} event")
return false
} else if (
startTimeByEvent.isEmpty() &&
@@ -124,10 +127,8 @@
) {
Log.e(
TAG,
- String.format(
- "The first log start event must be %s.",
- LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION.name
- )
+ "The first log start event must be " +
+ "${LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION.name}.",
)
return false
} else if (
@@ -138,11 +139,7 @@
) {
Log.e(
TAG,
- String.format(
- "Cannot start %s event after %s starts",
- LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC.name,
- LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC.name
- )
+ "Cannot start ${LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC.name} event after ${LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC.name} starts",
)
return false
} else if (
@@ -153,11 +150,7 @@
) {
Log.e(
TAG,
- String.format(
- "Cannot start %s event after %s starts",
- LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC.name,
- LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC.name
- )
+ "Cannot start ${LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_ASYNC.name} event after ${LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_WORKSPACE_LOADER_SYNC.name} starts",
)
return false
}
@@ -172,10 +165,10 @@
return true
}
if (!startTimeByEvent.contains(event.id)) {
- Log.e(TAG, String.format("Cannot end %s event before starting it", event.name))
+ Log.e(TAG, "Cannot end ${event.name} event before starting it")
return false
} else if (endTimeByEvent.contains(event.id)) {
- Log.e(TAG, String.format("Cannot end same %s event again", event.name))
+ Log.e(TAG, "Cannot end same ${event.name} event again")
return false
} else if (
event != LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION &&
@@ -185,11 +178,7 @@
) {
Log.e(
TAG,
- String.format(
- "Cannot end %s event after %s",
- event.name,
- LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION.name
- )
+ "Cannot end ${event.name} event after ${LauncherLatencyEvent.LAUNCHER_LATENCY_STARTUP_TOTAL_DURATION.name}",
)
return false
}
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 8197b73..15f3538 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -891,6 +891,12 @@
return this;
}
+
+ /** Sets cardinality of the event. */
+ default StatsLatencyLogger withCardinality(int cardinality) {
+ return this;
+ }
+
/**
* Sets packageId of log message.
*/
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
index ecf5f67..dc5fcf7 100644
--- a/src/com/android/launcher3/model/DatabaseHelper.java
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -15,8 +15,8 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import android.content.ContentValues;
import android.content.Context;
@@ -36,6 +36,9 @@
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
@@ -55,7 +58,6 @@
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Locale;
-import java.util.function.ToLongFunction;
import java.util.stream.Collectors;
/**
@@ -74,23 +76,45 @@
private static final boolean LOGD = false;
private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
+ public static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
private final Context mContext;
- private final ToLongFunction<UserHandle> mUserSerialProvider;
- private final Runnable mOnEmptyDbCreateCallback;
-
+ private final boolean mForMigration;
private int mMaxItemId = -1;
public boolean mHotseatRestoreTableExists;
+ public static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) {
+ return createDatabaseHelper(context, null, forMigration);
+ }
+
+ public static DatabaseHelper createDatabaseHelper(Context context, String dbName,
+ boolean forMigration) {
+ if (dbName == null) {
+ dbName = InvariantDeviceProfile.INSTANCE.get(context).dbFile;
+ }
+ DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName, forMigration);
+ // Table creation sometimes fails silently, which leads to a crash loop.
+ // This way, we will try to create a table every time after crash, so the device
+ // would eventually be able to recover.
+ if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
+ Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
+ // This operation is a no-op if the table already exists.
+ databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true);
+ }
+ databaseHelper.mHotseatRestoreTableExists = tableExists(
+ databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
+
+ databaseHelper.initIds();
+ return databaseHelper;
+ }
+
/**
* Constructor used in tests and for restore.
*/
- public DatabaseHelper(Context context, String dbName,
- ToLongFunction<UserHandle> userSerialProvider, Runnable onEmptyDbCreateCallback) {
+ public DatabaseHelper(Context context, String dbName, boolean forMigration) {
super(context, dbName, SCHEMA_VERSION);
mContext = context;
- mUserSerialProvider = userSerialProvider;
- mOnEmptyDbCreateCallback = onEmptyDbCreateCallback;
+ mForMigration = forMigration;
}
protected void initIds() {
@@ -107,11 +131,13 @@
mMaxItemId = 1;
- addTableToDb(db, getDefaultUserSerial(), false /* optional */);
+ addFavoritesTable(db, false);
// Fresh and clean launcher DB.
mMaxItemId = initializeMaxItemId(db);
- mOnEmptyDbCreateCallback.run();
+ if (!mForMigration) {
+ onEmptyDbCreated();
+ }
}
public void onAddOrDeleteOp(SQLiteDatabase db) {
@@ -121,8 +147,38 @@
}
}
- private long getDefaultUserSerial() {
- return mUserSerialProvider.applyAsLong(Process.myUserHandle());
+ /**
+ * Re-composite given key in respect to database. If the current db is
+ * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
+ * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
+ * string will be "EMPTY_DATABASE_CREATED@minimal.db".
+ */
+ public String getKey(final String key) {
+ if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
+ return key;
+ }
+ return key + "@" + getDatabaseName();
+ }
+
+ /**
+ * Overridden in tests.
+ */
+ protected void onEmptyDbCreated() {
+ // Set the flag for empty DB
+ LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
+ .commit();
+ }
+
+ public long getSerialNumberForUser(UserHandle user) {
+ return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
+ }
+
+ public long getDefaultUserSerial() {
+ return getSerialNumberForUser(Process.myUserHandle());
+ }
+
+ private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
+ Favorites.addTableToDb(db, getDefaultUserSerial(), optional);
}
@Override
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index 9a6cde6..eded5ea 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -16,9 +16,6 @@
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
-import static com.android.launcher3.LauncherSettings.Favorites.TMP_TABLE;
-import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
import android.content.ComponentName;
@@ -37,15 +34,16 @@
import androidx.annotation.NonNull;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.LauncherPreviewRenderer;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -91,38 +89,81 @@
return needsToMigrate;
}
+ /** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */
+ public static boolean migrateGridIfNeeded(Context context) {
+ if (context instanceof LauncherPreviewRenderer.PreviewContext) {
+ return true;
+ }
+ return migrateGridIfNeeded(context, null);
+ }
+
/**
- * When migrating the grid, we copy the table
- * {@link LauncherSettings.Favorites#TABLE_NAME} from {@code source} into
- * {@link LauncherSettings.Favorites#TMP_TABLE}, run the grid size migration algorithm
+ * When migrating the grid for preview, we copy the table
+ * {@link LauncherSettings.Favorites#TABLE_NAME} into
+ * {@link LauncherSettings.Favorites#PREVIEW_TABLE_NAME}, run grid size migration from the
+ * former to the later, then use the later table for preview.
+ *
+ * Similarly when doing the actual grid migration, the former grid option's table
+ * {@link LauncherSettings.Favorites#TABLE_NAME} is copied into the new grid option's
+ * {@link LauncherSettings.Favorites#TMP_TABLE}, we then run the grid size migration algorithm
* to migrate the later to the former, and load the workspace from the default
* {@link LauncherSettings.Favorites#TABLE_NAME}.
*
* @return false if the migration failed.
*/
- public static boolean migrateGridIfNeeded(
- @NonNull Context context,
- @NonNull InvariantDeviceProfile idp,
- @NonNull DatabaseHelper target,
- @NonNull SQLiteDatabase source) {
+ public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
+ boolean migrateForPreview = idp != null;
+ if (!migrateForPreview) {
+ idp = LauncherAppState.getIDP(context);
+ }
DeviceGridState srcDeviceState = new DeviceGridState(context);
DeviceGridState destDeviceState = new DeviceGridState(idp);
if (!needsToMigrate(srcDeviceState, destDeviceState)) {
return true;
}
- copyTable(source, TABLE_NAME, target.getWritableDatabase(), TMP_TABLE, context);
HashSet<String> validPackages = getValidPackages(context);
+
+ if (migrateForPreview) {
+ if (!LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW,
+ destDeviceState.getDbFile()).getBoolean(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+ return false;
+ }
+ } else if (!LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER,
+ destDeviceState.getDbFile()).getBoolean(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+ return false;
+ }
+
long migrationStartTime = System.currentTimeMillis();
- try (SQLiteTransaction t = new SQLiteTransaction(target.getWritableDatabase())) {
- DbReader srcReader = new DbReader(t.getDb(), TMP_TABLE, context, validPackages);
- DbReader destReader = new DbReader(t.getDb(), TABLE_NAME, context, validPackages);
+ try (SQLiteTransaction t = (SQLiteTransaction) LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+
+ DbReader srcReader = new DbReader(t.getDb(),
+ migrateForPreview ? LauncherSettings.Favorites.TABLE_NAME
+ : LauncherSettings.Favorites.TMP_TABLE,
+ context, validPackages);
+ DbReader destReader = new DbReader(t.getDb(),
+ migrateForPreview ? LauncherSettings.Favorites.PREVIEW_TABLE_NAME
+ : LauncherSettings.Favorites.TABLE_NAME,
+ context, validPackages);
Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
- migrate(target, srcReader, destReader, destDeviceState.getNumHotseat(),
+ migrate(context, t.getDb(), srcReader, destReader, destDeviceState.getNumHotseat(),
targetSize, srcDeviceState, destDeviceState);
- dropTable(t.getDb(), TMP_TABLE);
+
+ if (!migrateForPreview) {
+ dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
+ }
+
t.commit();
return true;
} catch (Exception e) {
@@ -133,7 +174,7 @@
Log.v(TAG, "Workspace migration completed in "
+ (System.currentTimeMillis() - migrationStartTime));
- if (!(context instanceof SandboxContext)) {
+ if (!migrateForPreview) {
// Save current configuration, so that the migration does not run again.
destDeviceState.writeToPrefs(context);
}
@@ -141,7 +182,7 @@
}
public static boolean migrate(
- @NonNull DatabaseHelper helper,
+ @NonNull final Context context, @NonNull final SQLiteDatabase db,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
final int destHotseatSize, @NonNull final Point targetSize,
@NonNull final DeviceGridState srcDeviceState,
@@ -193,8 +234,8 @@
Collections.sort(workspaceToBeAdded);
// Migrate hotseat
- solveHotseatPlacement(helper, destHotseatSize,
- srcReader, destReader, dstHotseatItems, hotseatToBeAdded);
+ solveHotseatPlacement(db, srcReader,
+ destReader, context, destHotseatSize, dstHotseatItems, hotseatToBeAdded);
// Migrate workspace.
// First we create a collection of the screens
@@ -214,8 +255,8 @@
if (DEBUG) {
Log.d(TAG, "Migrating " + screenId);
}
- solveGridPlacement(helper, srcReader,
- destReader, screenId, trgX, trgY, workspaceToBeAdded, false);
+ solveGridPlacement(db, srcReader,
+ destReader, context, screenId, trgX, trgY, workspaceToBeAdded, false);
if (workspaceToBeAdded.isEmpty()) {
break;
}
@@ -225,8 +266,8 @@
// any of the screens, in this case we add them to new screens until all of them are placed.
int screenId = destReader.mLastScreenId + 1;
while (!workspaceToBeAdded.isEmpty()) {
- solveGridPlacement(helper, srcReader,
- destReader, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
+ solveGridPlacement(db, srcReader,
+ destReader, context, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
screenId++;
}
@@ -257,33 +298,33 @@
});
}
- private static void insertEntryInDb(DatabaseHelper helper, DbEntry entry,
+ private static void insertEntryInDb(SQLiteDatabase db, Context context, DbEntry entry,
String srcTableName, String destTableName) {
- int id = copyEntryAndUpdate(helper, entry, srcTableName, destTableName);
+ int id = copyEntryAndUpdate(db, context, entry, srcTableName, destTableName);
if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
for (Set<Integer> itemIds : entry.mFolderItems.values()) {
for (int itemId : itemIds) {
- copyEntryAndUpdate(helper, itemId, id, srcTableName, destTableName);
+ copyEntryAndUpdate(db, context, itemId, id, srcTableName, destTableName);
}
}
}
}
- private static int copyEntryAndUpdate(DatabaseHelper helper,
+ private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
DbEntry entry, String srcTableName, String destTableName) {
- return copyEntryAndUpdate(helper, entry, -1, -1, srcTableName, destTableName);
+ return copyEntryAndUpdate(db, context, entry, -1, -1, srcTableName, destTableName);
}
- private static int copyEntryAndUpdate(DatabaseHelper helper,
+ private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
int id, int folderId, String srcTableName, String destTableName) {
- return copyEntryAndUpdate(helper, null, id, folderId, srcTableName, destTableName);
+ return copyEntryAndUpdate(db, context, null, id, folderId, srcTableName, destTableName);
}
- private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry,
- int id, int folderId, String srcTableName, String destTableName) {
+ private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
+ DbEntry entry, int id, int folderId, String srcTableName, String destTableName) {
int newId = -1;
- Cursor c = helper.getWritableDatabase().query(srcTableName, null,
+ Cursor c = db.query(srcTableName, null,
LauncherSettings.Favorites._ID + " = '" + (entry != null ? entry.id : id) + "'",
null, null, null, null);
while (c.moveToNext()) {
@@ -294,9 +335,11 @@
} else {
values.put(LauncherSettings.Favorites.CONTAINER, folderId);
}
- newId = helper.generateNewItemId();
+ newId = LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt(
+ LauncherSettings.Settings.EXTRA_VALUE);
values.put(LauncherSettings.Favorites._ID, newId);
- helper.getWritableDatabase().insert(destTableName, null, values);
+ db.insert(destTableName, null, values);
}
c.close();
return newId;
@@ -324,9 +367,9 @@
return validPackages;
}
- private static void solveGridPlacement(@NonNull final DatabaseHelper helper,
+ private static void solveGridPlacement(@NonNull final SQLiteDatabase db,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
- final int screenId, final int trgX, final int trgY,
+ @NonNull final Context context, final int screenId, final int trgX, final int trgY,
@NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
final Point trg = new Point(trgX, trgY);
@@ -348,7 +391,7 @@
continue;
}
if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
- insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
+ insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
iterator.remove();
}
}
@@ -385,9 +428,9 @@
return false;
}
- private static void solveHotseatPlacement(
- @NonNull final DatabaseHelper helper, final int hotseatSize,
+ private static void solveHotseatPlacement(@NonNull final SQLiteDatabase db,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
+ @NonNull final Context context, final int hotseatSize,
@NonNull final List<DbEntry> placedHotseatItems,
@NonNull final List<DbEntry> itemsToPlace) {
@@ -404,7 +447,7 @@
// to something other than -1.
entry.cellX = i;
entry.cellY = 0;
- insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
+ insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
occupied[entry.screenId] = true;
}
}
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 2054d93..a5dccc1 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -16,16 +16,16 @@
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
-
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.CursorWrapper;
+import android.net.Uri;
import android.os.UserHandle;
import android.provider.BaseColumns;
import android.text.TextUtils;
@@ -66,7 +66,9 @@
private final LongSparseArray<UserHandle> allUsers;
private final LauncherAppState mApp;
+ private final Uri mContentUri;
private final Context mContext;
+ private final PackageManager mPM;
private final IconCache mIconCache;
private final InvariantDeviceProfile mIDP;
@@ -106,14 +108,17 @@
public int itemType;
public int restoreFlag;
- public LoaderCursor(Cursor cursor, LauncherAppState app, UserManagerState userManagerState) {
+ public LoaderCursor(Cursor cursor, Uri contentUri, LauncherAppState app,
+ UserManagerState userManagerState) {
super(cursor);
mApp = app;
allUsers = userManagerState.allUsers;
+ mContentUri = contentUri;
mContext = app.getContext();
mIconCache = app.getIconCache();
mIDP = app.getInvariantDeviceProfile();
+ mPM = mContext.getPackageManager();
// Init column indices
mIconIndex = getColumnIndexOrThrow(Favorites.ICON);
@@ -385,7 +390,7 @@
*/
public ContentWriter updater() {
return new ContentWriter(mContext, new ContentWriter.CommitParams(
- mApp.getModel().getModelDbController(),
+ mApp.getModel().getModelDbController().getDatabaseHelper(),
BaseColumns._ID + "= ?", new String[]{Integer.toString(id)}));
}
@@ -404,8 +409,8 @@
public boolean commitDeleted() {
if (mItemsToRemove.size() > 0) {
// Remove dead items
- mApp.getModel().getModelDbController().delete(TABLE_NAME,
- Utilities.createDbSelectionQuery(Favorites._ID, mItemsToRemove), null);
+ mContext.getContentResolver().delete(mContentUri, Utilities.createDbSelectionQuery(
+ Favorites._ID, mItemsToRemove), null);
return true;
}
return false;
@@ -430,8 +435,9 @@
// Update restored items that no longer require special handling
ContentValues values = new ContentValues();
values.put(Favorites.RESTORED, 0);
- mApp.getModel().getModelDbController().update(TABLE_NAME, values,
- Utilities.createDbSelectionQuery(Favorites._ID, mRestoredRows), null);
+ mContext.getContentResolver().update(mContentUri, values,
+ Utilities.createDbSelectionQuery(
+ Favorites._ID, mRestoredRows), null);
}
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index d4eded5..9053d19 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -16,7 +16,6 @@
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
@@ -42,6 +41,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Point;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Trace;
import android.os.UserHandle;
@@ -50,6 +50,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
+import android.util.TimingLogger;
import androidx.annotation.Nullable;
@@ -199,10 +200,25 @@
}
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
+ TimingLogger timingLogger = new TimingLogger(TAG, "run");
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
- loadWorkspace(allShortcuts, "", memoryLogger);
+ Trace.beginSection("LoadWorkspace");
+ try {
+ loadWorkspace(allShortcuts, memoryLogger);
+ } finally {
+ Trace.endSection();
+ }
+ logASplit(timingLogger, "loadWorkspace");
+
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ verifyNotStopped();
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.markActive();
+ logASplit(timingLogger, "workspaceDelegateItems");
+ }
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
// sanitizeData should not be invoked if the workspace is loaded from a db different
@@ -212,21 +228,21 @@
verifyNotStopped();
sanitizeFolders(mItemsDeleted);
sanitizeWidgetsShortcutsAndPackages();
- logASplit("sanitizeData");
+ logASplit(timingLogger, "sanitizeData");
}
verifyNotStopped();
mLauncherBinder.bindWorkspace(true /* incrementBindId */, /* isBindSync= */ false);
- logASplit("bindWorkspace");
+ logASplit(timingLogger, "bindWorkspace");
mModelDelegate.workspaceLoadComplete();
// Notify the installer packages of packages with active installs on the first screen.
sendFirstScreenActiveInstallsBroadcast();
- logASplit("sendFirstScreenActiveInstallsBroadcast");
+ logASplit(timingLogger, "sendFirstScreenActiveInstallsBroadcast");
// Take a break
waitForIdle();
- logASplit("step 1 complete");
+ logASplit(timingLogger, "step 1 complete");
verifyNotStopped();
// second step
@@ -237,16 +253,16 @@
} finally {
Trace.endSection();
}
- logASplit("loadAllApps");
+ logASplit(timingLogger, "loadAllApps");
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
- logASplit("allAppsDelegateItems");
+ logASplit(timingLogger, "allAppsDelegateItems");
}
verifyNotStopped();
mLauncherBinder.bindAllApps();
- logASplit("bindAllApps");
+ logASplit(timingLogger, "bindAllApps");
verifyNotStopped();
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
@@ -254,73 +270,75 @@
updateHandler.updateIcons(allActivityList,
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
mApp.getModel()::onPackageIconsUpdated);
- logASplit("update icon cache");
+ logASplit(timingLogger, "update icon cache");
verifyNotStopped();
- logASplit("save shortcuts in icon cache");
+ logASplit(timingLogger, "save shortcuts in icon cache");
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
mApp.getModel()::onPackageIconsUpdated);
// Take a break
waitForIdle();
- logASplit("step 2 complete");
+ logASplit(timingLogger, "step 2 complete");
verifyNotStopped();
// third step
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
- logASplit("loadDeepShortcuts");
+ logASplit(timingLogger, "loadDeepShortcuts");
verifyNotStopped();
mLauncherBinder.bindDeepShortcuts();
- logASplit("bindDeepShortcuts");
+ logASplit(timingLogger, "bindDeepShortcuts");
verifyNotStopped();
- logASplit("save deep shortcuts in icon cache");
+ logASplit(timingLogger, "save deep shortcuts in icon cache");
updateHandler.updateIcons(allDeepShortcuts,
new ShortcutCachingLogic(), (pkgs, user) -> { });
// Take a break
waitForIdle();
- logASplit("step 3 complete");
+ logASplit(timingLogger, "step 3 complete");
verifyNotStopped();
// fourth step
List<ComponentWithLabelAndIcon> allWidgetsList =
mBgDataModel.widgetsModel.update(mApp, null);
- logASplit("load widgets");
+ logASplit(timingLogger, "load widgets");
verifyNotStopped();
mLauncherBinder.bindWidgets();
- logASplit("bindWidgets");
+ logASplit(timingLogger, "bindWidgets");
verifyNotStopped();
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
- logASplit("otherDelegateItems");
+ logASplit(timingLogger, "otherDelegateItems");
verifyNotStopped();
}
updateHandler.updateIcons(allWidgetsList,
new ComponentWithIconCachingLogic(mApp.getContext(), true),
mApp.getModel()::onWidgetLabelsUpdated);
- logASplit("save widgets in icon cache");
+ logASplit(timingLogger, "save widgets in icon cache");
// fifth step
loadFolderNames();
verifyNotStopped();
updateHandler.finish();
- logASplit("finish icon update");
+ logASplit(timingLogger, "finish icon update");
mModelDelegate.modelLoadComplete();
transaction.commit();
memoryLogger.clearLogs();
} catch (CancellationException e) {
// Loader stopped, ignore
- logASplit("Cancelled");
+ logASplit(timingLogger, "Cancelled");
} catch (Exception e) {
memoryLogger.printLogs();
throw e;
+ } finally {
+ timingLogger.dumpToLog();
}
TraceHelper.INSTANCE.endSection(traceToken);
}
@@ -330,29 +348,25 @@
this.notify();
}
- protected void loadWorkspace(
- List<ShortcutInfo> allDeepShortcuts,
- String selection,
- LoaderMemoryLogger memoryLogger) {
- Trace.beginSection("LoadWorkspace");
- try {
- loadWorkspaceImpl(allDeepShortcuts, selection, memoryLogger);
- } finally {
- Trace.endSection();
- }
- logASplit("loadWorkspace");
+ private void loadWorkspace(
+ List<ShortcutInfo> allDeepShortcuts, LoaderMemoryLogger memoryLogger) {
+ loadWorkspace(allDeepShortcuts, Favorites.CONTENT_URI,
+ null /* selection */, memoryLogger);
+ }
+ protected void loadWorkspaceForPreviewSurfaceRenderer(
+ List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
+ loadWorkspace(allDeepShortcuts, contentUri, selection, null);
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
- verifyNotStopped();
mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
mModelDelegate.markActive();
- logASplit("workspaceDelegateItems");
}
}
- private void loadWorkspaceImpl(
+ protected void loadWorkspace(
List<ShortcutInfo> allDeepShortcuts,
+ Uri contentUri,
String selection,
@Nullable LoaderMemoryLogger memoryLogger) {
final Context context = mApp.getContext();
@@ -363,7 +377,7 @@
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
boolean clearDb = false;
- if (!mApp.getModel().getModelDbController().migrateGridIfNeeded()) {
+ if (!GridSizeMigrationUtil.migrateGridIfNeeded(context)) {
// Migration failed. Clear workspace.
clearDb = true;
}
@@ -388,9 +402,8 @@
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
mShortcutKeyToPinnedShortcuts = new HashMap<>();
- ModelDbController dbController = mApp.getModel().getModelDbController();
final LoaderCursor c = new LoaderCursor(
- dbController.query(TABLE_NAME, null, selection, null, null),
+ contentResolver.query(contentUri, null, selection, null, null), contentUri,
mApp, mUserManagerState);
final Bundle extras = c.getExtras();
mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME);
@@ -1099,9 +1112,12 @@
FileLog.d(TAG, widgetDimension.toString());
}
- private static void logASplit(String label) {
- if (DEBUG) {
- Log.d(TAG, label);
+ private static void logASplit(@Nullable TimingLogger timingLogger, String label) {
+ if (timingLogger != null) {
+ timingLogger.addSplit(label);
+ if (DEBUG) {
+ Log.d(TAG, label);
+ }
}
}
}
diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java
index 1274c08..97bce8c 100644
--- a/src/com/android/launcher3/model/ModelDbController.java
+++ b/src/com/android/launcher3/model/ModelDbController.java
@@ -19,10 +19,11 @@
import static android.util.Base64.NO_WRAP;
import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT;
-import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG;
+import static com.android.launcher3.model.DatabaseHelper.EMPTY_DATABASE_CREATED;
+import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import android.app.blob.BlobHandle;
@@ -30,6 +31,7 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
@@ -41,7 +43,6 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
@@ -53,22 +54,18 @@
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.AutoInstallsLayout.SourceResources;
-import com.android.launcher3.ConstantItem;
import com.android.launcher3.DefaultLayoutParser;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
-import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
import com.android.launcher3.util.Partner;
import com.android.launcher3.widget.LauncherWidgetHolder;
@@ -76,6 +73,7 @@
import java.io.InputStream;
import java.io.StringReader;
+import java.util.function.Supplier;
/**
* Utility class which maintains an instance of Launcher database and provides utility methods
@@ -84,8 +82,6 @@
public class ModelDbController {
private static final String TAG = "LauncherProvider";
- private static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
-
protected DatabaseHelper mOpenHelper;
private final Context mContext;
@@ -96,36 +92,26 @@
private synchronized void createDbIfNotExists() {
if (mOpenHelper == null) {
- mOpenHelper = createDatabaseHelper(false /* forMigration */);
- RestoreDbTask.restoreIfNeeded(mContext, this);
+ mOpenHelper = DatabaseHelper.createDatabaseHelper(
+ mContext, false /* forMigration */);
+
+ RestoreDbTask.restoreIfNeeded(mContext, mOpenHelper);
}
}
- protected DatabaseHelper createDatabaseHelper(boolean forMigration) {
- boolean isSandbox = mContext instanceof SandboxContext;
- String dbName = isSandbox ? null : InvariantDeviceProfile.INSTANCE.get(mContext).dbFile;
-
- // Set the flag for empty DB
- Runnable onEmptyDbCreateCallback = forMigration ? () -> { }
- : () -> LauncherPrefs.get(mContext).putSync(getEmptyDbCreatedKey(dbName).to(true));
-
- DatabaseHelper databaseHelper = new DatabaseHelper(mContext, dbName,
- this::getSerialNumberForUser, onEmptyDbCreateCallback);
- // Table creation sometimes fails silently, which leads to a crash loop.
- // This way, we will try to create a table every time after crash, so the device
- // would eventually be able to recover.
- if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
- Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
- // This operation is a no-op if the table already exists.
- addTableToDb(databaseHelper.getWritableDatabase(),
- getSerialNumberForUser(Process.myUserHandle()),
- true /* optional */);
+ private synchronized boolean prepForMigration(String dbFile, String targetTableName,
+ Supplier<DatabaseHelper> src, Supplier<DatabaseHelper> dst) {
+ if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) {
+ Log.e(TAG, "prepForMigration - target db is same as current: " + dbFile);
+ return false;
}
- databaseHelper.mHotseatRestoreTableExists = tableExists(
- databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
- databaseHelper.initIds();
- return databaseHelper;
+ final DatabaseHelper helper = src.get();
+ mOpenHelper = dst.get();
+ copyTable(helper.getReadableDatabase(), Favorites.TABLE_NAME,
+ mOpenHelper.getWritableDatabase(), targetTableName, mContext);
+ helper.close();
+ return true;
}
/**
@@ -281,38 +267,42 @@
}
/**
- * Migrates the DB if needed, and returns false if the migration failed
- * and DB needs to be cleared.
+ * Updates the current DB and copies all the existing data to the temp table
+ * @param dbFile name of the target db file name
*/
- public boolean migrateGridIfNeeded() {
- InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext);
- if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) {
- return true;
- }
- String targetDbName = new DeviceGridState(idp).getDbFile();
- if (TextUtils.equals(targetDbName, mOpenHelper.getDatabaseName())) {
- // DB is same, ignore
- return true;
- }
- DatabaseHelper oldHelper = mOpenHelper;
- mOpenHelper = (mContext instanceof SandboxContext) ? oldHelper
- : createDatabaseHelper(true /* forMigration */);
- try {
- return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, idp, mOpenHelper,
- oldHelper.getWritableDatabase());
- } finally {
- if (mOpenHelper != oldHelper) {
- oldHelper.close();
- }
- }
+ @WorkerThread
+ public boolean updateCurrentOpenHelper(String dbFile) {
+ createDbIfNotExists();
+ return prepForMigration(
+ dbFile,
+ Favorites.TMP_TABLE,
+ () -> mOpenHelper,
+ () -> DatabaseHelper.createDatabaseHelper(
+ mContext, true /* forMigration */));
}
/**
- * Returns the underlying model database
+ * Returns the current DatabaseHelper.
+ * Only for tests
*/
- public SQLiteDatabase getDb() {
+ @WorkerThread
+ public DatabaseHelper getDatabaseHelper() {
createDbIfNotExists();
- return mOpenHelper.getWritableDatabase();
+ return mOpenHelper;
+ }
+
+ /**
+ * Prepares the DB for preview by copying all existing data to preview table
+ */
+ @WorkerThread
+ public boolean prepareForPreview(String dbFile) {
+ createDbIfNotExists();
+ return prepForMigration(
+ dbFile,
+ Favorites.PREVIEW_TABLE_NAME,
+ () -> DatabaseHelper.createDatabaseHelper(
+ mContext, dbFile, true /* forMigration */),
+ () -> mOpenHelper);
}
private void onAddOrDeleteOp(SQLiteDatabase db) {
@@ -355,7 +345,8 @@
}
private void clearFlagEmptyDbCreated() {
- LauncherPrefs.get(mContext).removeSync(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()));
+ LauncherPrefs.getPrefs(mContext).edit()
+ .remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit();
}
/**
@@ -368,8 +359,9 @@
@WorkerThread
public synchronized void loadDefaultFavoritesIfNecessary() {
createDbIfNotExists();
+ SharedPreferences sp = LauncherPrefs.getPrefs(mContext);
- if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()))) {
+ if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
Log.d(TAG, "loading default workspace");
LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
@@ -487,27 +479,4 @@
return new DefaultLayoutParser(mContext, widgetHolder,
mOpenHelper, mContext.getResources(), defaultLayout);
}
-
- /**
- * Re-composite given key in respect to database. If the current db is
- * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
- * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
- * string will be "EMPTY_DATABASE_CREATED@minimal.db".
- */
- private ConstantItem<Boolean> getEmptyDbCreatedKey(String dbName) {
- if (mContext instanceof SandboxContext) {
- return LauncherPrefs.nonRestorableItem(EMPTY_DATABASE_CREATED,
- false /* default value */, false /* boot aware */);
- }
- String key = TextUtils.equals(dbName, LauncherFiles.LAUNCHER_DB)
- ? EMPTY_DATABASE_CREATED : EMPTY_DATABASE_CREATED + "@" + dbName;
- return LauncherPrefs.backedUpItem(key, false /* default value */, false /* boot aware */);
- }
-
- /**
- * Returns the serial number for the provided user
- */
- public long getSerialNumberForUser(UserHandle user) {
- return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
- }
}
diff --git a/src/com/android/launcher3/model/WidgetItem.java b/src/com/android/launcher3/model/WidgetItem.java
index 7198d54..c99b889 100644
--- a/src/com/android/launcher3/model/WidgetItem.java
+++ b/src/com/android/launcher3/model/WidgetItem.java
@@ -3,6 +3,7 @@
import static com.android.launcher3.Utilities.ATLEAST_S;
import android.annotation.SuppressLint;
+import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -25,13 +26,15 @@
public final ShortcutConfigActivityInfo activityInfo;
public final String label;
+ public final CharSequence description;
public final int spanX, spanY;
public WidgetItem(LauncherAppWidgetProviderInfo info,
- InvariantDeviceProfile idp, IconCache iconCache) {
+ InvariantDeviceProfile idp, IconCache iconCache, Context context) {
super(info.provider, info.getProfile());
label = iconCache.getTitleNoCache(info);
+ description = ATLEAST_S ? info.loadDescription(context) : null;
widgetInfo = info;
activityInfo = null;
@@ -43,6 +46,7 @@
super(info.getComponent(), info.getUser());
label = info.isPersistable() ? iconCache.getTitleNoCache(info) :
Utilities.trim(info.getLabel(pm));
+ description = null;
widgetInfo = null;
activityInfo = info;
spanX = spanY = 1;
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index bc492fd..8274789 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -241,8 +241,8 @@
deepShortcutCount,
popupDataProvider.getNotificationKeysForItem(item),
systemShortcuts);
- launcher.tryClearAccessibilityFocus(icon);
}
+ launcher.tryClearAccessibilityFocus(icon);
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
container.requestFocus();
return container;
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index c718dcc..48969fc 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -101,7 +101,7 @@
UserManagerState ums = new UserManagerState();
ums.init(UserCache.INSTANCE.get(context),
context.getSystemService(UserManager.class));
- LoaderCursor lc = new LoaderCursor(c, LauncherAppState.getInstance(context), ums);
+ LoaderCursor lc = new LoaderCursor(c, null, LauncherAppState.getInstance(context), ums);
IntSet deletedShortcuts = new IntSet();
while (lc.moveToNext()) {
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index a6e064a..ac72164 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -16,8 +16,6 @@
package com.android.launcher3.provider;
-import static android.os.Process.myUserHandle;
-
import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
@@ -49,8 +47,8 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.FileLog;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.DeviceGridState;
-import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -85,12 +83,12 @@
/**
* Tries to restore the backup DB if needed
*/
- public static void restoreIfNeeded(Context context, ModelDbController dbController) {
+ public static void restoreIfNeeded(Context context, DatabaseHelper helper) {
if (!isPending(context)) {
return;
}
- if (!performRestore(context, dbController)) {
- dbController.createEmptyDB();
+ if (!performRestore(context, helper)) {
+ helper.createEmptyDB(helper.getWritableDatabase());
}
// Obtain InvariantDeviceProfile first before setting pending to false, so
@@ -104,12 +102,12 @@
idp.reinitializeAfterRestore(context);
}
- private static boolean performRestore(Context context, ModelDbController controller) {
- SQLiteDatabase db = controller.getDb();
+ private static boolean performRestore(Context context, DatabaseHelper helper) {
+ SQLiteDatabase db = helper.getWritableDatabase();
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(context, controller, db, new BackupManager(context));
- task.restoreAppWidgetIdsIfExists(context, controller);
+ task.sanitizeDB(context, helper, db, new BackupManager(context));
+ task.restoreAppWidgetIdsIfExists(context, helper);
t.commit();
return true;
} catch (Exception e) {
@@ -131,10 +129,10 @@
* @return number of items deleted.
*/
@VisibleForTesting
- protected int sanitizeDB(Context context, ModelDbController controller, SQLiteDatabase db,
+ protected int sanitizeDB(Context context, DatabaseHelper helper, SQLiteDatabase db,
BackupManager backupManager) throws Exception {
// Primary user ids
- long myProfileId = controller.getSerialNumberForUser(myUserHandle());
+ long myProfileId = helper.getDefaultUserSerial();
long oldProfileId = getDefaultProfileId(db);
LongSparseArray<Long> oldManagedProfileIds = getManagedProfileIds(db, oldProfileId);
LongSparseArray<Long> profileMapping = new LongSparseArray<>(oldManagedProfileIds.size()
@@ -146,7 +144,7 @@
long oldManagedProfileId = oldManagedProfileIds.keyAt(i);
UserHandle user = getUserForAncestralSerialNumber(backupManager, oldManagedProfileId);
if (user != null) {
- long newManagedProfileId = controller.getSerialNumberForUser(user);
+ long newManagedProfileId = helper.getSerialNumberForUser(user);
profileMapping.put(oldManagedProfileId, newManagedProfileId);
}
}
@@ -215,7 +213,7 @@
}
// Override shortcuts
- maybeOverrideShortcuts(context, controller, db, myProfileId);
+ maybeOverrideShortcuts(context, helper, db, myProfileId);
return itemsDeleted;
}
@@ -323,11 +321,11 @@
.putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
}
- private void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) {
+ private void restoreAppWidgetIdsIfExists(Context context, DatabaseHelper helper) {
LauncherPrefs lp = LauncherPrefs.get(context);
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
- AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, controller,
+ AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, helper,
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
host);
@@ -345,7 +343,7 @@
APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString()));
}
- protected static void maybeOverrideShortcuts(Context context, ModelDbController controller,
+ protected static void maybeOverrideShortcuts(Context context, DatabaseHelper helper,
SQLiteDatabase db, long currentUser) {
Map<String, LauncherActivityInfo> activityOverrides = ApiWrapper.getActivityOverrides(
context);
@@ -369,7 +367,7 @@
if (override != null) {
ContentValues values = new ContentValues();
values.put(Favorites.PROFILE_ID,
- controller.getSerialNumberForUser(override.getUser()));
+ helper.getSerialNumberForUser(override.getUser()));
values.put(Favorites.INTENT, AppInfo.makeLaunchIntent(override).toUri(0));
db.update(Favorites.TABLE_NAME, values, String.format("%s=?", Favorites._ID),
new String[]{String.valueOf(c.getInt(idIndex))});
diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java
index 7c5ef4d..e509235 100644
--- a/src/com/android/launcher3/util/ContentWriter.java
+++ b/src/com/android/launcher3/util/ContentWriter.java
@@ -26,7 +26,7 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.GraphicsUtils;
-import com.android.launcher3.model.ModelDbController;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.pm.UserCache;
/**
@@ -106,7 +106,7 @@
public int commit() {
if (mCommitParams != null) {
- mCommitParams.mDbController.update(
+ mCommitParams.mDatabaseHelper.getWritableDatabase().update(
Favorites.TABLE_NAME, getValues(mContext),
mCommitParams.mWhere, mCommitParams.mSelectionArgs);
}
@@ -115,12 +115,12 @@
public static final class CommitParams {
- final ModelDbController mDbController;
+ final DatabaseHelper mDatabaseHelper;
final String mWhere;
final String[] mSelectionArgs;
- public CommitParams(ModelDbController controller, String where, String[] selectionArgs) {
- mDbController = controller;
+ public CommitParams(DatabaseHelper helper, String where, String[] selectionArgs) {
+ mDatabaseHelper = helper;
mWhere = where;
mSelectionArgs = selectionArgs;
}
diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java
index 5abf95c..04f83b9 100644
--- a/src/com/android/launcher3/util/LogConfig.java
+++ b/src/com/android/launcher3/util/LogConfig.java
@@ -55,4 +55,9 @@
* When turned on, we enable quick launch v2 related logging.
*/
public static final String QUICK_LAUNCH_V2 = "QuickLaunchV2";
+
+ /**
+ * When turned on, we enable Gms Play related logging.
+ */
+ public static final String GMS_PLAY = "GmsPlay";
}
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 99616f1..ec7ec0b 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -99,7 +99,7 @@
protected @Nullable OnCloseListener mOnCloseBeginListener;
protected List<OnCloseListener> mOnCloseListeners = new ArrayList<>();
- private final AnimatedFloat mSlideInViewScale =
+ protected final AnimatedFloat mSlideInViewScale =
new AnimatedFloat(this::onScaleProgressChanged, VIEW_NO_SCALE);
protected boolean mIsBackProgressing;
@Nullable private Drawable mContentBackground;
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index 7030f6d..6f74fd9 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -146,8 +146,7 @@
previewWidth = drawable.getIntrinsicWidth();
previewHeight = drawable.getIntrinsicHeight();
} else {
- Size widgetSize = WidgetSizes.getWidgetPaddedSizePx(mContext, info.provider, dp, spanX,
- spanY);
+ Size widgetSize = WidgetSizes.getWidgetSizePx(dp, spanX, spanY);
previewWidth = widgetSize.getWidth();
previewHeight = widgetSize.getHeight();
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index bba1016..10aef9a 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -2,7 +2,6 @@
import static com.android.launcher3.Utilities.ATLEAST_S;
-import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -105,44 +104,35 @@
int spanX = 0;
int spanY = 0;
- Rect widgetPadding = new Rect();
- Rect localPadding = new Rect();
- AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding);
Point cellSize = new Point();
for (DeviceProfile dp : idp.supportedProfiles) {
dp.getCellSize(cellSize);
- // We want to account for the extra amount of padding that we are adding to the widget
- // to ensure that it gets the full amount of space that it has requested.
- // If grids supports insetting widgets, we do not account for widget padding.
- if (dp.shouldInsetWidgets()) {
- localPadding.setEmpty();
- } else {
- localPadding.set(widgetPadding);
- }
+ Rect widgetPadding = dp.widgetPadding;
+
minSpanX = Math.max(minSpanX,
- getSpanX(localPadding, minResizeWidth, dp.cellLayoutBorderSpacePx.x,
+ getSpanX(widgetPadding, minResizeWidth, dp.cellLayoutBorderSpacePx.x,
cellSize.x));
minSpanY = Math.max(minSpanY,
- getSpanY(localPadding, minResizeHeight, dp.cellLayoutBorderSpacePx.y,
+ getSpanY(widgetPadding, minResizeHeight, dp.cellLayoutBorderSpacePx.y,
cellSize.y));
if (ATLEAST_S) {
if (maxResizeWidth > 0) {
- maxSpanX = Math.min(maxSpanX, getSpanX(localPadding, maxResizeWidth,
+ maxSpanX = Math.min(maxSpanX, getSpanX(widgetPadding, maxResizeWidth,
dp.cellLayoutBorderSpacePx.x, cellSize.x));
}
if (maxResizeHeight > 0) {
- maxSpanY = Math.min(maxSpanY, getSpanY(localPadding, maxResizeHeight,
+ maxSpanY = Math.min(maxSpanY, getSpanY(widgetPadding, maxResizeHeight,
dp.cellLayoutBorderSpacePx.y, cellSize.y));
}
}
spanX = Math.max(spanX,
- getSpanX(localPadding, minWidth, dp.cellLayoutBorderSpacePx.x,
+ getSpanX(widgetPadding, minWidth, dp.cellLayoutBorderSpacePx.x,
cellSize.x));
spanY = Math.max(spanY,
- getSpanY(localPadding, minHeight, dp.cellLayoutBorderSpacePx.y,
+ getSpanY(widgetPadding, minHeight, dp.cellLayoutBorderSpacePx.y,
cellSize.y));
}
@@ -184,15 +174,22 @@
}
private int getSpanX(Rect widgetPadding, int widgetWidth, int cellSpacing, float cellWidth) {
- return Math.max(1, (int) Math.ceil(
- (widgetWidth + widgetPadding.left + widgetPadding.right + cellSpacing) / (cellWidth
- + cellSpacing)));
+ return getSpan(widgetPadding.left + widgetPadding.right,
+ widgetWidth, cellSpacing, cellWidth);
}
private int getSpanY(Rect widgetPadding, int widgetHeight, int cellSpacing, float cellHeight) {
+ return getSpan(widgetPadding.top + widgetPadding.bottom, widgetHeight,
+ cellSpacing, cellHeight);
+ }
+
+ /**
+ * Solving the equation:
+ * n * cellSize + (n - 1) * cellSpacing - widgetPadding = widgetSize
+ */
+ private int getSpan(int widgetPadding, int widgetSize, int cellSpacing, float cellSize) {
return Math.max(1, (int) Math.ceil(
- (widgetHeight + widgetPadding.top + widgetPadding.bottom + cellSpacing) / (
- cellHeight + cellSpacing)));
+ (widgetSize + widgetPadding + cellSpacing) / (cellSize + cellSpacing)));
}
public String getLabel(PackageManager packageManager) {
diff --git a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
index 3389fb1..f46b214 100644
--- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
@@ -25,7 +25,6 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Reorderable;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.util.MultiTranslateDelegate;
@@ -48,13 +47,13 @@
private float mScaleForReorderBounce = 1f;
- private final Rect mTempRect = new Rect();
-
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mChildrenFocused;
protected final ActivityContext mActivity;
+ private boolean mDisableSetPadding = false;
+
public NavigableAppWidgetHostView(Context context) {
super(context);
mActivity = ActivityContext.lookupContext(context);
@@ -147,6 +146,22 @@
}
@Override
+ public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) {
+ // Prevent default padding being set on the view based on provider info. Launcher manages
+ // its own widget spacing
+ mDisableSetPadding = true;
+ super.setAppWidget(appWidgetId, info);
+ mDisableSetPadding = false;
+ }
+
+ @Override
+ public void setPadding(int left, int top, int right, int bottom) {
+ if (!mDisableSetPadding) {
+ super.setPadding(left, top, right, bottom);
+ }
+ }
+
+ @Override
public boolean dispatchUnhandledMove(View focused, int direction) {
return mChildrenFocused;
}
@@ -195,26 +210,6 @@
public void getWorkspaceVisualDragBounds(Rect bounds) {
int width = (int) (getMeasuredWidth() * mScaleToFit);
int height = (int) (getMeasuredHeight() * mScaleToFit);
-
- getWidgetInset(mActivity.getDeviceProfile(), mTempRect);
- bounds.set(mTempRect.left, mTempRect.top, width - mTempRect.right,
- height - mTempRect.bottom);
- }
-
- /**
- * Widgets have padding added by the system. We may choose to inset this padding if the grid
- * supports it.
- */
- public void getWidgetInset(DeviceProfile grid, Rect out) {
- if (!grid.shouldInsetWidgets()) {
- out.setEmpty();
- return;
- }
- AppWidgetProviderInfo info = getAppWidgetInfo();
- if (info == null) {
- out.set(grid.inv.defaultWidgetPadding);
- } else {
- AppWidgetHostView.getDefaultPaddingForWidget(getContext(), info.provider, out);
- }
+ bounds.set(0, 0, width, height);
}
}
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 410a555..f269434 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -16,6 +16,8 @@
package com.android.launcher3.widget;
+import static com.android.launcher3.widget.util.WidgetSizes.getWidgetSizePx;
+
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -43,7 +45,6 @@
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.RoundDrawableWrapper;
import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener;
-import com.android.launcher3.widget.util.WidgetSizes;
/**
* Extension of {@link DragPreviewProvider} with logic specific to pending widgets/shortcuts
@@ -121,13 +122,8 @@
mAppWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1,
((PendingAddWidgetInfo) mAddInfo).info);
DeviceProfile deviceProfile = launcher.getDeviceProfile();
- Rect padding = new Rect();
- mAppWidgetHostViewPreview.getWidgetInset(deviceProfile, padding);
- mAppWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
- padding.bottom);
mAppWidgetHostViewPreview.updateAppWidget(/* remoteViews= */ mRemoteViewsPreview);
- Size widgetSizes = WidgetSizes.getWidgetPaddedSizePx(launcher,
- mAddInfo.componentName, deviceProfile, mAddInfo.spanX, mAddInfo.spanY);
+ Size widgetSizes = getWidgetSizePx(deviceProfile, mAddInfo.spanX, mAddInfo.spanY);
mAppWidgetHostViewPreview.measure(
MeasureSpec.makeMeasureSpec(widgetSizes.getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(widgetSizes.getHeight(), MeasureSpec.EXACTLY));
@@ -161,8 +157,15 @@
previewBounds.right -= padding;
}
if (mAppWidgetHostViewPreview != null) {
- previewWidth = mAppWidgetHostViewPreview.getMeasuredWidth();
- previewHeight = mAppWidgetHostViewPreview.getMeasuredHeight();
+ float previewScale = mAppWidgetHostViewPreview.getScaleX();
+ int widgetWidth = mAppWidgetHostViewPreview.getMeasuredWidth();
+ int widgetHeight = mAppWidgetHostViewPreview.getMeasuredHeight();
+ previewWidth = Math.round(widgetWidth * previewScale);
+ previewHeight = Math.round(widgetHeight * previewScale);
+
+ previewBounds.offset(
+ Math.round(widgetWidth * (previewScale - 1) / 2),
+ Math.round(widgetHeight * (previewScale - 1) / 2));
} else {
previewWidth = preview.getIntrinsicWidth();
previewHeight = preview.getIntrinsicHeight();
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 80bc1a7..c30342a 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -16,18 +16,15 @@
package com.android.launcher3.widget;
-import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
-import static com.android.launcher3.Utilities.ATLEAST_S;
-import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_WIDGET_CENTERING;
+import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.fromProviderInfo;
+import static com.android.launcher3.widget.util.WidgetSizes.getWidgetItemSizePx;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Process;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Size;
@@ -47,7 +44,6 @@
import androidx.annotation.Nullable;
import com.android.launcher3.CheckLongPressHelper;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -55,7 +51,6 @@
import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.widget.util.WidgetSizes;
import java.util.function.Consumer;
@@ -75,40 +70,8 @@
private static final int FADE_IN_DURATION_MS = 90;
- /** Widget cell width is calculated by multiplying this factor to grid cell width. */
- private static final float WIDTH_SCALE = 3f;
-
- /** Widget preview width is calculated by multiplying this factor to the widget cell width. */
- private static final float PREVIEW_SCALE = 0.8f;
-
/**
- * The maximum dimension that can be used as the size in
- * {@link android.view.View.MeasureSpec#makeMeasureSpec(int, int)}.
- *
- * <p>This is equal to (1 << MeasureSpec.MODE_SHIFT) - 1.
- */
- private static final int MAX_MEASURE_SPEC_DIMENSION = (1 << 30) - 1;
-
- /**
- * The target preview width, in pixels, of a widget or a shortcut.
- *
- * <p>The actual preview width may be smaller than or equal to this value subjected to scaling.
- */
- protected int mTargetPreviewWidth;
-
- /**
- * The target preview height, in pixels, of a widget or a shortcut.
- *
- * <p>The actual preview height may be smaller than or equal to this value subjected to scaling.
- */
- protected int mTargetPreviewHeight;
-
- protected int mPresetPreviewSize;
-
- private int mCellSize;
-
- /**
- * The scale of the preview container.
+ * The requested scale of the preview container. It can be lower than this as well.
*/
private float mPreviewContainerScale = 1f;
@@ -119,7 +82,8 @@
private TextView mWidgetDims;
private TextView mWidgetDescription;
- protected WidgetItem mItem;
+ private WidgetItem mItem;
+ private Size mWidgetSize;
private final DatabaseWidgetPreviewLoader mWidgetPreviewLoader;
@@ -150,18 +114,11 @@
mWidgetPreviewLoader = new DatabaseWidgetPreviewLoader(context);
mLongPressHelper = new CheckLongPressHelper(this);
mLongPressHelper.setLongPressTimeoutFactor(1);
+ mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context);
+ mWidgetSize = new Size(0, 0);
- setContainerWidth();
- setWillNotDraw(false);
setClipToPadding(false);
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
- mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context);
- }
-
- private void setContainerWidth() {
- mCellSize = (int) (mActivity.getDeviceProfile().allAppsIconSizePx * WIDTH_SCALE);
- mPresetPreviewSize = (int) (mCellSize * PREVIEW_SCALE);
- mTargetPreviewWidth = mTargetPreviewHeight = mPresetPreviewSize;
}
@Override
@@ -206,7 +163,6 @@
mWidgetDims.setText(null);
mWidgetDescription.setText(null);
mWidgetDescription.setVisibility(GONE);
- mTargetPreviewWidth = mTargetPreviewHeight = mPresetPreviewSize;
if (mActiveRequest != null) {
mActiveRequest.cancel();
@@ -218,7 +174,9 @@
}
mAppWidgetHostViewPreview = null;
mAppWidgetHostViewScale = 1f;
+ mPreviewContainerScale = 1f;
mItem = null;
+ mWidgetSize = new Size(0, 0);
}
public void setSourceContainer(int sourceContainer) {
@@ -248,17 +206,12 @@
*/
public void applyFromCellItem(WidgetItem item, float previewScale,
@NonNull Consumer<Bitmap> callback, @Nullable Bitmap cachedPreview) {
- // setPreviewSize
- DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- Size widgetSize = WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile, item);
- mTargetPreviewWidth = widgetSize.getWidth();
- mTargetPreviewHeight = widgetSize.getHeight();
mPreviewContainerScale = previewScale;
- applyPreviewOnAppWidgetHostView(item);
-
Context context = getContext();
mItem = item;
+ mWidgetSize = getWidgetItemSizePx(getContext(), mActivity.getDeviceProfile(), mItem);
+
mWidgetName.setText(mItem.label);
mWidgetName.setContentDescription(
context.getString(R.string.widget_preview_context_description, mItem.label));
@@ -266,14 +219,11 @@
mItem.spanX, mItem.spanY));
mWidgetDims.setContentDescription(context.getString(
R.string.widget_accessible_dims_format, mItem.spanX, mItem.spanY));
- if (ATLEAST_S && mItem.widgetInfo != null) {
- CharSequence description = mItem.widgetInfo.loadDescription(context);
- if (description != null && description.length() > 0) {
- mWidgetDescription.setText(description);
- mWidgetDescription.setVisibility(VISIBLE);
- } else {
- mWidgetDescription.setVisibility(GONE);
- }
+ if (!TextUtils.isEmpty(mItem.description)) {
+ mWidgetDescription.setText(mItem.description);
+ mWidgetDescription.setVisibility(VISIBLE);
+ } else {
+ mWidgetDescription.setVisibility(GONE);
}
if (item.activityInfo != null) {
@@ -282,68 +232,31 @@
setTag(new PendingAddWidgetInfo(item.widgetInfo, mSourceContainer));
}
- ensurePreviewWithCallback(callback, cachedPreview);
- }
-
- private static class ScaledAppWidgetHostView extends LauncherAppWidgetHostView {
- private boolean mKeepOrigForDragging = true;
-
- ScaledAppWidgetHostView(Context context) {
- super(context);
- }
-
- /**
- * Set if the view will keep its original scale when dragged
- * @param isKeepOrig True if keep original scale when dragged, false otherwise
- */
- public void setKeepOrigForDragging(boolean isKeepOrig) {
- mKeepOrigForDragging = isKeepOrig;
- }
-
- /**
- * @return True if the view is set to preserve original scale when dragged, false otherwise
- */
- public boolean isKeepOrigForDragging() {
- return mKeepOrigForDragging;
- }
-
- @Override
- public void startDrag() {
- super.startDrag();
- if (!isKeepOrigForDragging()) {
- // restore to original scale when being dragged, if set to do so
- setScaleToFit(1.0f);
- }
- // When the drag start, translations need to be set to zero to center the view
- getTranslateDelegate().setTranslation(INDEX_WIDGET_CENTERING, 0f, 0f);
- }
- }
-
- private void applyPreviewOnAppWidgetHostView(WidgetItem item) {
if (mRemoteViewsPreview != null) {
- mAppWidgetHostViewPreview = createAppWidgetHostView(getContext());
+ mAppWidgetHostViewPreview = createAppWidgetHostView(context);
setAppWidgetHostViewPreview(mAppWidgetHostViewPreview, item.widgetInfo,
mRemoteViewsPreview);
- return;
+ } else if (item.hasPreviewLayout()) {
+ // If the context is a Launcher activity, DragView will show mAppWidgetHostViewPreview
+ // as a preview during drag & drop. And thus, we should use LauncherAppWidgetHostView,
+ // which supports applying local color extraction during drag & drop.
+ mAppWidgetHostViewPreview = isLauncherContext(context)
+ ? new LauncherAppWidgetHostView(context)
+ : createAppWidgetHostView(context);
+ LauncherAppWidgetProviderInfo providerInfo =
+ fromProviderInfo(context, item.widgetInfo.clone());
+ // A hack to force the initial layout to be the preview layout since there is no API for
+ // rendering a preview layout for work profile apps yet. For non-work profile layout, a
+ // proper solution is to use RemoteViews(PackageName, LayoutId).
+ providerInfo.initialLayout = item.widgetInfo.previewLayout;
+ setAppWidgetHostViewPreview(mAppWidgetHostViewPreview, providerInfo, null);
+ } else if (cachedPreview != null) {
+ applyPreview(cachedPreview);
+ } else {
+ if (mActiveRequest == null) {
+ mActiveRequest = mWidgetPreviewLoader.loadPreview(mItem, mWidgetSize, callback);
+ }
}
-
- if (!item.hasPreviewLayout()) return;
-
- Context context = getContext();
- // If the context is a Launcher activity, DragView will show mAppWidgetHostViewPreview as
- // a preview during drag & drop. And thus, we should use LauncherAppWidgetHostView, which
- // supports applying local color extraction during drag & drop.
- mAppWidgetHostViewPreview = isLauncherContext(context)
- ? new ScaledAppWidgetHostView(context)
- : createAppWidgetHostView(context);
- LauncherAppWidgetProviderInfo launcherAppWidgetProviderInfo =
- LauncherAppWidgetProviderInfo.fromProviderInfo(context, item.widgetInfo.clone());
- // A hack to force the initial layout to be the preview layout since there is no API for
- // rendering a preview layout for work profile apps yet. For non-work profile layout, a
- // proper solution is to use RemoteViews(PackageName, LayoutId).
- launcherAppWidgetProviderInfo.initialLayout = item.widgetInfo.previewLayout;
- setAppWidgetHostViewPreview(mAppWidgetHostViewPreview,
- launcherAppWidgetProviderInfo, /* remoteViews= */ null);
}
private void setAppWidgetHostViewPreview(
@@ -353,6 +266,43 @@
appWidgetHostViewPreview.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
appWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1, providerInfo);
appWidgetHostViewPreview.updateAppWidget(remoteViews);
+ appWidgetHostViewPreview.setClipToPadding(false);
+ appWidgetHostViewPreview.setClipChildren(false);
+
+ FrameLayout.LayoutParams widgetHostLP = new FrameLayout.LayoutParams(
+ mWidgetSize.getWidth(), mWidgetSize.getHeight(), Gravity.CENTER);
+ mWidgetImageContainer.addView(appWidgetHostViewPreview, /* index= */ 0, widgetHostLP);
+ mWidgetImage.setVisibility(View.GONE);
+ applyPreview(null);
+
+ appWidgetHostViewPreview.addOnLayoutChangeListener(
+ (v, l, t, r, b, ol, ot, or, ob) ->
+ updateAppWidgetHostScale(appWidgetHostViewPreview));
+ }
+
+ private void updateAppWidgetHostScale(NavigableAppWidgetHostView view) {
+ // Scale the content such that all of the content is visible
+ int contentWidth = view.getWidth();
+ int contentHeight = view.getHeight();
+
+ if (view.getChildCount() == 1) {
+ View content = view.getChildAt(0);
+ // Take the content width based on the edge furthest from the center, so that when
+ // scaling the hostView, the farthest edge is still visible.
+ contentWidth = 2 * Math.max(contentWidth / 2 - content.getLeft(),
+ content.getRight() - contentWidth / 2);
+ contentHeight = 2 * Math.max(contentHeight / 2 - content.getTop(),
+ content.getBottom() - contentHeight / 2);
+ }
+
+ if (contentWidth <= 0 || contentHeight <= 0) {
+ mAppWidgetHostViewScale = 1;
+ } else {
+ float pWidth = mWidgetImageContainer.getWidth();
+ float pHeight = mWidgetImageContainer.getHeight();
+ mAppWidgetHostViewScale = Math.min(pWidth / contentWidth, pHeight / contentHeight);
+ }
+ view.setScaleToFit(mAppWidgetHostViewScale);
}
public WidgetImageView getWidgetView() {
@@ -372,17 +322,6 @@
if (bitmap != null) {
Drawable drawable = new RoundDrawableWrapper(
new FastBitmapDrawable(bitmap), mEnforcedCornerRadius);
-
- // Scale down the preview size if it's wider than the cell.
- float scale = 1f;
- if (mTargetPreviewWidth > 0) {
- float maxWidth = mTargetPreviewWidth;
- float previewWidth = drawable.getIntrinsicWidth() * mPreviewContainerScale;
- scale = Math.min(maxWidth / previewWidth, 1);
- }
- setContainerSize(
- Math.round(drawable.getIntrinsicWidth() * scale * mPreviewContainerScale),
- Math.round(drawable.getIntrinsicHeight() * scale * mPreviewContainerScale));
mWidgetImage.setDrawable(drawable);
mWidgetImage.setVisibility(View.VISIBLE);
if (mAppWidgetHostViewPreview != null) {
@@ -415,76 +354,6 @@
}
}
- private void setContainerSize(int width, int height) {
- LayoutParams layoutParams = (LayoutParams) mWidgetImageContainer.getLayoutParams();
- layoutParams.width = width;
- layoutParams.height = height;
- mWidgetImageContainer.setLayoutParams(layoutParams);
- }
-
- /**
- * Ensures that the preview is already loaded or being loaded. If the preview is not loaded,
- * it applies the provided cachedPreview. If that is null, it starts a loader and notifies the
- * callback on successful load.
- */
- private void ensurePreviewWithCallback(Consumer<Bitmap> callback,
- @Nullable Bitmap cachedPreview) {
- if (mAppWidgetHostViewPreview != null) {
- int containerWidth = (int) (mTargetPreviewWidth * mPreviewContainerScale);
- int containerHeight = (int) (mTargetPreviewHeight * mPreviewContainerScale);
- setContainerSize(containerWidth, containerHeight);
- boolean shouldMeasureAndScale = false;
- if (mAppWidgetHostViewPreview.getChildCount() == 1) {
- View widgetContent = mAppWidgetHostViewPreview.getChildAt(0);
- ViewGroup.LayoutParams layoutParams = widgetContent.getLayoutParams();
- // We only scale preview if both the width & height of the outermost view group are
- // not set to MATCH_PARENT.
- shouldMeasureAndScale =
- layoutParams.width != MATCH_PARENT && layoutParams.height != MATCH_PARENT;
- if (shouldMeasureAndScale) {
- setNoClip(mWidgetImageContainer);
- setNoClip(mAppWidgetHostViewPreview);
- mAppWidgetHostViewScale = measureAndComputeWidgetPreviewScale();
- }
- }
-
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
- mTargetPreviewWidth, mTargetPreviewHeight, Gravity.FILL);
- mAppWidgetHostViewPreview.setLayoutParams(params);
-
- if (!shouldMeasureAndScale
- && mAppWidgetHostViewPreview instanceof ScaledAppWidgetHostView) {
- // If the view is not measured & scaled, at least one side will match the grid size,
- // so it should be safe to restore the original scale once it is dragged.
- ScaledAppWidgetHostView tempView =
- (ScaledAppWidgetHostView) mAppWidgetHostViewPreview;
- tempView.setKeepOrigForDragging(false);
- tempView.setScaleToFit(mPreviewContainerScale);
- } else if (!shouldMeasureAndScale) {
- mAppWidgetHostViewPreview.setScaleToFit(mPreviewContainerScale);
- } else {
- mAppWidgetHostViewPreview.setScaleToFit(mAppWidgetHostViewScale);
- }
- mAppWidgetHostViewPreview.getTranslateDelegate().setTranslation(
- INDEX_WIDGET_CENTERING,
- -(params.width - (params.width * mPreviewContainerScale)) / 2.0f,
- -(params.height - (params.height * mPreviewContainerScale)) / 2.0f);
- mWidgetImageContainer.addView(mAppWidgetHostViewPreview, /* index= */ 0);
- mWidgetImage.setVisibility(View.GONE);
- applyPreview(null);
- return;
- }
- if (cachedPreview != null) {
- applyPreview(cachedPreview);
- return;
- }
- if (mActiveRequest != null) {
- return;
- }
- mActiveRequest = mWidgetPreviewLoader.loadPreview(
- mItem, new Size(mTargetPreviewWidth, mTargetPreviewHeight), callback);
- }
-
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
@@ -522,61 +391,20 @@
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
}
- private static void setNoClip(ViewGroup view) {
- view.setClipChildren(false);
- view.setClipToPadding(false);
- }
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ ViewGroup.LayoutParams containerLp = mWidgetImageContainer.getLayoutParams();
- private float measureAndComputeWidgetPreviewScale() {
- if (mAppWidgetHostViewPreview.getChildCount() != 1) {
- return 1f;
+ mAppWidgetHostViewScale = mPreviewContainerScale;
+ int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
+ containerLp.width = Math.round(mWidgetSize.getWidth() * mAppWidgetHostViewScale);
+ if (containerLp.width > maxWidth) {
+ containerLp.width = maxWidth;
+ mAppWidgetHostViewScale = (float) containerLp.width / mWidgetSize.getWidth();
}
+ containerLp.height = Math.round(mWidgetSize.getHeight() * mAppWidgetHostViewScale);
+ // No need to call mWidgetImageContainer.setLayoutParams as we are in measure pass
- // Measure the largest possible width & height that the app widget wants to display.
- mAppWidgetHostViewPreview.measure(
- makeMeasureSpec(MAX_MEASURE_SPEC_DIMENSION, MeasureSpec.UNSPECIFIED),
- makeMeasureSpec(MAX_MEASURE_SPEC_DIMENSION, MeasureSpec.UNSPECIFIED));
- if (mRemoteViewsPreview != null) {
- // If RemoteViews contains multiple sizes, the best fit sized RemoteViews will be
- // selected in onLayout. To work out the right measurement, let's layout and then
- // measure again.
- mAppWidgetHostViewPreview.layout(
- /* left= */ 0,
- /* top= */ 0,
- /* right= */ mTargetPreviewWidth,
- /* bottom= */ mTargetPreviewHeight);
- mAppWidgetHostViewPreview.measure(
- makeMeasureSpec(mTargetPreviewWidth, MeasureSpec.UNSPECIFIED),
- makeMeasureSpec(mTargetPreviewHeight, MeasureSpec.UNSPECIFIED));
-
- }
- View widgetContent = mAppWidgetHostViewPreview.getChildAt(0);
- int appWidgetContentWidth = widgetContent.getMeasuredWidth();
- int appWidgetContentHeight = widgetContent.getMeasuredHeight();
- if (appWidgetContentWidth == 0 || appWidgetContentHeight == 0) {
- return 1f;
- }
-
- // If the width / height of the widget content is set to wrap content, overrides the width /
- // height with the measured dimension. This avoids incorrect measurement after scaling.
- FrameLayout.LayoutParams layoutParam =
- (FrameLayout.LayoutParams) widgetContent.getLayoutParams();
- if (layoutParam.width == WRAP_CONTENT) {
- layoutParam.width = widgetContent.getMeasuredWidth();
- }
- if (layoutParam.height == WRAP_CONTENT) {
- layoutParam.height = widgetContent.getMeasuredHeight();
- }
- widgetContent.setLayoutParams(layoutParam);
-
- int horizontalPadding = mAppWidgetHostViewPreview.getPaddingStart()
- + mAppWidgetHostViewPreview.getPaddingEnd();
- int verticalPadding = mAppWidgetHostViewPreview.getPaddingTop()
- + mAppWidgetHostViewPreview.getPaddingBottom();
- return Math.min(
- (mTargetPreviewWidth - horizontalPadding) * mPreviewContainerScale
- / appWidgetContentWidth,
- (mTargetPreviewHeight - verticalPadding) * mPreviewContainerScale
- / appWidgetContentHeight);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 23cdae9..846dafd 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -252,8 +252,11 @@
super.setInsets(insets);
int bottomPadding = Math.max(insets.bottom, mNavBarScrimHeight);
- mContent.setPadding(mContent.getPaddingStart(),
- mContent.getPaddingTop(), mContent.getPaddingEnd(),
+ View widgetsTable = findViewById(R.id.widgets_table);
+ widgetsTable.setPadding(
+ widgetsTable.getPaddingLeft(),
+ widgetsTable.getPaddingTop(),
+ widgetsTable.getPaddingRight(),
bottomPadding);
if (bottomPadding > 0) {
setupNavBarColor();
diff --git a/src/com/android/launcher3/widget/util/WidgetSizes.java b/src/com/android/launcher3/widget/util/WidgetSizes.java
index 601c1b5..7049509 100644
--- a/src/com/android/launcher3/widget/util/WidgetSizes.java
+++ b/src/com/android/launcher3/widget/util/WidgetSizes.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.widget.util;
-import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
-
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
@@ -28,8 +26,6 @@
import android.util.Size;
import android.util.SizeF;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
@@ -43,24 +39,13 @@
/**
* Returns the list of all possible sizes, in dp, for a widget of given spans on this device.
- *
- * <p>The returned sizes already take into account the system padding, and whether it is applied
- * or not in that specific configuration.
*/
- public static ArrayList<SizeF> getWidgetPaddedSizes(Context context, ComponentName provider,
- int spanX, int spanY) {
- Rect padding = getDefaultPaddingForWidget(context, provider, /* padding= */ null);
-
+ public static ArrayList<SizeF> getWidgetSizesDp(Context context, int spanX, int spanY) {
ArrayList<SizeF> sizes = new ArrayList<>(2);
final float density = context.getResources().getDisplayMetrics().density;
- final Point cellSize = new Point();
for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) {
- Size widgetSizePx = getWidgetSizePx(profile, spanX, spanY, cellSize);
- if (!profile.shouldInsetWidgets()) {
- widgetSizePx = new Size(widgetSizePx.getWidth() - padding.left - padding.right,
- widgetSizePx.getHeight() - padding.top - padding.bottom);
- }
+ Size widgetSizePx = getWidgetSizePx(profile, spanX, spanY);
sizes.add(new SizeF(widgetSizePx.getWidth() / density,
widgetSizePx.getHeight() / density));
}
@@ -69,21 +54,15 @@
/** Returns the size, in pixels, a widget of given spans & {@code profile}. */
public static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY) {
- return getWidgetSizePx(profile, spanX, spanY, /* recycledCellSize= */ null);
- }
+ final int hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacePx.x;
+ final int vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacePx.y;
- /**
- * Returns the size, in pixels and removing padding, a widget of given spans & {@code profile}.
- */
- public static Size getWidgetPaddedSizePx(Context context, ComponentName component,
- DeviceProfile profile, int spanX, int spanY) {
- Size size = getWidgetSizePx(profile, spanX, spanY);
- if (profile.shouldInsetWidgets()) {
- return size;
- }
- Rect padding = getDefaultPaddingForWidget(context, component, /* padding= */ null);
- return new Size(size.getWidth() - padding.left - padding.right,
- size.getHeight() - padding.top - padding.bottom);
+ Point cellSize = profile.getCellSize();
+ Rect padding = profile.widgetPadding;
+
+ return new Size(
+ (spanX * cellSize.x) + hBorderSpacing - padding.left - padding.right,
+ (spanY * cellSize.y) + vBorderSpacing - padding.top - padding.bottom);
}
/**
@@ -92,8 +71,7 @@
* <p>This size is used by the widget picker. It should NEVER be shared with app widgets.
*
* <p>For sizes shared with app widgets, please refer to
- * {@link #getWidgetPaddedSizes(Context, ComponentName, int, int)} &
- * {@link #getWidgetPaddedSizePx(Context, ComponentName, DeviceProfile, int, int)}.
+ * {@link #getWidgetSizesDp(Context, int, int)} &
*/
public static Size getWidgetItemSizePx(Context context, DeviceProfile profile,
WidgetItem widgetItem) {
@@ -102,27 +80,7 @@
.getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
return new Size(dimension, dimension);
}
- Size widgetItemSize = getWidgetSizePx(profile, widgetItem.spanX,
- widgetItem.spanY, /* recycledCellSize= */ null);
- if (profile.shouldInsetWidgets()) {
- Rect inset = new Rect();
- AppWidgetHostView.getDefaultPaddingForWidget(context, widgetItem.componentName, inset);
- return new Size(widgetItemSize.getWidth() + inset.left + inset.right,
- widgetItemSize.getHeight() + inset.top + inset.bottom);
- }
- return widgetItemSize;
- }
-
- private static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY,
- @Nullable Point recycledCellSize) {
- final int hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacePx.x;
- final int vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacePx.y;
- if (recycledCellSize == null) {
- recycledCellSize = new Point();
- }
- profile.getCellSize(recycledCellSize);
- return new Size(((spanX * recycledCellSize.x) + hBorderSpacing),
- ((spanY * recycledCellSize.y) + vBorderSpacing));
+ return getWidgetSizePx(profile, widgetItem.spanX, widgetItem.spanY);
}
/**
@@ -154,7 +112,7 @@
*/
public static Bundle getWidgetSizeOptions(Context context, ComponentName provider, int spanX,
int spanY) {
- ArrayList<SizeF> paddedSizes = getWidgetPaddedSizes(context, provider, spanX, spanY);
+ ArrayList<SizeF> paddedSizes = getWidgetSizesDp(context, spanX, spanY);
Rect rect = getMinMaxSizes(paddedSizes);
Bundle options = new Bundle();
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 1b743e8..2f16065 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -129,7 +129,7 @@
LauncherAppWidgetProviderInfo.fromProviderInfo(context, widgetInfo);
widgetsAndShortcuts.add(new WidgetItem(
- launcherWidgetInfo, idp, app.getIconCache()));
+ launcherWidgetInfo, idp, app.getIconCache(), app.getContext()));
updatedItems.add(launcherWidgetInfo);
}
@@ -200,7 +200,8 @@
app.getContext().getPackageManager()));
} else {
items.set(i, new WidgetItem(item.widgetInfo,
- app.getInvariantDeviceProfile(), app.getIconCache()));
+ app.getInvariantDeviceProfile(), app.getIconCache(),
+ app.getContext()));
}
}
}
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index b472cdb..601b07e 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -90,6 +90,7 @@
public static final String REQUEST_DISABLE_TRANSIENT_TASKBAR = "disable-transient-taskbar";
public static final String REQUEST_UNSTASH_TASKBAR_IF_STASHED = "unstash-taskbar-if-stashed";
public static final String REQUEST_STASHED_TASKBAR_HEIGHT = "stashed-taskbar-height";
+ public static final String REQUEST_STASHED_TASKBAR_SCALE = "taskbar-stash-handle-scale";
public static final String REQUEST_RECREATE_TASKBAR = "recreate-taskbar";
public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags";
public static final String REQUEST_APPS_LIST_SCROLL_Y = "apps-list-scroll-y";
diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
index cea95e5..0a1a9ba 100644
--- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
+++ b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
@@ -39,7 +39,6 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
-import com.android.launcher3.pm.UserCache;
import org.junit.Before;
import org.junit.Test;
@@ -223,9 +222,7 @@
private class MyDatabaseHelper extends DatabaseHelper {
MyDatabaseHelper() {
- super(mContext, DB_FILE,
- UserCache.INSTANCE.get(mContext)::getSerialNumberForUser,
- () -> { });
+ super(mContext, DB_FILE, false);
}
@Override
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 63dbaa7..f24f0da 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.model
-import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.database.Cursor
@@ -24,7 +23,6 @@
import android.os.Process
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
@@ -33,7 +31,10 @@
import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
import com.android.launcher3.pm.UserCache
import com.android.launcher3.provider.LauncherDbUtils
+import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.*
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -42,12 +43,11 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class GridSizeMigrationUtilTest {
-
+ private lateinit var modelHelper: LauncherModelHelper
private lateinit var context: Context
+ private lateinit var db: SQLiteDatabase
private lateinit var validPackages: Set<String>
private lateinit var idp: InvariantDeviceProfile
- private lateinit var dbHelper: DatabaseHelper
- private lateinit var db: SQLiteDatabase
private val testPackage1 = "com.android.launcher3.validpackage1"
private val testPackage2 = "com.android.launcher3.validpackage2"
private val testPackage3 = "com.android.launcher3.validpackage3"
@@ -61,17 +61,13 @@
@Before
fun setUp() {
- context = InstrumentationRegistry.getInstrumentation().targetContext
- dbHelper =
- DatabaseHelper(
- context,
- null,
- UserCache.INSTANCE.get(context)::getSerialNumberForUser
- ) {}
- db = dbHelper.writableDatabase
+ modelHelper = LauncherModelHelper()
+ context = modelHelper.sandboxContext
+ db = modelHelper.provider.db
validPackages =
setOf(
+ TEST_PACKAGE,
testPackage1,
testPackage2,
testPackage3,
@@ -90,6 +86,11 @@
addTableToDb(db, userSerial, false, TMP_TABLE)
}
+ @After
+ fun tearDown() {
+ modelHelper.destroy()
+ }
+
/**
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
* needed anymore
@@ -98,26 +99,26 @@
@Throws(Exception::class)
fun testMigration() {
// Src Hotseat icons
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
// Src grid icons
// _ _ _ _ _
// _ _ _ _ 5
// _ _ 6 _ 7
// _ _ 8 _ 9
// _ _ _ _ _
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage9, 9, TMP_CONTENT_URI)
// Dest hotseat icons
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2)
// Dest grid icons
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage10)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -125,7 +126,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -136,13 +138,12 @@
// Check hotseat items
var c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -167,13 +168,12 @@
// Check workspace items
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -209,30 +209,30 @@
fun testMigrationBackAndForth() {
// Hotseat items in grid A
// 1 2 _ 3 4
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
// Workspace items in grid A
// _ _ _ _ _
// _ _ _ _ 5
// _ _ 6 _ 7
// _ _ 8 _ _
// _ _ _ _ _
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
// Hotseat items in grid B
// 2 _ _ _
- addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ modelHelper.addItem(SHORTCUT, 0, HOTSEAT, 0, 0, testPackage2)
// Workspace items in grid B
// _ _ _ _
// _ _ _ 10
// _ _ _ _
// _ _ _ _
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 3, testPackage10)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 3, testPackage10)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -241,7 +241,8 @@
val readerGridB = DbReader(db, TABLE_NAME, context, validPackages)
// migrate from A -> B
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
readerGridA,
readerGridB,
idp.numDatabaseHotseatIcons,
@@ -252,13 +253,12 @@
// Check hotseat items in grid B
var c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -272,13 +272,12 @@
// Check workspace items in grid B
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -295,11 +294,12 @@
assertThat(locMap[testPackage8]).isEqualTo(Triple(0, 3, 1))
// add item in B
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 2, testPackage9)
// migrate from B -> A
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
readerGridB,
readerGridA,
5,
@@ -309,13 +309,12 @@
)
// Check hotseat items in grid A
c =
- db.query(
- TMP_TABLE,
+ context.contentResolver.query(
+ TMP_CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -329,13 +328,12 @@
// Check workspace items in grid A
c =
- db.query(
- TMP_TABLE,
+ context.contentResolver.query(
+ TMP_CONTENT_URI,
arrayOf(SCREEN, CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -356,11 +354,12 @@
assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2))
// remove item from B
- db.delete(TMP_TABLE, "$_ID=7", null)
+ modelHelper.deleteItem(7, TMP_TABLE)
// migrate from A -> B
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
readerGridA,
readerGridB,
idp.numDatabaseHotseatIcons,
@@ -371,13 +370,12 @@
// Check hotseat items in grid B
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -391,13 +389,12 @@
// Check workspace items in grid B
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -446,28 +443,10 @@
fun migrateToLargerHotseat() {
val srcHotseatItems =
intArrayOf(
- addItem(
- ITEM_TYPE_APPLICATION,
- 0,
- CONTAINER_HOTSEAT,
- 0,
- 0,
- testPackage1,
- 1,
- TMP_TABLE
- ),
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE),
- addItem(
- ITEM_TYPE_APPLICATION,
- 2,
- CONTAINER_HOTSEAT,
- 0,
- 0,
- testPackage3,
- 3,
- TMP_TABLE
- ),
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
+ modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
)
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
idp.numDatabaseHotseatIcons = 6
@@ -476,7 +455,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -487,13 +467,12 @@
// Check hotseat items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -522,11 +501,11 @@
@Test
fun migrateFromLargerHotseat() {
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -534,7 +513,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -545,13 +525,12 @@
// Check hotseat items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -589,11 +568,11 @@
enableNewMigrationLogic("4,4")
// Setup src grid
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage1, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage2, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 1, testPackage3, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 2, testPackage4, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 3, 3, testPackage5, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 1, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 2, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 3, 3, testPackage5, 9, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 6
@@ -602,7 +581,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -613,13 +593,12 @@
// Get workspace items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(INTENT, SCREEN),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -651,11 +630,11 @@
enableNewMigrationLogic("2,2")
// Setup src grid
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 5
@@ -663,7 +642,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -674,13 +654,12 @@
// Get workspace items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(INTENT, SCREEN),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -712,11 +691,11 @@
enableNewMigrationLogic("5,5")
// Setup src grid
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -724,7 +703,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -735,13 +715,12 @@
// Get workspace items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(INTENT, SCREEN),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -768,48 +747,4 @@
private fun enableNewMigrationLogic(srcGridSize: String) {
LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize))
}
-
- private fun addItem(
- type: Int,
- screen: Int,
- container: Int,
- x: Int,
- y: Int,
- packageName: String?
- ): Int {
- return addItem(
- type,
- screen,
- container,
- x,
- y,
- packageName,
- dbHelper.generateNewItemId(),
- TABLE_NAME
- )
- }
-
- private fun addItem(
- type: Int,
- screen: Int,
- container: Int,
- x: Int,
- y: Int,
- packageName: String?,
- id: Int,
- tableName: String
- ): Int {
- val values = ContentValues()
- values.put(_ID, id)
- values.put(CONTAINER, container)
- values.put(SCREEN, screen)
- values.put(CELLX, x)
- values.put(CELLY, y)
- values.put(SPANX, 1)
- values.put(SPANY, 1)
- values.put(ITEM_TYPE, type)
- values.put(INTENT, Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0))
- db.insert(tableName, null, values)
- return id
- }
}
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 78812c0..d192be4 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -59,6 +59,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.Executors;
@@ -101,7 +102,7 @@
});
UserManagerState ums = new UserManagerState();
- mLoaderCursor = new LoaderCursor(mCursor, mApp, ums);
+ mLoaderCursor = new LoaderCursor(mCursor, Favorites.CONTENT_URI, mApp, ums);
ums.allUsers.put(0, Process.myUserHandle());
}
diff --git a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java
index 54b8489..2b6f9ff 100644
--- a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java
+++ b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java
@@ -45,7 +45,6 @@
import com.android.launcher3.R;
import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.DbDowngradeHelper;
-import com.android.launcher3.pm.UserCache;
import com.android.launcher3.settings.SettingsActivity;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.IOUtils;
@@ -166,11 +165,12 @@
private class MyDatabaseHelper extends DatabaseHelper {
MyDatabaseHelper() {
- super(mContext, null, UserCache.INSTANCE.get(mContext)::getSerialNumberForUser,
- () -> { });
+ super(mContext, null, false);
}
@Override
protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
+
+ protected void onEmptyDbCreated() { }
}
}
diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index 1b1b294..67de1f5 100644
--- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -46,7 +46,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.DatabaseHelper;
-import com.android.launcher3.model.ModelDbController;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,13 +63,13 @@
@Test
public void testGetProfileId() throws Exception {
- SQLiteDatabase db = new MyModelDbController(23).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(23).getWritableDatabase();
assertEquals(23, new RestoreDbTask().getDefaultProfileId(db));
}
@Test
public void testMigrateProfileId() throws Exception {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
@@ -90,7 +89,7 @@
@Test
public void testChangeDefaultColumn() throws Exception {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
@@ -121,20 +120,20 @@
long workProfileId = myProfileId + 2;
long workProfileId_old = myProfileId + 3;
- MyModelDbController controller = new MyModelDbController(myProfileId);
- SQLiteDatabase db = controller.getDb();
+ MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId);
+ SQLiteDatabase db = helper.getWritableDatabase();
BackupManager bm = spy(new BackupManager(context));
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
- controller.users.put(workProfileId, mWorkUser);
+ helper.users.put(workProfileId, mWorkUser);
- addIconsBulk(controller, 10, 1, myProfileId_old);
- addIconsBulk(controller, 6, 2, workProfileId_old);
+ addIconsBulk(helper, 10, 1, myProfileId_old);
+ addIconsBulk(helper, 6, 2, workProfileId_old);
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(context, controller, controller.getDb(), bm);
+ task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm);
// All the data has been migrated to the new user ids
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
@@ -152,20 +151,20 @@
long myProfileId_old = myProfileId + 1;
long workProfileId_old = myProfileId + 3;
- MyModelDbController controller = new MyModelDbController(myProfileId);
- SQLiteDatabase db = controller.getDb();
+ MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId);
+ SQLiteDatabase db = helper.getWritableDatabase();
BackupManager bm = spy(new BackupManager(context));
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
// Work profile is not migrated
doReturn(null).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
- addIconsBulk(controller, 10, 1, myProfileId_old);
- addIconsBulk(controller, 6, 2, workProfileId_old);
+ addIconsBulk(helper, 10, 1, myProfileId_old);
+ addIconsBulk(helper, 6, 2, workProfileId_old);
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(context, controller, controller.getDb(), bm);
+ task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm);
// All the data has been migrated to the new user ids
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
@@ -174,13 +173,12 @@
assertEquals(10, getCount(db, "select * from favorites"));
}
- private void addIconsBulk(MyModelDbController controller,
- int count, int screen, long profileId) {
+ private void addIconsBulk(DatabaseHelper helper, int count, int screen, long profileId) {
int columns = LauncherAppState.getIDP(getInstrumentation().getTargetContext()).numColumns;
String packageName = getInstrumentation().getContext().getPackageName();
for (int i = 0; i < count; i++) {
ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites._ID, controller.generateNewItemId());
+ values.put(LauncherSettings.Favorites._ID, helper.generateNewItemId());
values.put(LauncherSettings.Favorites.CONTAINER, CONTAINER_DESKTOP);
values.put(LauncherSettings.Favorites.SCREEN, screen);
values.put(LauncherSettings.Favorites.CELLX, i % columns);
@@ -191,11 +189,11 @@
values.put(LauncherSettings.Favorites.ITEM_TYPE, ITEM_TYPE_APPLICATION);
values.put(LauncherSettings.Favorites.INTENT,
new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
-
- controller.insert(TABLE_NAME, values);
+ helper.getWritableDatabase().insert(TABLE_NAME, null, values);
}
}
+
@Test
public void testRemoveScreenIdGaps_firstScreenEmpty() {
runRemoveScreenIdGapsTest(
@@ -218,7 +216,7 @@
}
private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
for (int i = 0; i < screenIds.length; i++) {
ContentValues values = new ContentValues();
@@ -256,15 +254,14 @@
}
}
- private class MyModelDbController extends ModelDbController {
+ private class MyDatabaseHelper extends DatabaseHelper {
- public final LongSparseArray<UserHandle> users = new LongSparseArray<>();
+ public final LongSparseArray<UserHandle> users;
- MyModelDbController(long profileId) {
- super(getInstrumentation().getTargetContext());
+ MyDatabaseHelper(long profileId) {
+ super(getInstrumentation().getTargetContext(), null, false);
+ users = new LongSparseArray<>();
users.put(profileId, myUserHandle());
- mOpenHelper = new DatabaseHelper(getInstrumentation().getTargetContext(), null,
- this::getSerialNumberForUser, () -> { });
}
@Override
@@ -272,5 +269,10 @@
int index = users.indexOfValue(user);
return index >= 0 ? users.keyAt(index) : -1;
}
+
+ @Override
+ protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
+
+ protected void onEmptyDbCreated() { }
}
}
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index d7f3547..7312dab 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -15,25 +15,27 @@
*/
package com.android.launcher3.ui.widget;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
-import android.util.Log;
+import android.view.View;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.tapl.Widget;
-import com.android.launcher3.tapl.WidgetResizeFrame;
-import com.android.launcher3.tapl.Widgets;
import com.android.launcher3.testcomponent.WidgetConfigActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
+import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -50,7 +52,6 @@
@RunWith(AndroidJUnit4.class)
public class AddConfigWidgetTest extends AbstractLauncherUiTest {
- private static final String WIDGET_PROVIDER_INFO = "b/276794291";
@Rule
public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@@ -88,33 +89,51 @@
clearHomescreen();
mDevice.pressHome();
- final Widgets widgets = mLauncher.getWorkspace().openAllWidgets();
-
// Drag widget to homescreen
WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor();
- WidgetResizeFrame resizeFrame =
- widgets.getWidget(mWidgetInfo.getLabel(mTargetContext.getPackageManager()))
- .dragConfigWidgetToWorkspace(acceptConfig);
+ mLauncher.getWorkspace()
+ .openAllWidgets()
+ .getWidget(mWidgetInfo.getLabel(mTargetContext.getPackageManager()))
+ .dragToWorkspace(true, false);
// Widget id for which the config activity was opened
mWidgetId = monitor.getWidgetId();
- Log.e(WIDGET_PROVIDER_INFO,
- "InstalledProviders count: " + mAppWidgetManager.getInstalledProviders().size());
-
// Verify that the widget id is valid and bound
assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
+ setResult(acceptConfig);
if (acceptConfig) {
- assertNotNull("Widget resize frame not shown after widget added", resizeFrame);
- resizeFrame.dismiss();
-
- final Widget widget =
- mLauncher.getWorkspace().tryGetWidget(mWidgetInfo.label, DEFAULT_UI_TIMEOUT);
- assertNotNull("Widget not found on the workspace", widget);
+ Wait.atMost("", new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
+ assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId));
} else {
- final Widget widget =
- mLauncher.getWorkspace().tryGetWidget(mWidgetInfo.label, DEFAULT_UI_TIMEOUT);
- assertNull("Widget unexpectedly found on the workspace", widget);
+ // Verify that the widget id is deleted.
+ Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null,
+ DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
+ }
+ }
+
+ private void setResult(boolean success) {
+ getInstrumentation().getTargetContext().sendBroadcast(
+ WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
+ success ? "clickOK" : "clickCancel"));
+ }
+
+ /**
+ * Condition for searching widget id
+ */
+ private class WidgetSearchCondition implements Wait.Condition, ItemOperator {
+
+ @Override
+ public boolean isTrue() throws Throwable {
+ return mMainThreadExecutor.submit(mActivityMonitor.itemExists(this)).get();
+ }
+
+ @Override
+ public boolean evaluate(ItemInfo info, View view) {
+ return info instanceof LauncherAppWidgetInfo
+ && ((LauncherAppWidgetInfo) info).providerName.getClassName().equals(
+ mWidgetInfo.provider.getClassName())
+ && ((LauncherAppWidgetInfo) info).appWidgetId == mWidgetId;
}
}
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 6fca965..bf31e39 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -363,6 +363,12 @@
sandboxContext.getContentResolver().insert(contentUri, values);
}
+ public void deleteItem(int itemId, @NonNull final String tableName) {
+ final Uri uri = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + tableName + "/" + itemId);
+ sandboxContext.getContentResolver().delete(uri, null, null);
+ }
+
/**
* Sets up a mock provider to load the provided layout by default, next time the layout loads
*/
@@ -420,7 +426,7 @@
}
public SQLiteDatabase getDb() {
- return getModelDbController().getDb();
+ return getModelDbController().getDatabaseHelper().getWritableDatabase();
}
}
diff --git a/tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java b/tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
index b534a41..48cf3df 100644
--- a/tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
+++ b/tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
@@ -32,6 +32,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
import org.junit.Before;
import org.junit.Test;
@@ -161,7 +162,6 @@
int maxPadding = Math.max(Math.max(padding.left, padding.right),
Math.max(padding.top, padding.bottom));
dp.cellLayoutBorderSpacePx.x = dp.cellLayoutBorderSpacePx.y = maxPadding + 1;
- Mockito.when(dp.shouldInsetWidgets()).thenReturn(true);
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
info.minWidth = CELL_SIZE * 3;
@@ -184,7 +184,6 @@
int maxPadding = Math.max(Math.max(padding.left, padding.right),
Math.max(padding.top, padding.bottom));
dp.cellLayoutBorderSpacePx.x = dp.cellLayoutBorderSpacePx.y = maxPadding - 1;
- Mockito.when(dp.shouldInsetWidgets()).thenReturn(false);
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
info.minWidth = CELL_SIZE * 3;
info.minHeight = CELL_SIZE * 3;
@@ -257,14 +256,16 @@
}
private InvariantDeviceProfile createIDP() {
- DeviceProfile profile = Mockito.mock(DeviceProfile.class);
+ DeviceProfile dp = LauncherAppState.getIDP(mContext)
+ .getDeviceProfile(mContext).copy(mContext);
+ DeviceProfile profile = Mockito.spy(dp);
doAnswer(i -> {
((Point) i.getArgument(0)).set(CELL_SIZE, CELL_SIZE);
return null;
}).when(profile).getCellSize(any(Point.class));
Mockito.when(profile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
profile.cellLayoutBorderSpacePx = new Point(SPACE_SIZE, SPACE_SIZE);
- Mockito.when(profile.shouldInsetWidgets()).thenReturn(true);
+ profile.widgetPadding.setEmpty();
InvariantDeviceProfile idp = new InvariantDeviceProfile();
List<DeviceProfile> supportedProfiles = new ArrayList<>(idp.supportedProfiles);
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
index 76492ba..8fc4481 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
@@ -147,7 +147,7 @@
widgetItems.add(new WidgetItem(
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
- mTestProfile, mIconCache));
+ mTestProfile, mIconCache, mContext));
}
return widgetItems;
}
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index e0101f5..60590e7 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -144,7 +144,7 @@
widgetItems.add(new WidgetItem(
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
- mTestProfile, mIconCache));
+ mTestProfile, mIconCache, mContext));
}
return widgetItems;
}
diff --git a/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java b/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
index d8f1f14..7552619 100644
--- a/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
@@ -26,6 +26,7 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
+import android.content.Context;
import android.os.UserHandle;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -249,12 +250,13 @@
String label = mWidgetsToLabels.get(componentName);
AppWidgetProviderInfo widgetInfo = createAppWidgetProviderInfo(componentName);
+ Context context = getApplicationContext();
LauncherAppWidgetProviderInfo launcherAppWidgetProviderInfo =
- LauncherAppWidgetProviderInfo.fromProviderInfo(getApplicationContext(), widgetInfo);
+ LauncherAppWidgetProviderInfo.fromProviderInfo(context, widgetInfo);
launcherAppWidgetProviderInfo.spanX = spanX;
launcherAppWidgetProviderInfo.spanY = spanY;
launcherAppWidgetProviderInfo.label = label;
- return new WidgetItem(launcherAppWidgetProviderInfo, mTestProfile, mIconCache);
+ return new WidgetItem(launcherAppWidgetProviderInfo, mTestProfile, mIconCache, context);
}
}
diff --git a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java b/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
index 0124f73..9c03ccf 100644
--- a/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/search/SimpleWidgetsSearchAlgorithmTest.java
@@ -202,7 +202,7 @@
WidgetItem widgetItem = new WidgetItem(
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
- mTestProfile, mIconCache);
+ mTestProfile, mIconCache, mContext);
widgetItems.add(widgetItem);
}
return widgetItems;
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index d2c2fd7..2c5a396 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -38,6 +38,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.icons.ComponentWithLabel;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
@@ -50,6 +51,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -68,7 +70,6 @@
@Mock
private IconCache mIconCache;
- @Mock
private DeviceProfile mTestDeviceProfile;
private Context mContext;
@@ -198,13 +199,18 @@
}
private void initDP() {
+ DeviceProfile dp = LauncherAppState.getIDP(mContext)
+ .getDeviceProfile(mContext).copy(mContext);
+ mTestDeviceProfile = Mockito.spy(dp);
+
doAnswer(i -> {
((Point) i.getArgument(0)).set(CELL_SIZE, CELL_SIZE);
return null;
}).when(mTestDeviceProfile).getCellSize(any(Point.class));
when(mTestDeviceProfile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
mTestDeviceProfile.cellLayoutBorderSpacePx = new Point(SPACE_SIZE, SPACE_SIZE);
- when(mTestDeviceProfile.shouldInsetWidgets()).thenReturn(false);
+ mTestDeviceProfile.widgetPadding.setEmpty();
+ mTestDeviceProfile.allAppsIconSizePx = 0;
}
private void initTestWidgets() {
@@ -212,19 +218,18 @@
new Point(2, 4), new Point(4, 4));
ArrayList<WidgetItem> widgetItems = new ArrayList<>();
- widgetSizes.stream().forEach(
- widgetSize -> {
- AppWidgetProviderInfo info = createAppWidgetProviderInfo(
- ComponentName.createRelative(
- TEST_PACKAGE,
- ".WidgetProvider_" + widgetSize.x + "x" + widgetSize.y));
- LauncherAppWidgetProviderInfo widgetInfo =
- LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
- widgetInfo.spanX = widgetSize.x;
- widgetInfo.spanY = widgetSize.y;
- widgetItems.add(new WidgetItem(widgetInfo, mTestInvariantProfile, mIconCache));
- }
- );
+ widgetSizes.stream().forEach(widgetSize -> {
+ AppWidgetProviderInfo info = createAppWidgetProviderInfo(
+ ComponentName.createRelative(
+ TEST_PACKAGE,
+ ".WidgetProvider_" + widgetSize.x + "x" + widgetSize.y));
+ LauncherAppWidgetProviderInfo widgetInfo =
+ LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
+ widgetInfo.spanX = widgetSize.x;
+ widgetInfo.spanY = widgetSize.y;
+ widgetItems.add(new WidgetItem(
+ widgetInfo, mTestInvariantProfile, mIconCache, mContext));
+ });
mWidget1x1 = widgetItems.get(0);
mWidget2x2 = widgetItems.get(1);
mWidget2x3 = widgetItems.get(2);
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 2687b28..0a0cf07 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -37,7 +37,8 @@
}
static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
- return By.clazz(TextView.class).text(appName).pkg(launcher.getLauncherPackageName());
+ return By.clazz(TextView.class).textContains(appName)
+ .pkg(launcher.getLauncherPackageName());
}
static BySelector getAnyAppIconSelector() {
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 58d5a36..a59eff7 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -25,13 +25,17 @@
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_SHELL_DRAG_READY;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT;
+import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_SCALE;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Condition;
+import androidx.test.uiautomator.UiDevice;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -43,6 +47,18 @@
// More drag steps than Launchables to give the window manager time to register the drag.
private static final int DEFAULT_DRAG_STEPS = 35;
+ // UNSTASHED_TASKBAR_HANDLE_HINT_SCALE value from TaskbarStashController.
+ private static final float UNSTASHED_TASKBAR_HANDLE_HINT_SCALE = 1.1f;
+
+ private final Condition<UiDevice, Boolean> mStashedTaskbarHintScaleCondition =
+ device -> mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_SCALE).getFloat(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD) - UNSTASHED_TASKBAR_HANDLE_HINT_SCALE
+ < 0.00001f;
+
+ private final Condition<UiDevice, Boolean> mStashedTaskbarDefaultScaleCondition =
+ device -> mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_SCALE).getFloat(
+ TestProtocol.TEST_INFO_RESPONSE_FIELD) - 1f < 0.00001f;
+
LaunchedAppState(LauncherInstrumentation launcher) {
super(launcher);
}
@@ -187,4 +203,89 @@
}
}
}
+
+ /**
+ * Emulate the cursor hovering the screen edge to unstash the taskbar.
+ *
+ * <p>This unstashing occurs when not actively hovering the taskbar.
+ */
+ public void hoverScreenBottomEdgeToUnstashTaskbar() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "cursor hover entering screen edge to unstash taskbar")) {
+ mLauncher.getDevice().wait(mStashedTaskbarDefaultScaleCondition,
+ ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT);
+
+ long downTime = SystemClock.uptimeMillis();
+ int leftEdge = 10;
+ Point taskbarUnstashArea = new Point(leftEdge, mLauncher.getRealDisplaySize().y - 1);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
+ new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null);
+
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
+
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
+ new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null);
+ }
+ }
+
+ /**
+ * Emulate the cursor hovering the taskbar to get unstash hint, then hovering below to unstash.
+ */
+ public void hoverBelowHintedTaskbarToUnstash() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "cursor hover entering stashed taskbar")) {
+ long downTime = SystemClock.uptimeMillis();
+ Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
+ mLauncher.getRealDisplaySize().y - 1);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null);
+
+ mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
+ LauncherInstrumentation.WAIT_TIME_MS);
+
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "cursor hover enter below taskbar to unstash")) {
+ downTime = SystemClock.uptimeMillis();
+ Point taskbarUnstashArea = new Point(mLauncher.getRealDisplaySize().x / 2,
+ mLauncher.getRealDisplaySize().y - 1);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
+ new Point(taskbarUnstashArea.x, taskbarUnstashArea.y), null);
+
+ mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID);
+ }
+ }
+ }
+
+ /**
+ * Emulate the cursor entering and exiting a hover over the taskbar.
+ */
+ public void hoverToShowTaskbarUnstashHint() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "cursor hover entering stashed taskbar")) {
+ long downTime = SystemClock.uptimeMillis();
+ Point stashedTaskbarHintArea = new Point(mLauncher.getRealDisplaySize().x / 2,
+ mLauncher.getRealDisplaySize().y - 1);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
+ new Point(stashedTaskbarHintArea.x, stashedTaskbarHintArea.y), null);
+
+ mLauncher.getDevice().wait(mStashedTaskbarHintScaleCondition,
+ LauncherInstrumentation.WAIT_TIME_MS);
+
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "cursor hover exiting stashed taskbar")) {
+ Point outsideStashedTaskbarHintArea = new Point(
+ mLauncher.getRealDisplaySize().x / 2,
+ mLauncher.getRealDisplaySize().y - 500);
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
+ new Point(outsideStashedTaskbarHintArea.x, outsideStashedTaskbarHintArea.y),
+ null);
+
+ mLauncher.getDevice().wait(mStashedTaskbarDefaultScaleCondition,
+ LauncherInstrumentation.WAIT_TIME_MS);
+ }
+ }
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index c4f8269..80fded5 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -107,6 +107,8 @@
static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
static final Pattern EVENT_TOUCH_CANCEL_TIS = getTouchEventPatternTIS("ACTION_CANCEL");
+ static final Pattern EVENT_HOVER_ENTER_TIS = getTouchEventPatternTIS("ACTION_HOVER_ENTER");
+ static final Pattern EVENT_HOVER_EXIT_TIS = getTouchEventPatternTIS("ACTION_HOVER_EXIT");
private static final Pattern EVENT_KEY_BACK_DOWN =
getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
@@ -140,7 +142,9 @@
* Represents a point in the code at which a callback can run.
*/
public enum CALLBACK_RUN_POINT {
- CALLBACK_HOLD_BEFORE_DROP
+ CALLBACK_HOLD_BEFORE_DROP,
+ CALLBACK_HOVER_ENTER,
+ CALLBACK_HOVER_EXIT,
}
private Consumer<CALLBACK_RUN_POINT> mCallbackAtRunPoint = null;
@@ -1682,6 +1686,12 @@
? EVENT_TOUCH_CANCEL_TIS : EVENT_TOUCH_UP_TIS);
}
break;
+ case MotionEvent.ACTION_HOVER_ENTER:
+ expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_ENTER_TIS);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_EXIT_TIS);
+ break;
}
final MotionEvent event = getMotionEvent(downTime, currentTime, action, point.x, point.y);
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
index 54be3c3..e349620 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenu.java
@@ -55,4 +55,12 @@
UiObject2 menuItem = mLauncher.findObjectInContainer(mMenu, By.text(expectedMenuItemText));
return menuItem != null;
}
+
+ /**
+ * Returns the menu item specified by name if present.
+ */
+ public OverviewTaskMenuItem getMenuItemByName(String menuItemName) {
+ return new OverviewTaskMenuItem(mLauncher,
+ mLauncher.waitForObjectInContainer(mMenu, By.text(menuItemName)));
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java
new file mode 100644
index 0000000..b2cc92d
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTaskMenuItem.java
@@ -0,0 +1,69 @@
+/*
+ * 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.tapl;
+
+import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOVER_ENTER;
+import static com.android.launcher3.tapl.LauncherInstrumentation.CALLBACK_RUN_POINT.CALLBACK_HOVER_EXIT;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+
+import androidx.test.uiautomator.UiObject2;
+
+/** Represents an item in the overview task menu. */
+public class OverviewTaskMenuItem {
+
+ private final LauncherInstrumentation mLauncher;
+ private final UiObject2 mMenuItem;
+
+ OverviewTaskMenuItem(LauncherInstrumentation launcher, UiObject2 menuItem) {
+ mLauncher = launcher;
+ mMenuItem = menuItem;
+ }
+
+ /**
+ * Returns this menu item's visible bounds.
+ */
+ public Rect getVisibleBounds() {
+ return mMenuItem.getVisibleBounds();
+ }
+
+ /**
+ * Emulate the cursor entering and exiting a hover over this menu item.
+ */
+ public void hoverCursor() {
+ try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+ LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "cursor hover entering menu item")) {
+ long downTime = SystemClock.uptimeMillis();
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER,
+ new Point(mMenuItem.getVisibleCenter().x, mMenuItem.getVisibleCenter().y),
+ null);
+ mLauncher.runCallbackIfActive(CALLBACK_HOVER_ENTER);
+
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "cursor hover exiting menu item")) {
+ downTime = SystemClock.uptimeMillis();
+ mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_HOVER_EXIT,
+ new Point(mMenuItem.getVisibleCenter().x, mMenuItem.getVisibleCenter().y),
+ null);
+ mLauncher.runCallbackIfActive(CALLBACK_HOVER_EXIT);
+ }
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java
index d440903..e7016a3 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widget.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widget.java
@@ -17,11 +17,7 @@
package com.android.launcher3.tapl;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -69,10 +65,7 @@
*/
@NonNull
public WidgetResizeFrame dragWidgetToWorkspace() {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false, -1,
- -1, 1, 1);
- }
+ return dragWidgetToWorkspace(-1, -1, 1, 1);
}
/**
@@ -84,22 +77,19 @@
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"Dragging widget to workspace cell " + cellX + "," + cellY)) {
- return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false,
- cellX, cellY, spanX, spanY);
- }
- }
+ if (cellX == -1 || cellY == -1) {
+ internalDragToWorkspace(/* startsActivity= */ false, /* isWidgetShortcut= */
+ false);
+ } else {
+ dragToWorkspaceCellPosition(/* startsActivity= */ false, /* isWidgetShortcut= */
+ false, cellX, cellY, spanX, spanY);
+ }
- /**
- * Drags a configurable widget from the widgets container to the workspace, either accepts or
- * cancels the configuration based on {@code acceptsConfig}, and returns the resize frame that
- * is shown if the widget is added.
- */
- @Nullable
- public WidgetResizeFrame dragConfigWidgetToWorkspace(boolean acceptsConfig) {
- // TODO(b/239438337, fransebas) add correct event checking for this case
- //try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1, 1, 1);
- //}
+ try (LauncherInstrumentation.Closable closable = mLauncher.addContextLayer(
+ "want to get widget resize frame")) {
+ return new WidgetResizeFrame(mLauncher);
+ }
+ }
}
/**
@@ -122,53 +112,4 @@
isWidgetShortcut,
launchable::addExpectedEventsForLongClick);
}
-
- /**
- * Drags a widget from the widgets container to the workspace and returns the resize frame that
- * is shown after the widget is added.
- *
- * <p> If {@code configurable} is true, then either accepts or cancels the configuration based
- * on {@code acceptsConfig}.
- * <p> If either {@code cellX} or {@code cellY} are negative, then a default location would be
- * chosen
- *
- * @param configurable if the widget has a configuration activity.
- * @param acceptsConfig if the widget has a configuration, then if we should accept it or
- * cancel it
- * @param cellX X position to drop the widget in the workspace
- * @param cellY Y position to drop the widget in the workspace
- * @return returns the given resize frame of the widget after being dropped, if
- * configurable is true and acceptsConfig is false then the widget would not be places and will
- * be cancel and it returns null.
- */
- @Nullable
- private WidgetResizeFrame dragWidgetToWorkspace(boolean configurable, boolean acceptsConfig,
- int cellX, int cellY, int spanX, int spanY) {
- if (cellX == -1 || cellY == -1) {
- internalDragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */
- false);
- } else {
- dragToWorkspaceCellPosition(/* startsActivity= */ configurable, /* isWidgetShortcut= */
- false, cellX, cellY, spanX, spanY);
- }
-
- if (configurable) {
- // Configure the widget.
- BySelector selector = By.text(acceptsConfig ? "OK" : "Cancel");
- mLauncher.getDevice()
- .wait(Until.findObject(selector), LauncherInstrumentation.WAIT_TIME_MS)
- .click();
-
- // If the widget configuration was cancelled, then the widget wasn't added to the home
- // screen. In that case, we cannot return a resize frame.
- if (!acceptsConfig) {
- return null;
- }
- }
-
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to get widget resize frame")) {
- return new WidgetResizeFrame(mLauncher);
- }
- }
}