Merge "Fixing robolectric tests not running on UI thread after changing looper mode" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index eced590..163fc17 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -231,6 +231,13 @@
}
flag {
+ name: "enable_refactor_task_thumbnail"
+ namespace: "launcher"
+ description: "Enables rewritten version of TaskThumbnailViews in Overview"
+ bug: "331753115"
+}
+
+flag {
name: "enable_handle_delayed_gesture_callbacks"
namespace: "launcher"
description: "Enables additional handling for delayed mid-gesture callbacks"
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 253147d..0eb8775 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -56,7 +56,7 @@
import com.android.quickstep.util.AssistContentRequester;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GoOverviewActionsView;
-import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -101,7 +101,7 @@
/**
* Create a new overlay instance for the given View
*/
- public TaskOverlayGo createOverlay(TaskThumbnailView thumbnailView) {
+ public TaskOverlayGo createOverlay(TaskThumbnailViewDeprecated thumbnailView) {
return new TaskOverlayGo(thumbnailView, mContentRequester);
}
@@ -120,7 +120,7 @@
private OverlayDialogGo mDialog;
private ArrowTipView mArrowTipView;
- private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
+ private TaskOverlayGo(TaskThumbnailViewDeprecated taskThumbnailView,
AssistContentRequester assistContentRequester) {
super(taskThumbnailView);
mFactoryContentRequester = assistContentRequester;
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 9d599c9..9f648a7 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -28,7 +28,7 @@
launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
- <com.android.quickstep.views.TaskThumbnailView
+ <com.android.quickstep.views.TaskThumbnailViewDeprecated
android:id="@+id/snapshot"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index 3cafcfd..36d7f86 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -42,7 +42,7 @@
views that do not inherint from TaskView only or create a generic TaskView that have
N number of tasks.
-->
- <com.android.quickstep.views.TaskThumbnailView
+ <com.android.quickstep.views.TaskThumbnailViewDeprecated
android:id="@+id/snapshot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index e91e773..ec657bd 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -33,12 +33,12 @@
launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
launcher:hoverBorderColor="?androidprv:attr/materialColorPrimary">
- <com.android.quickstep.views.TaskThumbnailView
+ <com.android.quickstep.views.TaskThumbnailViewDeprecated
android:id="@+id/snapshot"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- <com.android.quickstep.views.TaskThumbnailView
+ <com.android.quickstep.views.TaskThumbnailViewDeprecated
android:id="@+id/bottomright_snapshot"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
diff --git a/quickstep/res/layout/task_menu_with_arrow.xml b/quickstep/res/layout/task_menu_with_arrow.xml
index c9108a5..88e5cf7 100644
--- a/quickstep/res/layout/task_menu_with_arrow.xml
+++ b/quickstep/res/layout/task_menu_with_arrow.xml
@@ -18,6 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:minWidth="@dimen/task_menu_width_grid"
android:animateLayoutChanges="true"
android:background="@drawable/task_menu_bg"
android:orientation="vertical"
diff --git a/quickstep/res/layout/taskbar_edu_circle_to_search.xml b/quickstep/res/layout/taskbar_edu_search.xml
similarity index 79%
rename from quickstep/res/layout/taskbar_edu_circle_to_search.xml
rename to quickstep/res/layout/taskbar_edu_search.xml
index 6c95f25..ca84f35 100644
--- a/quickstep/res/layout/taskbar_edu_circle_to_search.xml
+++ b/quickstep/res/layout/taskbar_edu_search.xml
@@ -23,35 +23,35 @@
style="@style/TextAppearance.TaskbarEduTooltip.Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:text="@string/taskbar_edu_circle_to_search_title"
+ android:text="@string/taskbar_search_edu_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/circle_to_search_animation" />
+ app:layout_constraintBottom_toTopOf="@+id/search_edu_animation" />
<com.airbnb.lottie.LottieAnimationView
- android:id="@+id/circle_to_search_animation"
+ android:id="@+id/search_edu_animation"
android:layout_width="@dimen/taskbar_edu_swipe_lottie_width"
android:layout_height="@dimen/taskbar_edu_swipe_lottie_height"
android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
- app:layout_constraintBottom_toTopOf="@id/circle_to_search_text"
+ app:layout_constraintBottom_toTopOf="@id/search_edu_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
- app:lottie_rawRes="@raw/taskbar_edu_circle_to_search"
+ app:lottie_rawRes="@raw/taskbar_edu_search"
app:lottie_autoPlay="true"
app:lottie_loop="true" />
<TextView
- android:id="@+id/circle_to_search_text"
+ android:id="@+id/search_edu_text"
style="@style/TextAppearance.TaskbarEduTooltip.Subtext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
- android:textSize="@dimen/taskbar_edu_circle_to_search_subtitle_text_size"
+ android:textSize="@dimen/taskbar_edu_search_subtitle_text_size"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@id/circle_to_search_animation"
+ app:layout_constraintTop_toBottomOf="@id/search_edu_animation"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/quickstep/res/raw/taskbar_edu_circle_to_search.json b/quickstep/res/raw/taskbar_edu_search.json
similarity index 100%
rename from quickstep/res/raw/taskbar_edu_circle_to_search.json
rename to quickstep/res/raw/taskbar_edu_search.json
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 6a749d1..ab1dd78 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Voeg nou app by werkskerm"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselleer"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 500cc3d..e7fe0fa 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> እና <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"መተግበሪያን ወደ ዴስክቶፕ በማከል ላይ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ይቅር"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index de2c8b1..e98fc2f 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"\"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" و\"<xliff:g id="APP_NAME_2">%2$s</xliff:g>\""</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"إضافة تطبيق إلى سطح المكتب"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"إلغاء"</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index c483fb1..9b75dad 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> আৰু <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপত এপ্ যোগ দি থকা হৈছে"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল কৰক"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 1500e82..25a0fc8 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> və <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Tətbiqin masaüstünə əlavə edilməsi"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ləğv edin"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 9529776..aaa7d8c 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaje se aplikacija na radnu povrršinu"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 6b20866..4d65ecd 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Замацаваць"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Адвольная форма"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Працоўны стол"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> і <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Дадаванне праграмы на камп\'ютар"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасаваць"</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 8631d8b..bf42a23 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Фиксиране"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Свободна форма"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"За компютър"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Приложението се добавя на настолния компютър"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отказ"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 948d07d..89a5e76 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"পিন করুন"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ফ্রি-ফর্ম"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"ডেস্কটপ"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ও <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপে অ্যাপ যোগ করা হচ্ছে"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল করুন"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 15da445..059c14c 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodan oblik"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Radna površina"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke korištenja aplikacije"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 62ae01b..f2118eb 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"S\'està afegint l\'aplicació a l\'ordinador"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel·la"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index a07ffc5..0771ace 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Přidání aplikace na plochu"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušit"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index a1ca3c5..a805762 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fastgør"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Frit format"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Computertilstand"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nye elementer"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Indstillinger for appforbrug"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ryd alt"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Appen føjes til computeren"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuller"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 73c3f04..b1ce2d5 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixieren"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform-Modus"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Desktopmodus"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Einstellungen zur App-Nutzung"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Alle Apps schließen"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> und <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Hinzufügen einer App zum Desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Abbrechen"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 55e535b..030d834 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> και <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Γίνεται προσθήκη εφαρμογής στον υπολογιστή"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ακύρωση"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 64c68e0..a083fa4 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 4daaa90..cadf7ee 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -138,6 +138,7 @@
<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>
+ <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 64c68e0..a083fa4 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 64c68e0..a083fa4 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 19e6aa0..7f1aa13 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -138,6 +138,7 @@
<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>
+ <string name="quick_switch_desktop" msgid="4834587349322698616">"{count,plural, =1{Show # desktop app.}other{Show # desktop apps.}}"</string>
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index aa568f3..0a92029 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Escritorio"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración de uso de la app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Cerrar todo"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Agregando app al escritorio"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 27eceb8..0d1ebe0 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Ordenador"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay nada reciente"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ajustes de uso de la aplicación"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Añadiendo aplicación al ordenador"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index bffce79..77529cb 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kinnita"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vabavorm"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Lauaarvuti režiim"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hiljutisi üksusi pole"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Rakenduse kasutuse seaded"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Sule kõik"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Rakenduse lisamine arvutisse"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Tühista"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 39fc489..8a504ec 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ainguratu"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Modu librea"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Ordenagailua"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ez dago azkenaldi honetako ezer"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Aplikazioen erabileraren ezarpenak"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Garbitu guztiak"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> eta <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Aplikazioa mahaigainean gehitzen"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Utzi"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index a3e5b7f..8141045 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> و <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"درحال افزودن برنامه به رایانه"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"لغو"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 40c4fc2..18331a2 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kiinnitä"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vapaamuotoinen"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Tietokone"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ei viimeaikaisia kohteita"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Sovelluksen käyttöasetukset"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Poista kaikki"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Sovelluksen lisääminen työpöydälle"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Peru"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 10aa359..467a72a 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'application au bureau en cours…"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 457d425..20b9bab 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'appli au bureau"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 0be8958..71ebcf7 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma libre"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Escritorio"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Non hai elementos recentes"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración do uso de aplicacións"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Engadindo aplicación ao ordenador"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 644240a..cb3c03f 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"પિન કરો"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ફ્રિફોર્મ"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"ડેસ્કટૉપ"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> અને <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ડેસ્કટૉપ પર ઍપ ઉમેરી રહ્યાં છીએ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"રદ કરો"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index b2da5db..ebe7d89 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करें"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ़्रीफ़ॉर्म"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"डेस्कटॉप"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> और <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉप पर ऐप्लिकेशन जोड़ा जा रहा है"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करें"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index b68d961..a8875ad 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Prikvači"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Računalo"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Izbriši sve"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Odustani"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 006184b..4650f4d 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> és <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Alkalmazás hozzáadása az asztalhoz"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Mégse"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index e0646aa..04049a9 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ամրացնել"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Կամայական ձև"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Համակարգիչ"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> և <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Հավելվածն ավելացվում է աշխատասեղանին"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Չեղարկել"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 34a8b2b..833a568 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -138,6 +138,8 @@
<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 lainnya.}other{Tampilkan # aplikasi lainnya.}}"</string>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan aplikasi ke Desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batalkan"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index d5f2488..5d3693d 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Forriti bætt við skjáborð"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Hætta við"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index c38243f..a9391f6 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Aggiunta app a desktop in corso…"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annulla"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 9d6b246..7514ba1 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ו-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"האפליקציה מתווספת לשולחן העבודה"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ביטול"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 69b3954..0cc9f89 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> と <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"アプリをデスクトップに追加する"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"キャンセル"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 4306f1f..d24a698 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> და <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"მიმდინარეობს აპის დესკტოპზე დამატება"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"გაუქმება"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 2a12452..5073a3f 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Бекіту"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Еркін форма"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Компьютер"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> және <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Жұмыс үстеліне қолданба қосу"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Бас тарту"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index bcec955..0d9aa52 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> និង <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"កំពុងបញ្ចូលកម្មវិធីទៅកុំព្យូទ័រ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"បោះបង់"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 4df7f3a..e4ff655 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ಡೆಸ್ಕ್ಟಾಪ್ಗೆ ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ರದ್ದುಮಾಡಿ"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 0fba87d..90486bd 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"고정"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"자유 형식"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"데스크톱"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> 및 <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"데스크톱에 앱 추가하기"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"취소"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 061952c..00573c3 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Кадап коюу"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Эркин форма режими"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Компьютер"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> жана <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Колдонмону иш тактага кошуу"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Жокко чыгаруу"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 9496dd5..c2ec34f 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ແລະ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ການເພີ່ມແອັບໄປໃສ່ເດັສທັອບ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ຍົກເລີກ"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 47c3670..a4ca187 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"„<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ ir „<xliff:g id="APP_NAME_2">%2$s</xliff:g>“"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridedama programa prie darbalaukio"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atšaukti"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 276120b..7fef880 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Piespraust"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Brīva forma"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Dators"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nav nesenu vienumu."</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Lietotņu izmantošanas iestatījumi"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Notīrīt visu"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"“<xliff:g id="APP_NAME_1">%1$s</xliff:g>” un “<xliff:g id="APP_NAME_2">%2$s</xliff:g>”"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Notiek lietotnes pievienošana datoram"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atcelt"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 539448d..832bd74 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Закачи"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Компјутер"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Додавање на апликацијата во „Работна површина“"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 90ceeff..6432438 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ആപ്പ് ഡെസ്ക്ടോപ്പിലേക്ക് ചേർക്കുന്നു"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"റദ്ദാക്കുക"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index c021d21..4ab619e 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Бэхлэх"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Чөлөөтэй хувьсах"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Компьютер"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> болон <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Компьютерт апп нэмж байна"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Цуцлах"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 3fea03b..cae868d 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> आणि <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉपवर ॲप जोडत आहे"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करा"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index d998176..92f6a64 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan apl pada Desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batal"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 66c4e5f..f694c39 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"ပင်ထိုးရန်"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"အလွတ်ပုံစံ"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"ဒက်စ်တော့"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> နှင့် <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"‘ဒက်စ်တော့’ တွင် အက်ပ်ကို ထည့်ခြင်း"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"မလုပ်တော့"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 6ee48dc..54f2596 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Legg til apper på datamaskin"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index f6668c1..401e13b 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> र <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटपमा एप हालिँदै छ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द गर्नुहोस्"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index c288868..e2e0dbe 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Vastzetten"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vrije vorm"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Desktop"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen recente items"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Instellingen voor app-gebruik"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Alles wissen"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"App toevoegen aan desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuleren"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index a7c5d44..d05fe1e 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"ପିନ୍"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ଫ୍ରିଫର୍ମ"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"ଡେସ୍କଟପ"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ଏବଂ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ଡେସ୍କଟପରେ ଆପ ଯୋଗ କରାଯାଉଛି"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ବାତିଲ କରନ୍ତୁ"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 15be242..3256033 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ਐਪ ਨੂੰ ਡੈਸਕਟਾਪ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ਰੱਦ ਕਰੋ"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 11f46bc..4792733 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaję aplikację do komputera"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anuluj"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 5af1bf6..4f96a38 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"A adicionar a app ao computador"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 9ea746c..2530361 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Computador"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configurações de uso do app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Remover tudo"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Adicionando app ao computador"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index e45e45a..0d54d0d 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixează"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formă liberă"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Computer"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Niciun element recent"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setări de utilizare a aplicației"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Șterge tot"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> și <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Se adaugă aplicația pe computer"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulează"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 5369d1e..41e0f35 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Добавление приложения на компьютер"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отмена"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 3b7598b..f90dd28 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> සහ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ඩෙස්ක්ටොප් වෙත යෙදුම එක් කිරීම"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"අවලංගු කරන්න"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index c01f2f0..3b5639c 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridanie aplikácie na plochu"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušiť"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 58e34f2..6714240 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pripni"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Prosta oblika"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Namizni računalnik"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ni nedavnih elementov"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavitve uporabe aplikacij"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Počisti vse"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> in <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodajanje aplikacije na namizje"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Prekliči"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 7ae201f..f67efb6 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Gozhdo"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formë e lirë"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Desktopi"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nuk ka asnjë artikull të fundit"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cilësimet e përdorimit të aplikacionit"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Pastroji të gjitha"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dhe <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Shtimi i aplikacionit te desktopi"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulo"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 2a7239e..5ad5c1f 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Додаје се апликација на радну поврршину"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 808cfe9..67f7928 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -21,8 +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>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Dator"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> och <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Lägger till appen på skrivbordet"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index ba960ec..8f4d3fd 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> na <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Kuweka programu kwenye Eneo-kazi"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ghairi"</string>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index c5cbfcd..5a4630e 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"பின் செய்தல்"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"குறிப்பிட்ட வடிவமில்லாத பயன்முறை"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"டெஸ்க்டாப்"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ஆப்ஸை டெஸ்க்டாப்பில் சேர்க்கிறது"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ரத்துசெய்"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index f2c06b4..ceee6e5 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"డెస్క్టాప్నకు యాప్ను జోడిస్తోంది"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"రద్దు చేయండి"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index c5f0b3e..71f9950 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> และ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"การเพิ่มแอปไปยังเดสก์ท็อป"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ยกเลิก"</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 5fbc57b..3c3acc1 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"I-pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Desktop"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Walang kamakailang item"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mga setting ng paggamit ng app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"I-clear lahat"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> at <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Idinaragdag ang app sa Desktop"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselahin"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 79f8ad1..45d2fc4 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Sabitle"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Serbest çalışma"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Masaüstü"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yeni öğe yok"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Uygulama kullanım ayarları"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Tümünü temizle"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ve <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Uygulama Masaüstü\'ne ekleniyor"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"İptal"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index c1ef51d..4838552 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Закріпити"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Довільна форма"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Комп’ютер"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> та <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Встановлення додатка на комп’ютер"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасувати"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 69b4ba1..ee96e5c 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> اور <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"ڈیسک ٹاپ پر ایپ شامل کرنا"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"منسوخ کریں"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index f548c19..41e6d24 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> va <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Ilova kompyuterga qoʻshilmoqda"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Bekor qilish"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 136e1d2..709fb10 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ghim"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Dạng tự do"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"Máy tính"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Không có mục gần đây nào"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cài đặt mức sử dụng ứng dụng"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Xóa tất cả"</string>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> và <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Đang thêm ứng dụng vào máy tính"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Huỷ"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index b90d6bf..d30fdfa 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -21,8 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"自由窗口"</string>
- <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
- <skip />
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"桌面设备"</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>
@@ -139,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>和<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"将应用添加到桌面"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 45cf781..d8e698c 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
- <string name="recent_task_option_desktop" msgid="8280879717125435668">"電腦"</string>
+ <string name="recent_task_option_desktop" msgid="8280879717125435668">"桌面"</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>
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"正在新增應用程式至桌面"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index ef811c4..98465a6 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"新增應用程式至桌面"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 71c9227..bbb6631 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -138,6 +138,8 @@
<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>
+ <!-- no translation found for quick_switch_desktop (4834587349322698616) -->
+ <skip />
<string name="quick_switch_split_task" msgid="5598194724255333896">"I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> ne-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
<string name="desktop_select_app_toast" msgid="2306057322833956910">"Yengeza i-app ku-Deskithophu"</string>
<string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Khansela"</string>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 28cdb99..b3502db 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -35,6 +35,7 @@
<string name="taskbar_view_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarViewCallbacksFactory</string>
<string name="launcher_restore_event_logger_class" translatable="false">com.android.quickstep.LauncherRestoreEventLoggerImpl</string>
<string name="plugin_manager_wrapper_class" translatable="false">com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl</string>
+ <string name="taskbar_edu_tooltip_controller_class" translatable="false">com.android.launcher3.taskbar.TaskbarEduTooltipController</string>
<string name="nav_handle_long_press_handler_class" translatable="false"></string>
<string name="assist_utils_class" translatable="false"></string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 9ca8060..dbf075c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -403,7 +403,7 @@
<dimen name="taskbar_edu_features_tooltip_width_with_one_feature">412dp</dimen>
<dimen name="taskbar_edu_features_tooltip_width_with_two_features">428dp</dimen>
<dimen name="taskbar_edu_features_tooltip_width_with_three_features">624dp</dimen>
- <dimen name="taskbar_edu_circle_to_search_subtitle_text_size">12sp</dimen>
+ <dimen name="taskbar_edu_search_subtitle_text_size">12sp</dimen>
<!--- Taskbar Pinning -->
<dimen name="taskbar_pinning_popup_menu_width">300dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index fc3c0e3..278c66a 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -275,10 +275,10 @@
<string name="taskbar_edu_pinning_title">Always show the Taskbar</string>
<!-- Text in dialog that shows a user how to pin the Taskbar. [CHAR_LIMIT 150] -->
<string name="taskbar_edu_pinning_standalone">To always show the Taskbar on the bottom of your screen, touch & hold the divider</string>
- <!-- Title in dialog that shows a user how to invoke the Circle to Search feature. [CHAR_LIMIT 150] -->
- <string name="taskbar_edu_circle_to_search_title">Touch & hold the action key to search what\'s on your screen</string>
+ <!-- Title in dialog that shows a user how to invoke the Search feature. [CHAR_LIMIT 150] -->
+ <string name="taskbar_search_edu_title">Touch & hold the action key to search what\'s on your screen</string>
<!-- Message showed to user to disclose privacy information they need to accept in order to access the app. [CHAR LIMIT=200]-->
- <string name="taskbar_edu_circle_to_search_disclosure">This product uses the selected part of your screen to search. Google\'s <xliff:g example="https://policies.google.com/privacy/embedded" id="begin_privacy_link"><a href=\"%1$s\"></xliff:g>Privacy Policy<xliff:g id="end_privacy_link"></a></xliff:g> and <xliff:g example="https://policies.google.com/terms" id="begin_tos_link"><a href=\"%2$s\"></xliff:g>Terms of Service<xliff:g id="end_tos_link"></a></xliff:g> apply.</string>
+ <string name="taskbar_edu_search_disclosure">This product uses the selected part of your screen to search. Google\'s <xliff:g example="https://policies.google.com/privacy/embedded" id="begin_privacy_link"><a href=\"%1$s\"></xliff:g>Privacy Policy<xliff:g id="end_privacy_link"></a></xliff:g> and <xliff:g example="https://policies.google.com/terms" id="begin_tos_link"><a href=\"%2$s\"></xliff:g>Terms of Service<xliff:g id="end_tos_link"></a></xliff:g> apply.</string>
<!-- Text on button to exit a tutorial [CHAR_LIMIT=16] -->
<string name="taskbar_edu_close">Close</string>
<!-- Text on button to finish a tutorial [CHAR_LIMIT=16] -->
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 694475a..84c2ed2 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -28,14 +28,15 @@
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
-import com.android.launcher3.util.Themes;
/**
* A view which shows a horizontal divider
@@ -54,6 +55,7 @@
private final @ColorInt int mStrokeColor;
private final @ColorInt int mAllAppsLabelTextColor;
+ private final AccessibilityManager mAccessibilityManager;
private Layout mAllAppsLabelLayout;
private boolean mShowAllAppsLabel;
@@ -87,7 +89,8 @@
mAllAppsLabelTextColor = ContextCompat.getColor(context,
R.color.material_color_on_surface_variant);
- mShowAllAppsLabel = !ALL_APPS_VISITED_COUNT.hasReachedMax(context);
+ mAccessibilityManager = AccessibilityManager.getInstance(context);
+ setShowAllAppsLabel(!ALL_APPS_VISITED_COUNT.hasReachedMax(context));
}
public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
@@ -99,6 +102,9 @@
/** {@code true} if all apps label should be shown in place of divider. */
public void setShowAllAppsLabel(boolean showAllAppsLabel) {
+ if (mAccessibilityManager.isEnabled() && !Utilities.isRunningInTestHarness()) {
+ showAllAppsLabel = true;
+ }
if (showAllAppsLabel != mShowAllAppsLabel) {
mShowAllAppsLabel = showAllAppsLabel;
updateDividerType();
@@ -148,6 +154,7 @@
mDividerType = dividerType;
int topPadding;
int bottomPadding;
+ setContentDescription(null);
switch (dividerType) {
case LINE:
topPadding = 0;
@@ -161,6 +168,7 @@
bottomPadding = getResources()
.getDimensionPixelSize(R.dimen.all_apps_label_bottom_padding);
mPaint.setColor(mAllAppsLabelTextColor);
+ setContentDescription(mAllAppsLabelLayout.getText());
break;
case NONE:
default:
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 489102f..2c2311a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
-import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE;
import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE;
@@ -306,8 +305,8 @@
*/
public void showEduOnAppLaunch() {
if (!shouldShowEduOnAppLaunch()) {
- // Called in case the edu finishes and circle to search edu is still pending
- mControllers.taskbarEduTooltipController.maybeShowCircleToSearchEdu();
+ // Called in case the edu finishes and search edu is still pending
+ mControllers.taskbarEduTooltipController.maybeShowSearchEdu();
return;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 679528b..1a94424 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -306,7 +306,7 @@
new TaskbarTranslationController(this),
new TaskbarSpringOnStashController(this),
createTaskbarRecentAppsController(isPcMode),
- new TaskbarEduTooltipController(this),
+ TaskbarEduTooltipController.newInstance(this),
new KeyboardQuickSwitchController(),
new TaskbarPinningController(this),
bubbleControllersOptional);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index e53f627..d43055d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.taskbar
+import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
@@ -42,8 +43,10 @@
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.launcher3.util.DisplayController
-import com.android.launcher3.util.OnboardingPrefs.TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
+import com.android.launcher3.util.OnboardingPrefs.TASKBAR_SEARCH_EDU_SEEN
+import com.android.launcher3.util.ResourceBasedOverride
+import com.android.launcher3.views.ActivityContext
import com.android.launcher3.views.BaseDragLayer
import com.android.quickstep.util.LottieAnimationColorUtils
import java.io.PrintWriter
@@ -72,9 +75,11 @@
annotation class TaskbarEduTooltipStep
/** Controls stepping through the Taskbar tooltip EDU. */
-class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
- LoggableTaskbarController {
+open class TaskbarEduTooltipController(context: Context) :
+ ResourceBasedOverride, LoggableTaskbarController {
+ protected val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context)
+ open val shouldShowSearchEdu = false
private val isTooltipEnabled: Boolean
get() = !Utilities.isRunningInTestHarness() && !activityContext.isPhoneMode
private val isOpen: Boolean
@@ -83,13 +88,13 @@
get() = isTooltipEnabled && tooltipStep <= TOOLTIP_STEP_FEATURES
private lateinit var controllers: TaskbarControllers
- // Keep track of whether the user has seen the Circle to Search Edu
- private var userHasSeenCircleToSearchEdu: Boolean
+ // Keep track of whether the user has seen the Search Edu
+ private var userHasSeenSearchEdu: Boolean
get() {
- return TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN.get(activityContext)
+ return TASKBAR_SEARCH_EDU_SEEN.get(activityContext)
}
private set(seen) {
- LauncherPrefs.get(activityContext).put(TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN, seen)
+ LauncherPrefs.get(activityContext).put(TASKBAR_SEARCH_EDU_SEEN, seen)
}
@TaskbarEduTooltipStep
@@ -105,8 +110,8 @@
fun init(controllers: TaskbarControllers) {
this.controllers = controllers
- // We want to show the Circle To Search Edu right after pinning, so we post it here
- activityContext.dragLayer.post { maybeShowCircleToSearchEdu() }
+ // We want to show the Search Edu right after pinning the taskbar, so we post it here
+ activityContext.dragLayer.post { maybeShowSearchEdu() }
}
/** Shows swipe EDU tooltip if it is the current [tooltipStep]. */
@@ -136,7 +141,7 @@
fun maybeShowFeaturesEdu() {
if (!isTooltipEnabled || tooltipStep > TOOLTIP_STEP_FEATURES) {
maybeShowPinningEdu()
- maybeShowCircleToSearchEdu()
+ maybeShowSearchEdu()
return
}
@@ -233,26 +238,26 @@
}
/**
- * Shows standalone Circle To Search EDU tooltip if this EDU has not been seen.
+ * Shows standalone Search EDU tooltip if this EDU has not been seen.
*
- * We show this standalone edu for users to learn to how to trigger Circle To Search from the
- * pinned taskbar
+ * We show this standalone edu for users to learn to how to trigger Search from the pinned
+ * taskbar
*/
- fun maybeShowCircleToSearchEdu() {
+ fun maybeShowSearchEdu() {
if (
!enableTaskbarPinning() ||
!DisplayController.isPinnedTaskbar(activityContext) ||
!isTooltipEnabled ||
- userHasSeenCircleToSearchEdu
+ !shouldShowSearchEdu ||
+ userHasSeenSearchEdu
) {
return
}
- userHasSeenCircleToSearchEdu = true
- inflateTooltip(R.layout.taskbar_edu_circle_to_search)
+ userHasSeenSearchEdu = true
+ inflateTooltip(R.layout.taskbar_edu_search)
tooltip?.run {
- requireViewById<LottieAnimationView>(R.id.circle_to_search_animation)
- .supportLightTheme()
- val eduSubtitle: TextView = requireViewById(R.id.circle_to_search_text)
+ requireViewById<LottieAnimationView>(R.id.search_edu_animation).supportLightTheme()
+ val eduSubtitle: TextView = requireViewById(R.id.search_edu_text)
showDisclosureText(eduSubtitle)
updateLayoutParams<BaseDragLayer.LayoutParams> {
if (DisplayController.isTransientTaskbar(activityContext)) {
@@ -285,7 +290,7 @@
*/
private fun TaskbarEduTooltip.showDisclosureText(
textView: TextView,
- stringId: Int = R.string.taskbar_edu_circle_to_search_disclosure,
+ stringId: Int = R.string.taskbar_edu_search_disclosure,
) {
val locale = resources.configuration.locales[0]
val text =
@@ -395,6 +400,17 @@
pw?.println("$prefix\tisOpen=$isOpen")
pw?.println("$prefix\ttooltipStep=$tooltipStep")
}
+
+ companion object {
+ @JvmStatic
+ fun newInstance(context: Context): TaskbarEduTooltipController {
+ return ResourceBasedOverride.Overrides.getObject(
+ TaskbarEduTooltipController::class.java,
+ context,
+ R.string.taskbar_edu_tooltip_controller_class
+ )
+ }
+ }
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 6163dad..95c4e25 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -153,6 +153,16 @@
context.deviceProfile.widthPx,
windowLayoutParams.height
)
+
+ // if there's an animating bubble add it to the touch region so that it's clickable
+ val animatingBubbleBounds =
+ controllers.bubbleControllers
+ .getOrNull()
+ ?.bubbleBarViewController
+ ?.animatingBubbleBounds
+ if (animatingBubbleBounds != null) {
+ defaultTouchableRegion.op(animatingBubbleBounds, Region.Op.UNION)
+ }
}
// Pre-calculate insets for different providers across different rotations for this gravity
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index e47640b..3196bfb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -62,6 +62,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks;
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
@@ -70,7 +71,6 @@
import com.android.quickstep.AllAppsActionManager;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.AssistUtils;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
@@ -209,15 +209,18 @@
@SuppressLint("WrongConstant")
public TaskbarManager(
- TouchInteractionService service, AllAppsActionManager allAppsActionManager) {
+ Context context,
+ AllAppsActionManager allAppsActionManager,
+ TaskbarNavButtonCallbacks navCallbacks) {
+
Display display =
- service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
- mContext = service.createWindowContext(display,
+ context.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
+ mContext = context.createWindowContext(display,
ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL,
null);
mAllAppsActionManager = allAppsActionManager;
mNavigationBarPanelContext = ENABLE_TASKBAR_NAVBAR_UNIFICATION
- ? service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null)
+ ? context.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null)
: null;
if (enableTaskbarNoRecreate()) {
mWindowManager = mContext.getSystemService(WindowManager.class);
@@ -234,8 +237,11 @@
}
};
}
- mNavButtonController = new TaskbarNavButtonController(service,
- SystemUiProxy.INSTANCE.get(mContext), new Handler(),
+ mNavButtonController = new TaskbarNavButtonController(
+ context,
+ navCallbacks,
+ SystemUiProxy.INSTANCE.get(mContext),
+ new Handler(),
AssistUtils.newInstance(mContext));
mComponentCallbacks = new ComponentCallbacks() {
private Configuration mOldConfig = mContext.getResources().getConfiguration();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 03f55ca..ade4649 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -31,6 +31,7 @@
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
@@ -47,10 +48,8 @@
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.quickstep.LauncherActivityInterface;
-import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
-import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.AssistUtils;
import java.io.PrintWriter;
@@ -106,7 +105,8 @@
private static final int SCREEN_UNPIN_COMBO = BUTTON_BACK | BUTTON_RECENTS;
private int mLongPressedButtons = 0;
- private final TouchInteractionService mService;
+ private final Context mContext;
+ private final TaskbarNavButtonCallbacks mCallbacks;
private final SystemUiProxy mSystemUiProxy;
private final Handler mHandler;
private final AssistUtils mAssistUtils;
@@ -114,9 +114,14 @@
private final Runnable mResetLongPress = this::resetScreenUnpin;
- public TaskbarNavButtonController(TouchInteractionService service,
- SystemUiProxy systemUiProxy, Handler handler, AssistUtils assistUtils) {
- mService = service;
+ public TaskbarNavButtonController(
+ Context context,
+ TaskbarNavButtonCallbacks callbacks,
+ SystemUiProxy systemUiProxy,
+ Handler handler,
+ AssistUtils assistUtils) {
+ mContext = context;
+ mCallbacks = callbacks;
mSystemUiProxy = systemUiProxy;
mHandler = handler;
mAssistUtils = assistUtils;
@@ -286,7 +291,7 @@
desktopVisibilityController.onHomeActionTriggered();
}
- mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
+ mCallbacks.onNavigateHome();
}
private void navigateToOverview() {
@@ -295,7 +300,7 @@
}
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle");
TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
- mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_TOGGLE);
+ mCallbacks.onToggleOverview();
}
private void executeBack() {
@@ -310,7 +315,7 @@
if (longClick) {
mSystemUiProxy.notifyAccessibilityButtonLongClicked();
} else {
- mSystemUiProxy.notifyAccessibilityButtonClicked(mService.getDisplayId());
+ mSystemUiProxy.notifyAccessibilityButtonClicked(mContext.getDisplayId());
}
}
@@ -333,4 +338,13 @@
private void showNotifications() {
mSystemUiProxy.toggleNotificationPanel();
}
+
+ /** Callbacks for navigation buttons on Taskbar. */
+ public interface TaskbarNavButtonCallbacks {
+ /** Callback invoked when the home button is pressed. */
+ default void onNavigateHome() {}
+
+ /** Callback invoked when the overview button is pressed. */
+ default void onToggleOverview() {}
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 110c30f..5234936 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -104,6 +104,8 @@
* updates the bounds and accounts for translation.
*/
private final Rect mBubbleBarBounds = new Rect();
+ /** The bounds of the animating bubble in the coordinate space of the BubbleBarView. */
+ private final Rect mAnimatingBubbleBounds = new Rect();
// The amount the bubbles overlap when they are stacked in the bubble bar
private final float mIconOverlapAmount;
// The spacing between the bubbles when bubble bar is expanded
@@ -120,6 +122,7 @@
// Whether the bar is expanded (i.e. the bubble activity is being displayed).
private boolean mIsBarExpanded = false;
// The currently selected bubble view.
+ @Nullable
private BubbleView mSelectedBubbleView;
private BubbleBarLocation mBubbleBarLocation = BubbleBarLocation.DEFAULT;
// The click listener when the bubble bar is collapsed.
@@ -205,6 +208,7 @@
// If the bar was just collapsed and the overflow was the last bubble that was
// selected, set the first bubble as selected.
if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null
+ && mSelectedBubbleView != null
&& mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) {
BubbleView firstBubble = (BubbleView) getChildAt(0);
mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey());
@@ -458,6 +462,30 @@
return mBubbleBarBounds;
}
+ /** Returns the bounds of the animating bubble, or {@code null} if no bubble is animating. */
+ @Nullable
+ public Rect getAnimatingBubbleBounds() {
+ if (mIsAnimatingNewBubble) {
+ return mAnimatingBubbleBounds;
+ }
+ return null;
+ }
+
+ /**
+ * Updates the animating bubble bounds. This should be called when the bubble is fully animated
+ * in so that we can include it in taskbar touchable region.
+ *
+ * <p>The bounds are adjusted to the coordinate space of BubbleBarView so that it can be used
+ * by taskbar.
+ */
+ public void updateAnimatingBubbleBounds(int left, int top, int width, int height) {
+ Rect bubbleBarBounds = getBubbleBarBounds();
+ mAnimatingBubbleBounds.left = bubbleBarBounds.left + left;
+ mAnimatingBubbleBounds.top = bubbleBarBounds.top + top;
+ mAnimatingBubbleBounds.right = mAnimatingBubbleBounds.left + width;
+ mAnimatingBubbleBounds.bottom = mAnimatingBubbleBounds.top + height;
+ }
+
/**
* Set bubble bar relative pivot value for X and Y, applied as a fraction of view width/height
* respectively. If the value is not in range of 0 to 1 it will be normalized.
@@ -534,6 +562,10 @@
@Override
public void removeView(View view) {
super.removeView(view);
+ if (view == mSelectedBubbleView) {
+ mSelectedBubbleView = null;
+ mBubbleBarBackground.showArrow(false);
+ }
updateWidth();
}
@@ -575,6 +607,8 @@
final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
final boolean animate = getVisibility() == VISIBLE;
final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
+ // elevation state is opposite to widthState - when expanded all icons are flat
+ float elevationState = (1 - widthState);
for (int i = 0; i < bubbleCount; i++) {
BubbleView bv = (BubbleView) getChildAt(i);
bv.setTranslationY(ty);
@@ -593,17 +627,20 @@
expandedX = i * (mIconSize + mExpandedBarIconsSpacing);
collapsedX = i == 0 ? 0 : mIconOverlapAmount;
}
-
+ if (bv == mDraggedBubbleView) {
+ // if bubble is dragged set the elevation to bubble drag elevation
+ bv.setZ(mDragElevation);
+ } else {
+ // otherwise slowly animate elevation while keeping correct Z ordering
+ float fullElevationForChild = (MAX_BUBBLES * mBubbleElevation) - i;
+ bv.setZ(fullElevationForChild * elevationState);
+ }
if (mIsBarExpanded) {
// If bar is on the right, account for bubble bar expanding and shifting left
final float expandedBarShift = onLeft ? 0 : currentWidth - expandedWidth;
// where the bubble will end up when the animation ends
final float targetX = expandedX + expandedBarShift;
bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
- // if we're fully expanded, set the z level to 0 or to bubble elevation if dragged
- if (widthState == 1f) {
- bv.setZ(bv == mDraggedBubbleView ? mBubbleElevation : 0);
- }
// When we're expanded, we're not stacked so we're not behind the stack
bv.setBehindStack(false, animate);
bv.setAlpha(1);
@@ -612,7 +649,6 @@
final float collapsedBarShift = onLeft ? 0 : currentWidth - collapsedWidth;
final float targetX = collapsedX + collapsedBarShift;
bv.setTranslationX(widthState * (expandedX - targetX) + targetX);
- bv.setZ((MAX_BUBBLES * mBubbleElevation) - i);
// If we're not the first bubble we're behind the stack
bv.setBehindStack(i > 0, animate);
// If we're fully collapsed, hide all bubbles except for the first 2. If there are
@@ -689,8 +725,12 @@
* Sets which bubble view should be shown as selected.
*/
public void setSelectedBubble(BubbleView view) {
+ BubbleView previouslySelectedBubble = mSelectedBubbleView;
mSelectedBubbleView = view;
- updateArrowForSelected(/* shouldAnimate= */ true);
+ mBubbleBarBackground.showArrow(view != null);
+ // TODO: (b/283309949) remove animation should be implemented first, so than arrow
+ // animation is adjusted, skip animation for now
+ updateArrowForSelected(previouslySelectedBubble != null);
}
/**
@@ -715,6 +755,10 @@
// Find the center of the bubble when it's expanded, set the arrow position to it.
final float tx = arrowPositionForSelectedWhenExpanded();
final float currentArrowPosition = mBubbleBarBackground.getArrowPositionX();
+ if (tx == currentArrowPosition) {
+ // arrow position remains unchanged
+ return;
+ }
if (shouldAnimate && currentArrowPosition > expandedWidth()) {
Log.d(TAG, "arrow out of bounds of expanded view, skip animation");
shouldAnimate = false;
@@ -838,10 +882,15 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (!mIsBarExpanded) {
+ if (!mIsBarExpanded && !mIsAnimatingNewBubble) {
// When the bar is collapsed, all taps on it should expand it.
return true;
}
return super.onInterceptTouchEvent(ev);
}
+
+ /** Whether a new bubble is currently animating. */
+ public boolean isAnimatingNewBubble() {
+ return mIsAnimatingNewBubble;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 0e62eaf..3c46f32 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -138,6 +138,15 @@
if (bubble == null) {
Log.e(TAG, "bubble click listener, bubble was null");
}
+
+ if (mBarView.isAnimatingNewBubble()) {
+ mBubbleBarViewAnimator.onBubbleClickedWhileAnimating();
+ mBubbleStashController.showBubbleBarImmediate();
+ setExpanded(true);
+ mBubbleBarController.showAndSelectBubble(bubble);
+ return;
+ }
+
final String currentlySelected = mBubbleBarController.getSelectedBubbleKey();
if (mBarView.isExpanded() && Objects.equals(bubble.getKey(), currentlySelected)) {
// Tapping the currently selected bubble while expanded collapses the view.
@@ -213,6 +222,12 @@
return mBarView.getBubbleBarBounds();
}
+ /** The bounds of the animating bubble, or {@code null} if no bubble is animating. */
+ @Nullable
+ public Rect getAnimatingBubbleBounds() {
+ return mBarView.getAnimatingBubbleBounds();
+ }
+
/** The horizontal margin of the bubble bar from the edge of the screen. */
public int getHorizontalMargin() {
return mBarView.getHorizontalMargin();
@@ -373,7 +388,7 @@
boolean isInApp = mTaskbarStashController.isInApp();
// only animate the new bubble if we're in an app and not auto expanding
- if (b instanceof BubbleBarBubble && isInApp && !isExpanding) {
+ if (b instanceof BubbleBarBubble && isInApp && !isExpanding && !isExpanded()) {
mBubbleBarViewAnimator.animateBubbleInForStashed((BubbleBarBubble) b);
}
} else {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 76d86de..bea0af8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -347,7 +347,7 @@
hotseatCellHeight - mUnstashedHeight) / 2;
}
- float getBubbleBarTranslationY() {
+ public float getBubbleBarTranslationY() {
// If we're on home, adjust the translation so the bubble bar aligns with hotseat.
// Otherwise we're either showing in an app or in overview. In either case adjust it so
// the bubble bar aligns with the taskbar.
@@ -374,4 +374,19 @@
public PhysicsAnimator<View> getStashedHandlePhysicsAnimator() {
return mHandleViewController.getPhysicsAnimator();
}
+
+ /** Notifies taskbar that it should update its touchable region. */
+ public void updateTaskbarTouchRegion() {
+ mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+ }
+
+ /** Shows the bubble bar immediately without animation. */
+ public void showBubbleBarImmediate() {
+ mHandleViewController.setTranslationYForSwipe(0);
+ mIconTranslationYForStash.updateValue(getBubbleBarTranslationY());
+ mIconAlphaForStash.setValue(1);
+ mIconScaleForStash.updateValue(1);
+ mIsStashed = false;
+ onIsStashedChanged();
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
index 2d8983f..da36944 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -35,6 +35,8 @@
private val scheduler: Scheduler = HandlerScheduler(bubbleBarView)
) {
+ private var animatingBubble: AnimatingBubble? = null
+
private companion object {
/** The time to show the flyout. */
const val FLYOUT_DELAY_MS: Long = 2500
@@ -54,26 +56,40 @@
const val BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y = -20f
}
+ /** Wrapper around the animating bubble with its show and hide animations. */
+ private data class AnimatingBubble(
+ val bubbleView: BubbleView,
+ val showAnimation: Runnable,
+ val hideAnimation: Runnable
+ )
+
/** An interface for scheduling jobs. */
interface Scheduler {
/** Schedule the given [block] to run. */
- fun post(block: () -> Unit)
+ fun post(block: Runnable)
/** Schedule the given [block] to start with a delay of [delayMillis]. */
- fun postDelayed(delayMillis: Long, block: () -> Unit)
+ fun postDelayed(delayMillis: Long, block: Runnable)
+
+ /** Cancel the given [block] if it hasn't started yet. */
+ fun cancel(block: Runnable)
}
/** A [Scheduler] that uses a Handler to run jobs. */
private class HandlerScheduler(private val view: View) : Scheduler {
- override fun post(block: () -> Unit) {
+ override fun post(block: Runnable) {
view.post(block)
}
- override fun postDelayed(delayMillis: Long, block: () -> Unit) {
+ override fun postDelayed(delayMillis: Long, block: Runnable) {
view.postDelayed(block, delayMillis)
}
+
+ override fun cancel(block: Runnable) {
+ view.removeCallbacks(block)
+ }
}
private val springConfig =
@@ -91,6 +107,7 @@
// and the second part hides it after a delay.
val showAnimation = buildShowAnimation(bubbleView, b.key)
val hideAnimation = buildHideAnimation(bubbleView)
+ animatingBubble = AnimatingBubble(bubbleView, showAnimation, hideAnimation)
scheduler.post(showAnimation)
scheduler.postDelayed(FLYOUT_DELAY_MS, hideAnimation)
}
@@ -113,7 +130,7 @@
private fun buildShowAnimation(
bubbleView: BubbleView,
key: String,
- ): () -> Unit = {
+ ) = Runnable {
bubbleBarView.prepareForAnimatingBubbleWhileStashed(key)
// calculate the initial translation x the bubble should have in order to align it with the
// stash handle.
@@ -140,7 +157,7 @@
// map the path [0, BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y] to [0,1]
val fraction = ty / BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
- target.alpha = 1 - fraction / 2
+ target.alpha = 1 - fraction
}
ty >= totalTranslationY -> {
// this is the second leg of the animation. the handle should be completely
@@ -173,6 +190,16 @@
}
}
}
+ animator.addEndListener { _, _, _, _, _, _, _ ->
+ // the bubble is now fully settled in. make it touchable
+ bubbleBarView.updateAnimatingBubbleBounds(
+ bubbleView.left,
+ bubbleView.top,
+ bubbleView.width,
+ bubbleView.height
+ )
+ bubbleStashController.updateTaskbarTouchRegion()
+ }
animator.start()
}
@@ -189,7 +216,7 @@
* 1. In the second part the bubble is fully hidden and the handle animates in.
* 1. The third part is the overshoot. The handle is made fully visible.
*/
- private fun buildHideAnimation(bubbleView: BubbleView): () -> Unit = {
+ private fun buildHideAnimation(bubbleView: BubbleView) = Runnable {
// this is the total distance that both the stashed handle and the bubble will be traveling
val totalTranslationY =
BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y + BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
@@ -230,6 +257,7 @@
}
}
animator.addEndListener { _, _, _, _, _, _, _ ->
+ animatingBubble = null
bubbleView.alpha = 0f
bubbleView.translationY = 0f
bubbleView.scaleY = 1f
@@ -237,9 +265,18 @@
bubbleBarView.alpha = 0f
}
bubbleBarView.onAnimatingBubbleCompleted()
+ bubbleStashController.updateTaskbarTouchRegion()
}
animator.start()
}
+
+ /** Handles clicking on the animating bubble while the animation is still playing. */
+ fun onBubbleClickedWhileAnimating() {
+ val hideAnimation = animatingBubble?.hideAnimation ?: return
+ scheduler.cancel(hideAnimation)
+ bubbleBarView.onAnimatingBubbleCompleted()
+ animatingBubble = null
+ }
}
/** The X position in screen coordinates of the center of the bubble. */
diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
index f26d594..aab6aa1 100644
--- a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
+++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
@@ -73,7 +73,7 @@
)
}
- override fun showForSplitscreen() = true
+ override fun showForGroupedTask() = true
}
}
}
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index 79b09fd..225b127 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -220,6 +220,11 @@
}
});
}
+
+ @Override
+ public void setTriggerBack(boolean triggerBack) {
+ // TODO(b/261654570): track touch from the Launcher process.
+ }
}
private static class RemoteAnimationRunnerStub extends IRemoteAnimationRunner.Stub {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index ab9840f..b0b2589 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -460,10 +460,11 @@
}
@Override
- public void setOverrideHomeButtonLongPress(long duration, float slopMultiplier) {
+ public void setOverrideHomeButtonLongPress(long duration, float slopMultiplier,
+ boolean haptic) {
if (mSystemUiProxy != null) {
try {
- mSystemUiProxy.setOverrideHomeButtonLongPress(duration, slopMultiplier);
+ mSystemUiProxy.setOverrideHomeButtonLongPress(duration, slopMultiplier, haptic);
} catch (RemoteException e) {
Log.w(TAG, "Failed call setOverrideHomeButtonLongPress", e);
}
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 18b8e3e..d32c7a6 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -16,8 +16,6 @@
package com.android.quickstep;
-import static android.view.Surface.ROTATION_0;
-
import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
@@ -33,7 +31,6 @@
import androidx.annotation.RequiresApi;
import com.android.launcher3.BaseActivity;
-import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -42,11 +39,12 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.Snackbar;
import com.android.quickstep.util.RecentsOrientedState;
+import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
-import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
@@ -65,9 +63,11 @@
final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
final RecentsViewContainer container =
RecentsViewContainer.containerFromContext(taskView.getContext());
- boolean hasMultipleTasks = taskView.getTaskIds()[1] != -1;
for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
- if (hasMultipleTasks && !menuOption.showForSplitscreen()) {
+ if (taskView instanceof GroupedTaskView && !menuOption.showForGroupedTask()) {
+ continue;
+ }
+ if (taskView instanceof DesktopTaskView && !menuOption.showForDesktopTask()) {
continue;
}
@@ -77,37 +77,10 @@
}
shortcuts.addAll(menuShortcuts);
}
- RecentsOrientedState orientedState = taskView.getRecentsView().getPagedViewOrientedState();
- boolean canLauncherRotate = orientedState.isRecentsActivityRotationAllowed();
- boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0;
- boolean isTablet = container.getDeviceProfile().isTablet;
-
- boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
- // Add overview actions to the menu when:
- // - single task is showing
- // - in in-place rotate landscape mode, or in grid-only overview.
- if (!hasMultipleTasks && ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview)) {
- // Add screenshot action to task menu.
- List<SystemShortcut> screenshotShortcuts = TaskShortcutFactory.SCREENSHOT
- .getShortcuts(container, taskContainer);
- if (screenshotShortcuts != null) {
- shortcuts.addAll(screenshotShortcuts);
- }
-
- // Add modal action only if display orientation is the same as the device orientation,
- // or in grid-only overview.
- if (orientedState.getDisplayRotation() == ROTATION_0 || isGridOnlyOverview) {
- List<SystemShortcut> modalShortcuts = TaskShortcutFactory.MODAL
- .getShortcuts(container, taskContainer);
- if (modalShortcuts != null) {
- shortcuts.addAll(modalShortcuts);
- }
- }
- }
return shortcuts;
}
- public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) {
+ public TaskOverlay createOverlay(TaskThumbnailViewDeprecated thumbnailView) {
return new TaskOverlay(thumbnailView);
}
@@ -140,7 +113,9 @@
TaskShortcutFactory.FREE_FORM,
DesktopSystemShortcut.Companion.createFactory(),
TaskShortcutFactory.WELLBEING,
- TaskShortcutFactory.SAVE_APP_PAIR
+ TaskShortcutFactory.SAVE_APP_PAIR,
+ TaskShortcutFactory.SCREENSHOT,
+ TaskShortcutFactory.MODAL
};
/**
@@ -149,14 +124,14 @@
public static class TaskOverlay<T extends OverviewActionsView> {
protected final Context mApplicationContext;
- protected final TaskThumbnailView mThumbnailView;
+ protected final TaskThumbnailViewDeprecated mThumbnailView;
private T mActionsView;
protected ImageActionsApi mImageApi;
- protected TaskOverlay(TaskThumbnailView taskThumbnailView) {
- mApplicationContext = taskThumbnailView.getContext().getApplicationContext();
- mThumbnailView = taskThumbnailView;
+ protected TaskOverlay(TaskThumbnailViewDeprecated taskThumbnailViewDeprecated) {
+ mApplicationContext = taskThumbnailViewDeprecated.getContext().getApplicationContext();
+ mThumbnailView = taskThumbnailViewDeprecated;
mImageApi = new ImageActionsApi(
mApplicationContext, mThumbnailView::getThumbnail);
}
@@ -169,7 +144,7 @@
return mActionsView;
}
- public TaskThumbnailView getThumbnailView() {
+ public TaskThumbnailViewDeprecated getThumbnailView() {
return mThumbnailView;
}
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 9d10ac1..8df4bdd 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
import static com.android.window.flags.Flags.enableDesktopWindowingMode;
@@ -39,6 +40,7 @@
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
@@ -50,10 +52,11 @@
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
-import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
import com.android.systemui.shared.recents.model.Task;
@@ -79,7 +82,17 @@
return null;
}
- default boolean showForSplitscreen() {
+ /**
+ * Returns {@code true} if it should be shown for grouped task; {@code false} otherwise.
+ */
+ default boolean showForGroupedTask() {
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if it should be shown for desktop task; {@code false} otherwise.
+ */
+ default boolean showForDesktopTask() {
return false;
}
@@ -107,7 +120,7 @@
}
@Override
- public boolean showForSplitscreen() {
+ public boolean showForGroupedTask() {
return true;
}
};
@@ -158,7 +171,7 @@
private Handler mHandler;
private final RecentsView mRecentsView;
- private final TaskThumbnailView mThumbnailView;
+ private final TaskThumbnailViewDeprecated mThumbnailView;
private final TaskView mTaskView;
private final LauncherEvent mLauncherEvent;
@@ -354,7 +367,7 @@
}
@Override
- public boolean showForSplitscreen() {
+ public boolean showForGroupedTask() {
return true;
}
};
@@ -456,18 +469,53 @@
@Override
public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
TaskIdAttributeContainer taskContainer) {
+ boolean isTablet = container.getDeviceProfile().isTablet;
+ boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
+ // Extra conditions if it's not grid-only overview
+ if (!isGridOnlyOverview) {
+ RecentsOrientedState orientedState =
+ taskContainer.getTaskView().getRecentsView().getPagedViewOrientedState();
+ boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
+ && orientedState.getTouchRotation() != ROTATION_0;
+ if (!isFakeLandscape) {
+ return null;
+ }
+ }
+
SystemShortcut screenshotShortcut =
taskContainer.getThumbnailView().getTaskOverlay()
.getScreenshotShortcut(container, taskContainer.getItemInfo(),
taskContainer.getTaskView());
return createSingletonShortcutList(screenshotShortcut);
}
+
+ @Override
+ public boolean showForDesktopTask() {
+ return true;
+ }
};
TaskShortcutFactory MODAL = new TaskShortcutFactory() {
@Override
public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
TaskIdAttributeContainer taskContainer) {
+ boolean isTablet = container.getDeviceProfile().isTablet;
+ boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
+ // Extra conditions if it's not grid-only overview
+ if (!isGridOnlyOverview) {
+ RecentsOrientedState orientedState =
+ taskContainer.getTaskView().getRecentsView().getPagedViewOrientedState();
+ boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
+ && orientedState.getTouchRotation() != ROTATION_0;
+ if (!isFakeLandscape) {
+ return null;
+ }
+ // Disallow "Select" when swiping up from landscape due to rotated thumbnail.
+ if (orientedState.getDisplayRotation() != ROTATION_0) {
+ return null;
+ }
+ }
+
SystemShortcut modalStateSystemShortcut =
taskContainer.getThumbnailView().getTaskOverlay()
.getModalStateSystemShortcut(
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 450e960..d89d399 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -80,7 +80,7 @@
import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.TaskThumbnailView;
+import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.quickstep.views.TaskView;
import com.android.systemui.animation.RemoteAnimationTargetCompat;
import com.android.systemui.shared.recents.model.Task;
@@ -334,7 +334,7 @@
// During animation we apply transformation on the thumbnailView (and not the rootView)
// to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
// Mt K(0)` K(t) Mt`
- TaskThumbnailView[] thumbnails = v.getThumbnails();
+ TaskThumbnailViewDeprecated[] thumbnails = v.getThumbnails();
// In case simulator copies and thumbnail size do no match, ensure we get the lesser.
// This ensures we do not create arrays with empty elements or attempt to references
@@ -344,7 +344,7 @@
Matrix[] mt = new Matrix[matrixSize];
Matrix[] mti = new Matrix[matrixSize];
for (int i = 0; i < matrixSize; i++) {
- TaskThumbnailView ttv = thumbnails[i];
+ TaskThumbnailViewDeprecated ttv = thumbnails[i];
RectF localBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
float[] tvBoundsMapped = new float[]{0, 0, ttv.getWidth(), ttv.getHeight()};
getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
@@ -391,7 +391,7 @@
out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- for (TaskThumbnailView ttv : thumbnails) {
+ for (TaskThumbnailViewDeprecated ttv : thumbnails) {
ttv.setAnimationMatrix(null);
}
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index a842b51..832f4e1 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -94,6 +94,7 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarManager;
+import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -470,6 +471,18 @@
private final ScreenOnTracker.ScreenOnListener mScreenOnListener = this::onScreenOnChanged;
+ private final TaskbarNavButtonCallbacks mNavCallbacks = new TaskbarNavButtonCallbacks() {
+ @Override
+ public void onNavigateHome() {
+ mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_HOME);
+ }
+
+ @Override
+ public void onToggleOverview() {
+ mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_TOGGLE);
+ }
+ };
+
private ActivityManagerWrapper mAM;
private OverviewCommandHelper mOverviewCommandHelper;
private OverviewComponentObserver mOverviewComponentObserver;
@@ -500,7 +513,7 @@
mDeviceState = new RecentsAnimationDeviceState(this, true);
mAllAppsActionManager = new AllAppsActionManager(
this, UI_HELPER_EXECUTOR, this::createAllAppsPendingIntent);
- mTaskbarManager = new TaskbarManager(this, mAllAppsActionManager);
+ mTaskbarManager = new TaskbarManager(this, mAllAppsActionManager, mNavCallbacks);
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
new file mode 100644
index 0000000..0843ae3
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailUiState.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import com.android.systemui.shared.recents.model.Task
+
+sealed class TaskThumbnailUiState {
+ data object Uninitialized : TaskThumbnailUiState()
+ data object LiveTile : TaskThumbnailUiState()
+}
+
+data class TaskThumbnail(val task: Task, val isRunning: Boolean)
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
new file mode 100644
index 0000000..d51069f
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffXfermode
+import android.util.AttributeSet
+import android.view.View
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.*
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.launch
+
+class TaskThumbnailView : View {
+ // TODO(b/335649589): Ideally create and obtain this from DI. This ViewModel should be scoped
+ // to [TaskView], and also shared between [TaskView] and [TaskThumbnailView]
+ val viewModel = TaskThumbnailViewModel()
+
+ private var uiState: TaskThumbnailUiState = Uninitialized
+
+ constructor(context: Context?) : super(context)
+ constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
+ constructor(
+ context: Context?,
+ attrs: AttributeSet?,
+ defStyleAttr: Int,
+ ) : super(context, attrs, defStyleAttr)
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ // TODO(b/335396935) replace MainScope with shorter lifecycle.
+ MainScope().launch {
+ viewModel.uiState.collect { viewModelUiState ->
+ uiState = viewModelUiState
+ invalidate()
+ }
+ }
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ when (uiState) {
+ is Uninitialized -> {}
+ is LiveTile -> drawTransparentUiState(canvas)
+ }
+ }
+
+ private fun drawTransparentUiState(canvas: Canvas) {
+ canvas.drawRoundRect(
+ 0f,
+ 0f,
+ measuredWidth.toFloat(),
+ measuredHeight.toFloat(),
+ // TODO(b/334826840) add rounded corners
+ 0f,
+ 0f,
+ CLEAR_PAINT
+ )
+ }
+
+ companion object {
+ private val CLEAR_PAINT =
+ Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
new file mode 100644
index 0000000..9925873
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class TaskThumbnailViewModel {
+ private val _uiState: MutableStateFlow<TaskThumbnailUiState> =
+ MutableStateFlow(TaskThumbnailUiState.Uninitialized)
+ val uiState: StateFlow<TaskThumbnailUiState> = _uiState
+
+ fun bind(task: TaskThumbnail) {
+ _uiState.value =
+ if (task.isRunning) {
+ TaskThumbnailUiState.LiveTile
+ } else {
+ TaskThumbnailUiState.Uninitialized
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
index 4a35c3b..42db65f 100644
--- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java
+++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
@@ -33,11 +33,6 @@
public AssistStateManager() {}
- /** Whether search supports haptic on invocation. */
- public boolean supportsCommitHaptic() {
- return false;
- }
-
/** Whether search is available. */
public boolean isSearchAvailable() {
return false;
@@ -90,6 +85,11 @@
return 0;
}
+ /** Get the haptic bit overridden by AGSA. */
+ public Optional<Boolean> getShouldPlayHapticOverride() {
+ return Optional.empty();
+ }
+
/** Return {@code true} if the Settings toggle is enabled. */
public boolean isSettingsAllEntrypointsEnabled() {
return false;
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index 9df568e..2a27dea 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -136,21 +136,16 @@
});
}
- if (!ALL_APPS_VISITED_COUNT.hasReachedMax(launcher)) {
+ if (!Utilities.isRunningInTestHarness()) {
launcher.getStateManager().addStateListener(new StateListener<LauncherState>() {
@Override
public void onStateTransitionComplete(LauncherState finalState) {
if (finalState == ALL_APPS) {
ALL_APPS_VISITED_COUNT.increment(launcher);
- return;
}
-
- boolean hasReachedMaxCount = ALL_APPS_VISITED_COUNT.hasReachedMax(launcher);
- launcher.getAppsView().getFloatingHeaderView().findFixedRowByType(
- AppsDividerView.class).setShowAllAppsLabel(!hasReachedMaxCount);
- if (hasReachedMaxCount) {
- launcher.getStateManager().removeStateListener(this);
- }
+ launcher.getAppsView().getFloatingHeaderView()
+ .findFixedRowByType(AppsDividerView.class)
+ .setShowAllAppsLabel(!ALL_APPS_VISITED_COUNT.hasReachedMax(launcher));
}
});
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index 021c455..f430d79 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -65,7 +65,7 @@
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.SplitInstructionsView
-import com.android.quickstep.views.TaskThumbnailView
+import com.android.quickstep.views.TaskThumbnailViewDeprecated
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
import com.android.quickstep.views.TaskViewIcon
@@ -160,9 +160,9 @@
/**
* When selecting first app from split pair, second app's thumbnail remains. This animates the
* second thumbnail by expanding it to take up the full taskViewWidth/Height and overlaying it
- * with [TaskThumbnailView]'s splashView. Adds animations to the provided builder. Note: The app
- * that **was not** selected as the first split app should be the container that's passed
- * through.
+ * with [TaskThumbnailViewDeprecated]'s splashView. Adds animations to the provided builder.
+ * Note: The app that **was not** selected as the first split app should be the container that's
+ * passed through.
*
* @param builder Adds animation to this
* @param taskIdAttributeContainer container of the app that **was not** selected
@@ -179,7 +179,7 @@
) {
val thumbnail = taskIdAttributeContainer.thumbnailView
val iconView: View = taskIdAttributeContainer.iconView.asView()
- builder.add(ObjectAnimator.ofFloat(thumbnail, TaskThumbnailView.SPLASH_ALPHA, 1f))
+ builder.add(ObjectAnimator.ofFloat(thumbnail, TaskThumbnailViewDeprecated.SPLASH_ALPHA, 1f))
thumbnail.setShowSplashForSplitSelection(true)
// With the new `IconAppChipView`, we always want to keep the chip pinned to the
// top left of the task / thumbnail.
@@ -202,7 +202,7 @@
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
- TaskThumbnailView.SPLIT_SELECT_TRANSLATE_X,
+ TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_X,
centerThumbnailTranslationX
)
)
@@ -224,7 +224,7 @@
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
- TaskThumbnailView.SPLIT_SELECT_TRANSLATE_Y,
+ TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_Y,
translateYResetVal
)
)
@@ -252,7 +252,7 @@
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
- TaskThumbnailView.SPLIT_SELECT_TRANSLATE_Y,
+ TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_Y,
centerThumbnailTranslationY
)
)
@@ -266,7 +266,11 @@
// Reset other dimensions
thumbnail.scaleX = 1f
builder.add(
- ObjectAnimator.ofFloat(thumbnail, TaskThumbnailView.SPLIT_SELECT_TRANSLATE_X, 0f)
+ ObjectAnimator.ofFloat(
+ thumbnail,
+ TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_X,
+ 0f
+ )
)
}
}
@@ -276,43 +280,59 @@
* [pendingAnimation]. Assumes that animation will be the final split placeholder launch anim.
*
* [secondPlaceholderEndingBounds] refers to the second placeholder view that gets added on
- * screen, not the logical second app.
- * For landscape it's the left app and for portrait the top one.
+ * screen, not the logical second app. For landscape it's the left app and for portrait the top
+ * one.
*/
- fun addDividerPlaceholderViewToAnim(pendingAnimation: PendingAnimation,
- container: RecentsViewContainer,
- secondPlaceholderEndingBounds: Rect,
- context: Context) : View {
+ fun addDividerPlaceholderViewToAnim(
+ pendingAnimation: PendingAnimation,
+ container: RecentsViewContainer,
+ secondPlaceholderEndingBounds: Rect,
+ context: Context
+ ): View {
val mSplitDividerPlaceholderView = View(context)
val recentsView = container.getOverviewPanel<RecentsView<*, *>>()
- val dp : com.android.launcher3.DeviceProfile = container.getDeviceProfile()
+ val dp: com.android.launcher3.DeviceProfile = container.getDeviceProfile()
// Add it before/under the most recently added first floating taskView
- val firstAddedSplitViewIndex: Int = container.getDragLayer().indexOfChild(
- recentsView.splitSelectController.firstFloatingTaskView)
+ val firstAddedSplitViewIndex: Int =
+ container
+ .getDragLayer()
+ .indexOfChild(recentsView.splitSelectController.firstFloatingTaskView)
container.getDragLayer().addView(mSplitDividerPlaceholderView, firstAddedSplitViewIndex)
val lp = mSplitDividerPlaceholderView.layoutParams as InsettableFrameLayout.LayoutParams
lp.topMargin = 0
if (dp.isLeftRightSplit) {
lp.height = secondPlaceholderEndingBounds.height()
- lp.width = container.asContext().resources.
- getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
- mSplitDividerPlaceholderView.translationX = secondPlaceholderEndingBounds.right - lp.width / 2f
+ lp.width =
+ container
+ .asContext()
+ .resources
+ .getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
+ mSplitDividerPlaceholderView.translationX =
+ secondPlaceholderEndingBounds.right - lp.width / 2f
mSplitDividerPlaceholderView.translationY = 0f
} else {
- lp.height = container.asContext().resources
+ lp.height =
+ container
+ .asContext()
+ .resources
.getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
lp.width = secondPlaceholderEndingBounds.width()
- mSplitDividerPlaceholderView.translationY = secondPlaceholderEndingBounds.top - lp.height / 2f
+ mSplitDividerPlaceholderView.translationY =
+ secondPlaceholderEndingBounds.top - lp.height / 2f
mSplitDividerPlaceholderView.translationX = 0f
}
mSplitDividerPlaceholderView.alpha = 0f
- mSplitDividerPlaceholderView.setBackgroundColor(container.asContext().resources
- .getColor(R.color.taskbar_background_dark))
+ mSplitDividerPlaceholderView.setBackgroundColor(
+ container.asContext().resources.getColor(R.color.taskbar_background_dark)
+ )
val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet)
- pendingAnimation.setViewAlpha(mSplitDividerPlaceholderView, 1f,
- Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f))
+ pendingAnimation.setViewAlpha(
+ mSplitDividerPlaceholderView,
+ 1f,
+ Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f)
+ )
return mSplitDividerPlaceholderView
}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 78b1763..a0ec525 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -18,11 +18,12 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
@@ -31,20 +32,18 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
-import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.desktop.DesktopRecentsTransitionController;
-import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.util.CancellableTask;
import com.android.launcher3.util.RunnableList;
+import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.util.RecentsOrientedState;
@@ -74,10 +73,10 @@
@NonNull
private List<Task> mTasks = new ArrayList<>();
- private final ArrayList<TaskThumbnailView> mSnapshotViews = new ArrayList<>();
+ private final ArrayList<TaskThumbnailViewDeprecated> mSnapshotViews = new ArrayList<>();
- /** Maps {@code taskIds} to corresponding {@link TaskThumbnailView}s */
- private final SparseArray<TaskThumbnailView> mSnapshotViewMap = new SparseArray<>();
+ /** Maps {@code taskIds} to corresponding {@link TaskThumbnailViewDeprecated}s */
+ private final SparseArray<TaskThumbnailViewDeprecated> mSnapshotViewMap = new SparseArray<>();
private final ArrayList<CancellableTask<?>> mPendingThumbnailRequests = new ArrayList<>();
@@ -87,6 +86,8 @@
private int mChildCountAtInflation;
+ private final PointF mTempPointF = new PointF();
+
public DesktopTaskView(Context context) {
this(context, null);
}
@@ -129,13 +130,12 @@
ShapeDrawable background = new ShapeDrawable(shape);
background.setTint(getResources().getColor(android.R.color.system_neutral2_300,
getContext().getTheme()));
- // TODO(b/244348395): this should be wallpaper
mBackgroundView.setBackground(background);
Drawable icon = getResources().getDrawable(R.drawable.ic_desktop, getContext().getTheme());
Drawable iconBackground = getResources().getDrawable(R.drawable.bg_circle,
getContext().getTheme());
- mIconView.setDrawable(new LayerDrawable(new Drawable[]{iconBackground, icon}));
+ setIcon(mIconView, new LayerDrawable(new Drawable[]{iconBackground, icon}));
mChildCountAtInflation = getChildCount();
}
@@ -175,13 +175,14 @@
if (mSnapshotViews.size() > mTasks.size()) {
int diff = mSnapshotViews.size() - mTasks.size();
for (int i = 0; i < diff; i++) {
- TaskThumbnailView snapshotView = mSnapshotViews.remove(0);
+ TaskThumbnailViewDeprecated snapshotView = mSnapshotViews.remove(0);
removeView(snapshotView);
}
} else if (mSnapshotViews.size() < mTasks.size()) {
int diff = mTasks.size() - mSnapshotViews.size();
for (int i = 0; i < diff; i++) {
- TaskThumbnailView snapshotView = new TaskThumbnailView(getContext());
+ TaskThumbnailViewDeprecated snapshotView =
+ new TaskThumbnailViewDeprecated(getContext());
mSnapshotViews.add(snapshotView);
// Add snapshots from to position after the initial child views.
addView(snapshotView, mChildCountAtInflation,
@@ -191,7 +192,7 @@
for (int i = 0; i < mTasks.size(); i++) {
Task task = mTasks.get(i);
- TaskThumbnailView snapshotView = mSnapshotViews.get(i);
+ TaskThumbnailViewDeprecated snapshotView = mSnapshotViews.get(i);
snapshotView.bind(task);
mSnapshotViewMap.put(task.key.id, snapshotView);
}
@@ -217,31 +218,17 @@
mTaskIdAttributeContainer = new TaskIdAttributeContainer[Math.max(mTasks.size(), 2)];
for (int i = 0; i < mTasks.size(); i++) {
Task task = mTasks.get(i);
- TaskThumbnailView thumbnailView = mSnapshotViewMap.get(task.key.id);
+ TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
mTaskIdAttributeContainer[i] = createAttributeContainer(task, thumbnailView);
}
}
private TaskIdAttributeContainer createAttributeContainer(Task task,
- TaskThumbnailView thumbnailView) {
- return new TaskIdAttributeContainer(task, thumbnailView, createIconView(task),
+ TaskThumbnailViewDeprecated thumbnailView) {
+ return new TaskIdAttributeContainer(task, thumbnailView, mIconView,
STAGE_POSITION_UNDEFINED);
}
- private IconView createIconView(Task task) {
- IconView iconView = new IconView(mContext);
- PackageManager pm = mContext.getApplicationContext().getPackageManager();
- try {
- IconProvider provider = new IconProvider(mContext);
- Drawable appIcon = provider.getIcon(pm.getActivityInfo(task.topActivity,
- PackageManager.ComponentInfoFlags.of(0)));
- iconView.setDrawable(appIcon);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Package not found: " + task.topActivity.getPackageName(), e);
- }
- return iconView;
- }
-
@Nullable
@Override
public Task getTask() {
@@ -250,14 +237,14 @@
}
@Override
- public TaskThumbnailView getThumbnail() {
+ public TaskThumbnailViewDeprecated getThumbnail() {
// TODO(b/249371338): returning single thumbnail. This won't work well with multiple tasks.
Task task = getTask();
if (task != null) {
return mSnapshotViewMap.get(task.key.id);
}
// Return the place holder snapshot views. Callers expect this to be non-null
- return mSnapshotView;
+ return mTaskThumbnailViewDeprecated;
}
@Override
@@ -277,7 +264,8 @@
for (Task task : mTasks) {
CancellableTask<?> thumbLoadRequest =
thumbnailCache.updateThumbnailInBackground(task, thumbnailData -> {
- TaskThumbnailView thumbnailView = mSnapshotViewMap.get(task.key.id);
+ TaskThumbnailViewDeprecated thumbnailView =
+ mSnapshotViewMap.get(task.key.id);
if (thumbnailView != null) {
thumbnailView.setThumbnail(task, thumbnailData);
}
@@ -290,7 +278,7 @@
} else {
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
for (Task task : mTasks) {
- TaskThumbnailView thumbnailView = mSnapshotViewMap.get(task.key.id);
+ TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
if (thumbnailView != null) {
thumbnailView.setThumbnail(null, null);
}
@@ -303,16 +291,7 @@
@Override
protected void setThumbnailOrientation(RecentsOrientedState orientationState) {
- DeviceProfile deviceProfile = mContainer.getDeviceProfile();
- int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
-
- LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
- snapshotParams.topMargin = thumbnailTopMargin;
-
- for (int i = 0; i < mSnapshotViewMap.size(); i++) {
- TaskThumbnailView thumbnailView = mSnapshotViewMap.valueAt(i);
- thumbnailView.setLayoutParams(snapshotParams);
- }
+ // no-op
}
@Override
@@ -323,16 +302,6 @@
mPendingThumbnailRequests.clear();
}
- @Override
- public boolean offerTouchToChildren(MotionEvent event) {
- return false;
- }
-
- @Override
- protected boolean showTaskMenuWithContainer(TaskViewIcon iconView) {
- return false;
- }
-
@Nullable
@Override
public RunnableList launchTaskAnimated() {
@@ -367,11 +336,11 @@
void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
// Sets new thumbnails based on the incoming data and refreshes the rest.
// Create a copy of the thumbnail map, so we can track thumbnails that need refreshing.
- SparseArray<TaskThumbnailView> thumbnailsToRefresh = mSnapshotViewMap.clone();
+ SparseArray<TaskThumbnailViewDeprecated> thumbnailsToRefresh = mSnapshotViewMap.clone();
if (thumbnailDatas != null) {
for (Task task : mTasks) {
int key = task.key.id;
- TaskThumbnailView thumbnailView = thumbnailsToRefresh.get(key);
+ TaskThumbnailViewDeprecated thumbnailView = thumbnailsToRefresh.get(key);
ThumbnailData thumbnailData = thumbnailDatas.get(key);
if (thumbnailView != null && thumbnailData != null) {
thumbnailView.setThumbnail(task, thumbnailData);
@@ -388,8 +357,9 @@
}
@Override
- public TaskThumbnailView[] getThumbnails() {
- TaskThumbnailView[] thumbnails = new TaskThumbnailView[mSnapshotViewMap.size()];
+ public TaskThumbnailViewDeprecated[] getThumbnails() {
+ TaskThumbnailViewDeprecated[] thumbnails =
+ new TaskThumbnailViewDeprecated[mSnapshotViewMap.size()];
for (int i = 0; i < thumbnails.length; i++) {
thumbnails[i] = mSnapshotViewMap.valueAt(i);
}
@@ -402,7 +372,7 @@
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
for (Task task : mTasks) {
- TaskThumbnailView thumbnailView = mSnapshotViewMap.get(task.key.id);
+ TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
if (thumbnailView != null) {
thumbnailView.setThumbnail(task, null);
}
@@ -428,8 +398,10 @@
return;
}
- int windowWidth = mContainer.getDeviceProfile().widthPx;
- int windowHeight = mContainer.getDeviceProfile().heightPx;
+ BaseContainerInterface.getTaskDimension(mContext, mContainer.getDeviceProfile(),
+ mTempPointF);
+ int windowWidth = (int) mTempPointF.x;
+ int windowHeight = (int) mTempPointF.y;
float scaleWidth = containerWidth / (float) windowWidth;
float scaleHeight = containerHeight / (float) windowHeight;
@@ -453,7 +425,7 @@
int thumbWidth = (int) (taskSize.width() * scaleWidth);
int thumbHeight = (int) (taskSize.height() * scaleHeight);
- TaskThumbnailView thumbnailView = mSnapshotViewMap.get(task.key.id);
+ TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.get(task.key.id);
if (thumbnailView != null) {
thumbnailView.measure(MeasureSpec.makeMeasureSpec(thumbWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(thumbHeight, MeasureSpec.EXACTLY));
@@ -480,7 +452,7 @@
@Override
public void setOverlayEnabled(boolean overlayEnabled) {
- // Intentional no-op to prevent setting smart actions overlay on thumbnails
+ // TODO(b/330685808) support overlay for Screenshot action
}
@Override
@@ -488,6 +460,7 @@
// TODO(b/249371338): this copies parent implementation and makes it work for N thumbs
progress = Utilities.boundToRange(progress, 0, 1);
mFullscreenProgress = progress;
+ mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
if (mFullscreenProgress > 0) {
// Don't show background while we are transitioning to/from fullscreen
mBackgroundView.setVisibility(INVISIBLE);
@@ -495,9 +468,15 @@
mBackgroundView.setVisibility(VISIBLE);
}
for (int i = 0; i < mSnapshotViewMap.size(); i++) {
- TaskThumbnailView thumbnailView = mSnapshotViewMap.valueAt(i);
+ TaskThumbnailViewDeprecated thumbnailView = mSnapshotViewMap.valueAt(i);
thumbnailView.getTaskOverlay().setFullscreenProgress(progress);
}
+ // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
+ // oversized and banner would look disproportionately large.
+ if (mContainer.<RecentsView<?, ?>>getOverviewPanel().getStateManager().getState()
+ != BACKGROUND_APP) {
+ setIconsAndBannersTransitionProgress(progress, true);
+ }
updateSnapshotRadius();
}
@@ -514,11 +493,6 @@
}
@Override
- protected void setIconsAndBannersTransitionProgress(float progress, boolean invert) {
- // no-op
- }
-
- @Override
public void setColorTint(float amount, int tintColor) {
for (int i = 0; i < mSnapshotViewMap.size(); i++) {
mSnapshotViewMap.valueAt(i).setDimAlpha(amount);
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
index d869fed..e5a7333 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
@@ -31,7 +31,7 @@
/**
* A child view of {@link com.android.quickstep.views.FloatingTaskView} to draw the thumbnail in a
* rounded corner frame. While the purpose of this class sounds similar to
- * {@link TaskThumbnailView}, it doesn't need a lot of complex logic in {@link TaskThumbnailView}
+ * {@link TaskThumbnailViewDeprecated}, it doesn't need a lot of complex logic in {@link TaskThumbnailViewDeprecated}
* in relation to moving with {@link RecentsView}.
*/
public class FloatingTaskThumbnailView extends View {
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 9e1c856..a593712 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -11,6 +11,7 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
@@ -43,6 +44,7 @@
import kotlin.Unit;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.function.Consumer;
@@ -58,9 +60,11 @@
*/
public class GroupedTaskView extends TaskView {
+ private static final String TAG = TaskView.class.getSimpleName();
@Nullable
private Task mSecondaryTask;
- private TaskThumbnailView mSnapshotView2;
+ // TODO(b/336612373): Support new TTV for GroupedTaskView
+ private TaskThumbnailViewDeprecated mSnapshotView2;
private TaskViewIcon mIconView2;
@Nullable
private CancellableTask<ThumbnailData> mThumbnailLoadRequest2;
@@ -68,7 +72,8 @@
private CancellableTask mIconLoadRequest2;
private final float[] mIcon2CenterCoords = new float[2];
private TransformingTouchDelegate mIcon2TouchDelegate;
- @Nullable private SplitBounds mSplitBoundsConfig;
+ @Nullable
+ private SplitBounds mSplitBoundsConfig;
private final DigitalWellBeingToast mDigitalWellBeingToast2;
public GroupedTaskView(Context context) {
@@ -91,13 +96,17 @@
return Unit.INSTANCE;
}
bounds.set(
- Math.min(mSnapshotView.getLeft() + Math.round(mSnapshotView.getTranslationX()),
+ Math.min(mTaskThumbnailViewDeprecated.getLeft() + Math.round(
+ mTaskThumbnailViewDeprecated.getTranslationX()),
mSnapshotView2.getLeft() + Math.round(mSnapshotView2.getTranslationX())),
- Math.min(mSnapshotView.getTop() + Math.round(mSnapshotView.getTranslationY()),
+ Math.min(mTaskThumbnailViewDeprecated.getTop() + Math.round(
+ mTaskThumbnailViewDeprecated.getTranslationY()),
mSnapshotView2.getTop() + Math.round(mSnapshotView2.getTranslationY())),
- Math.max(mSnapshotView.getRight() + Math.round(mSnapshotView.getTranslationX()),
+ Math.max(mTaskThumbnailViewDeprecated.getRight() + Math.round(
+ mTaskThumbnailViewDeprecated.getTranslationX()),
mSnapshotView2.getRight() + Math.round(mSnapshotView2.getTranslationX())),
- Math.max(mSnapshotView.getBottom() + Math.round(mSnapshotView.getTranslationY()),
+ Math.max(mTaskThumbnailViewDeprecated.getBottom() + Math.round(
+ mTaskThumbnailViewDeprecated.getTranslationY()),
mSnapshotView2.getBottom() + Math.round(mSnapshotView2.getTranslationY())));
return Unit.INSTANCE;
}
@@ -130,7 +139,7 @@
if (mSplitBoundsConfig == null) {
return;
}
- mSnapshotView.getPreviewPositionHelper().setSplitBounds(
+ mTaskThumbnailViewDeprecated.getPreviewPositionHelper().setSplitBounds(
convertLauncherSplitBoundsToShell(splitBoundsConfig),
PreviewPositionHelper.STAGE_POSITION_TOP_OR_LEFT);
mSnapshotView2.getPreviewPositionHelper().setSplitBounds(
@@ -258,7 +267,6 @@
InteractionJankMonitorWrapper.end(Cuj.CUJ_SPLIT_SCREEN_ENTER);
}, false /* freezeTaskList */, true /*launchingExistingTaskview*/);
-
// Callbacks get run from recentsView for case when recents animation already running
recentsView.addSideTaskLaunchCallback(endCallback);
return endCallback;
@@ -281,6 +289,8 @@
launchingExistingTaskView ? this : null, mTask.key.id,
mSecondaryTask.key.id, SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
callback, isQuickswitch, getSnapPosition());
+ Log.d(TAG, "launchTaskInternal - launchExistingSplitPair: " + Arrays.toString(
+ getTaskIds()));
}
@Override
@@ -304,8 +314,8 @@
}
@Override
- public TaskThumbnailView[] getThumbnails() {
- return new TaskThumbnailView[]{mSnapshotView, mSnapshotView2};
+ public TaskThumbnailViewDeprecated[] getThumbnails() {
+ return new TaskThumbnailViewDeprecated[]{mTaskThumbnailViewDeprecated, mSnapshotView2};
}
@Override
@@ -349,20 +359,24 @@
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
- if (mSplitBoundsConfig == null || mSnapshotView == null || mSnapshotView2 == null) {
+ if (mSplitBoundsConfig == null || mTaskThumbnailViewDeprecated == null
+ || mSnapshotView2 == null) {
return;
}
int initSplitTaskId = getThisTaskCurrentlyInSplitSelection();
if (initSplitTaskId == INVALID_TASK_ID) {
- getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
+ getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(
+ mTaskThumbnailViewDeprecated,
mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
mContainer.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL);
// Should we be having a separate translation step apart from the measuring above?
// The following only applies to large screen for now, but for future reference
// we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
// translation directions
- mSnapshotView.applySplitSelectTranslateX(mSnapshotView.getTranslationX());
- mSnapshotView.applySplitSelectTranslateY(mSnapshotView.getTranslationY());
+ mTaskThumbnailViewDeprecated.applySplitSelectTranslateX(
+ mTaskThumbnailViewDeprecated.getTranslationX());
+ mTaskThumbnailViewDeprecated.applySplitSelectTranslateY(
+ mTaskThumbnailViewDeprecated.getTranslationY());
mSnapshotView2.applySplitSelectTranslateX(mSnapshotView2.getTranslationX());
mSnapshotView2.applySplitSelectTranslateY(mSnapshotView2.getTranslationY());
} else {
@@ -446,8 +460,9 @@
mSplitBoundsConfig);
} else {
getPagedOrientationHandler().setSplitIconParams(mIconView.asView(), mIconView2.asView(),
- taskIconHeight, mSnapshotView.getMeasuredWidth(),
- mSnapshotView.getMeasuredHeight(), getMeasuredHeight(), getMeasuredWidth(),
+ taskIconHeight, mTaskThumbnailViewDeprecated.getMeasuredWidth(),
+ mTaskThumbnailViewDeprecated.getMeasuredHeight(), getMeasuredHeight(),
+ getMeasuredWidth(),
isRtl, deviceProfile, mSplitBoundsConfig);
}
}
@@ -510,12 +525,12 @@
@Override
void setThumbnailVisibility(int visibility, int taskId) {
if (visibility == VISIBLE) {
- mSnapshotView.setVisibility(visibility);
+ mTaskThumbnailViewDeprecated.setVisibility(visibility);
mDigitalWellBeingToast.setBannerVisibility(visibility);
mSnapshotView2.setVisibility(visibility);
mDigitalWellBeingToast2.setBannerVisibility(visibility);
} else if (taskId == getTaskIds()[0]) {
- mSnapshotView.setVisibility(visibility);
+ mTaskThumbnailViewDeprecated.setVisibility(visibility);
mDigitalWellBeingToast.setBannerVisibility(visibility);
} else {
mSnapshotView2.setVisibility(visibility);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ae6f703..5daafcf 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -130,6 +130,7 @@
import com.android.internal.jank.Cuj;
import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.PagedView;
@@ -1045,8 +1046,9 @@
continue;
}
Task task = taskAttributes.getTask();
- TaskThumbnailView taskThumbnailView = taskAttributes.getThumbnailView();
- taskThumbnailView.setThumbnail(task, thumbnail, refreshNow);
+ TaskThumbnailViewDeprecated taskThumbnailViewDeprecated =
+ taskAttributes.getThumbnailView();
+ taskThumbnailViewDeprecated.setThumbnail(task, thumbnail, refreshNow);
// thumbnailData can contain 1-2 ids, but they should correspond to the same
// TaskView, so overwriting is ok
updatedTaskView = taskView;
@@ -1833,7 +1835,7 @@
// the full list of tasks to taskViews
newRunningTaskView = getTaskViewByTaskIds(runningTaskId);
if (newRunningTaskView != null) {
- mRunningTaskViewId = newRunningTaskView.getTaskViewId();
+ setRunningTaskViewId(newRunningTaskView.getTaskViewId());
} else {
if (mActiveGestureRunningTasks != null) {
// This will update mRunningTaskViewId and create a stub view if necessary.
@@ -1842,7 +1844,7 @@
// the current running task is excludedFromRecents.)
showCurrentTask(mActiveGestureRunningTasks);
} else {
- mRunningTaskViewId = INVALID_TASK_ID;
+ setRunningTaskViewId(INVALID_TASK_ID);
}
}
}
@@ -2734,18 +2736,22 @@
* Returns true if we should add a stub taskView for the running task id
*/
protected boolean shouldAddStubTaskView(Task[] runningTasks) {
- if (runningTasks.length > 1) {
- TaskView primaryTaskView = getTaskViewByTaskId(runningTasks[0].key.id);
- TaskView secondaryTaskView = getTaskViewByTaskId(runningTasks[1].key.id);
- int leftTopTaskViewId =
- (primaryTaskView == null) ? -1 : primaryTaskView.getTaskViewId();
- int rightBottomTaskViewId =
- (secondaryTaskView == null) ? -1 : secondaryTaskView.getTaskViewId();
- // Add a new stub view if both taskIds don't match any taskViews
- return leftTopTaskViewId != rightBottomTaskViewId || leftTopTaskViewId == -1;
+ TaskView taskView = getTaskViewByTaskId(runningTasks[0].key.id);
+ if (taskView == null) {
+ // No TaskView found, add a stub task.
+ return true;
}
- Task runningTaskInfo = runningTasks[0];
- return runningTaskInfo != null && getTaskViewByTaskId(runningTaskInfo.key.id) == null;
+
+ if (runningTasks.length > 1) {
+ // Ensure all taskIds matches the TaskView, otherwise add a stub task.
+ return Arrays.stream(runningTasks).anyMatch(
+ runningTask -> !taskView.containsTaskId(runningTask.key.id));
+ } else {
+ // Ensure the TaskView only contains a single taskId, or is a DesktopTask,
+ // otherwise add a stub task.
+ // TODO(b/249371338): Figure out why DesktopTask only have a single runningTask.
+ return taskView.containsMultipleTasks() && !taskView.isDesktopTask();
+ }
}
/**
@@ -2842,7 +2848,23 @@
setRunningTaskViewShowScreenshot(true);
setRunningTaskHidden(false);
}
+ setRunningTaskViewId(runningTaskViewId);
+ }
+
+ private void setRunningTaskViewId(int runningTaskViewId) {
+ int prevRunningTaskViewId = mRunningTaskViewId;
mRunningTaskViewId = runningTaskViewId;
+
+ if (Flags.enableRefactorTaskThumbnail()) {
+ TaskView previousRunningTaskView = getTaskViewFromTaskViewId(prevRunningTaskViewId);
+ if (previousRunningTaskView != null) {
+ previousRunningTaskView.notifyIsRunningTaskUpdated();
+ }
+ TaskView newRunningTaskView = getTaskViewFromTaskViewId(runningTaskViewId);
+ if (newRunningTaskView != null) {
+ newRunningTaskView.notifyIsRunningTaskUpdated();
+ }
+ }
}
private int getTaskViewIdFromTaskId(int taskId) {
@@ -4762,7 +4784,7 @@
mSplitSelectStateController.getInitialTaskId();
TaskIdAttributeContainer taskIdAttributeContainer = mSplitHiddenTaskView
.getTaskIdAttributeContainers()[primaryTaskSelected ? 1 : 0];
- TaskThumbnailView thumbnail = taskIdAttributeContainer.getThumbnailView();
+ TaskThumbnailViewDeprecated thumbnail = taskIdAttributeContainer.getThumbnailView();
mSplitSelectStateController.getSplitAnimationController()
.addInitialSplitFromPair(taskIdAttributeContainer, builder,
mContainer.getDeviceProfile(),
@@ -5865,7 +5887,7 @@
ThumbnailData td =
mRecentsAnimationController.screenshotTask(container.getTask().key.id);
- TaskThumbnailView thumbnailView = container.getThumbnailView();
+ TaskThumbnailViewDeprecated thumbnailView = container.getThumbnailView();
if (td != null) {
thumbnailView.setThumbnail(container.getTask(), td);
} else {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index fcbb45b..443f83c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -22,7 +22,7 @@
import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
+import static com.android.quickstep.views.TaskThumbnailViewDeprecated.DIM_ALPHA;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -193,10 +193,6 @@
/** @return true if successfully able to populate task view menu, false otherwise */
private boolean populateAndLayoutMenu() {
- if (mTaskContainer.getTask().icon == null) {
- // Icon may not be loaded
- return false;
- }
addMenuOptions(mTaskContainer);
orientAroundTaskView(mTaskContainer);
return true;
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index 1db04a8..a138db0 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -83,7 +83,7 @@
private var alignedOptionIndex: Int = 0
private val extraSpaceForRowAlignment: Int
get() = optionMeasuredHeight * alignedOptionIndex
- private val menuWidth = context.resources.getDimensionPixelSize(R.dimen.task_menu_width_grid)
+ private val menuPaddingEnd = context.resources.getDimensionPixelSize(R.dimen.task_card_margin)
private lateinit var taskView: TaskView
private lateinit var optionLayout: LinearLayout
@@ -174,10 +174,10 @@
/** @return true if successfully able to populate task view menu, false otherwise */
private fun populateMenu(): Boolean {
// Icon may not be loaded
- if (taskContainer.task.icon == null) return false
+ if (taskContainer.iconView.drawable == null) return false
addMenuOptions()
- return true
+ return optionLayout.childCount > 0
}
private fun addMenuOptions() {
@@ -213,7 +213,13 @@
menuOptionView.requireViewById(R.id.text)
)
val lp = menuOptionView.layoutParams as LayoutParams
- lp.width = menuWidth
+ lp.width = LayoutParams.MATCH_PARENT
+ menuOptionView.setPaddingRelative(
+ menuOptionView.paddingStart,
+ menuOptionView.paddingTop,
+ menuPaddingEnd,
+ menuOptionView.paddingBottom
+ )
menuOptionView.setOnClickListener { view: View? -> menuOption.onClick(view) }
optionLayout.addView(menuOptionView)
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
similarity index 91%
rename from quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
rename to quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
index 7e46739..9802beb 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
@@ -62,61 +62,66 @@
/**
* A task in the Recents view.
+ *
+ * @deprecated This class will be replaced by the new [TaskThumbnailView].
*/
-public class TaskThumbnailView extends View {
+@Deprecated
+public class TaskThumbnailViewDeprecated extends View {
private static final MainThreadInitializedObject<FullscreenDrawParams> TEMP_PARAMS =
new MainThreadInitializedObject<>(FullscreenDrawParams::new);
- public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
- new FloatProperty<TaskThumbnailView>("dimAlpha") {
+ public static final Property<TaskThumbnailViewDeprecated, Float> DIM_ALPHA =
+ new FloatProperty<TaskThumbnailViewDeprecated>("dimAlpha") {
@Override
- public void setValue(TaskThumbnailView thumbnail, float dimAlpha) {
+ public void setValue(TaskThumbnailViewDeprecated thumbnail, float dimAlpha) {
thumbnail.setDimAlpha(dimAlpha);
}
@Override
- public Float get(TaskThumbnailView thumbnailView) {
+ public Float get(TaskThumbnailViewDeprecated thumbnailView) {
return thumbnailView.mDimAlpha;
}
};
- public static final Property<TaskThumbnailView, Float> SPLASH_ALPHA =
- new FloatProperty<TaskThumbnailView>("splashAlpha") {
+ public static final Property<TaskThumbnailViewDeprecated, Float> SPLASH_ALPHA =
+ new FloatProperty<TaskThumbnailViewDeprecated>("splashAlpha") {
@Override
- public void setValue(TaskThumbnailView thumbnail, float splashAlpha) {
+ public void setValue(TaskThumbnailViewDeprecated thumbnail, float splashAlpha) {
thumbnail.setSplashAlpha(splashAlpha);
}
@Override
- public Float get(TaskThumbnailView thumbnailView) {
+ public Float get(TaskThumbnailViewDeprecated thumbnailView) {
return thumbnailView.mSplashAlpha / 255f;
}
};
/** Use to animate thumbnail translationX while first app in split selection is initiated */
- public static final Property<TaskThumbnailView, Float> SPLIT_SELECT_TRANSLATE_X =
- new FloatProperty<TaskThumbnailView>("splitSelectTranslateX") {
+ public static final Property<TaskThumbnailViewDeprecated, Float> SPLIT_SELECT_TRANSLATE_X =
+ new FloatProperty<TaskThumbnailViewDeprecated>("splitSelectTranslateX") {
@Override
- public void setValue(TaskThumbnailView thumbnail, float splitSelectTranslateX) {
+ public void setValue(TaskThumbnailViewDeprecated thumbnail,
+ float splitSelectTranslateX) {
thumbnail.applySplitSelectTranslateX(splitSelectTranslateX);
}
@Override
- public Float get(TaskThumbnailView thumbnailView) {
+ public Float get(TaskThumbnailViewDeprecated thumbnailView) {
return thumbnailView.mSplitSelectTranslateX;
}
};
/** Use to animate thumbnail translationY while first app in split selection is initiated */
- public static final Property<TaskThumbnailView, Float> SPLIT_SELECT_TRANSLATE_Y =
- new FloatProperty<TaskThumbnailView>("splitSelectTranslateY") {
+ public static final Property<TaskThumbnailViewDeprecated, Float> SPLIT_SELECT_TRANSLATE_Y =
+ new FloatProperty<TaskThumbnailViewDeprecated>("splitSelectTranslateY") {
@Override
- public void setValue(TaskThumbnailView thumbnail, float splitSelectTranslateY) {
+ public void setValue(TaskThumbnailViewDeprecated thumbnail,
+ float splitSelectTranslateY) {
thumbnail.applySplitSelectTranslateY(splitSelectTranslateY);
}
@Override
- public Float get(TaskThumbnailView thumbnailView) {
+ public Float get(TaskThumbnailViewDeprecated thumbnailView) {
return thumbnailView.mSplitSelectTranslateY;
}
};
@@ -156,15 +161,16 @@
private float mSplitSelectTranslateX;
private float mSplitSelectTranslateY;
- public TaskThumbnailView(Context context) {
+ public TaskThumbnailViewDeprecated(Context context) {
this(context, null);
}
- public TaskThumbnailView(Context context, @Nullable AttributeSet attrs) {
+ public TaskThumbnailViewDeprecated(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
- public TaskThumbnailView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ public TaskThumbnailViewDeprecated(Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint.setFilterBitmap(true);
mBackgroundPaint.setColor(Color.WHITE);
@@ -180,7 +186,6 @@
/**
* Updates the thumbnail to draw the provided task
- * @param task
*/
public void bind(Task task) {
getTaskOverlay().reset();
@@ -194,6 +199,7 @@
/**
* Updates the thumbnail.
+ *
* @param refreshNow whether the {@code thumbnailData} will be used to redraw immediately.
* In most cases, we use the {@link #setThumbnail(Task, ThumbnailData)}
* version with {@code refreshNow} is true. The only exception is
@@ -227,6 +233,7 @@
/**
* Updates the shader, paint, matrix to redraw.
+ *
* @param shouldRefreshOverlay whether to re-initialize overlay
*/
private void refresh(boolean shouldRefreshOverlay) {
@@ -253,7 +260,6 @@
* <p>
* If dimAlpha is 0, no dimming is applied; if dimAlpha is 1, the thumbnail will be the
* extracted background color.
- *
*/
public void setDimAlpha(float dimAlpha) {
mDimAlpha = dimAlpha;
@@ -286,6 +292,7 @@
/**
* Get the scaled insets that are being used to draw the task view. This is a subsection of
* the full snapshot.
+ *
* @return the insets in snapshot bitmap coordinates.
*/
@RequiresApi(api = Build.VERSION_CODES.Q)
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index a033243..8fd99de 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -25,6 +25,7 @@
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.Flags.enableOverviewIconMenu;
+import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
@@ -106,6 +107,8 @@
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.task.thumbnail.TaskThumbnail;
+import com.android.quickstep.task.thumbnail.TaskThumbnailView;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.BorderAnimator;
import com.android.quickstep.util.RecentsOrientedState;
@@ -127,6 +130,7 @@
import java.util.function.Consumer;
import java.util.stream.Stream;
+
/**
* A task in the Recents view.
*/
@@ -318,13 +322,15 @@
@Override
public Float get(TaskView taskView) {
- return taskView.mSnapshotView.getScaleX();
+ return taskView.mTaskThumbnailViewDeprecated.getScaleX();
}
};
@Nullable
protected Task mTask;
- protected TaskThumbnailView mSnapshotView;
+ @Nullable // can be null when enableRefactorTaskThumbnail() == true
+ protected TaskThumbnailViewDeprecated mTaskThumbnailViewDeprecated;
+ protected TaskThumbnailView mTaskThumbnailView;
protected TaskViewIcon mIconView;
protected final DigitalWellBeingToast mDigitalWellBeingToast;
protected float mFullscreenProgress;
@@ -463,10 +469,11 @@
}
protected Unit updateBorderBounds(@NonNull Rect bounds) {
- bounds.set(mSnapshotView.getLeft() + Math.round(mSnapshotView.getTranslationX()),
- mSnapshotView.getTop() + Math.round(mSnapshotView.getTranslationY()),
- mSnapshotView.getRight() + Math.round(mSnapshotView.getTranslationX()),
- mSnapshotView.getBottom() + Math.round(mSnapshotView.getTranslationY()));
+ View snapshotView = getSnapshotView();
+ bounds.set(snapshotView.getLeft() + Math.round(snapshotView.getTranslationX()),
+ snapshotView.getTop() + Math.round(snapshotView.getTranslationY()),
+ snapshotView.getRight() + Math.round(snapshotView.getTranslationX()),
+ snapshotView.getBottom() + Math.round(snapshotView.getTranslationY()));
return Unit.INSTANCE;
}
@@ -479,6 +486,17 @@
}
/**
+ * Updates [TaskThumbnailView] to reflect the latest [Task] state (i.e., task isRunning).
+ */
+ public void notifyIsRunningTaskUpdated() {
+ // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
+ // so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
+ if (mTask != null) {
+ bindTaskThumbnailView();
+ }
+ }
+
+ /**
* Builds proto for logging
*/
public WorkspaceItemInfo getItemInfo() {
@@ -515,7 +533,14 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mSnapshotView = findViewById(R.id.snapshot);
+ mTaskThumbnailViewDeprecated = findViewById(R.id.snapshot);
+ if (enableRefactorTaskThumbnail()) {
+ mTaskThumbnailView = new TaskThumbnailView(mContext);
+ mTaskThumbnailView.setLayoutParams(mTaskThumbnailViewDeprecated.getLayoutParams());
+ int indexOfSnapshotView = indexOfChild(mTaskThumbnailViewDeprecated);
+ addView(mTaskThumbnailView, indexOfSnapshotView);
+ mTaskThumbnailViewDeprecated.setVisibility(View.GONE);
+ }
ViewStub iconViewStub = findViewById(R.id.icon);
if (enableOverviewIconMenu()) {
iconViewStub.setLayoutResource(R.layout.icon_app_chip_view);
@@ -650,12 +675,23 @@
cancelPendingLoadTasks();
mTask = task;
mTaskIdContainer[0] = mTask.key.id;
- mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView, mIconView,
+ mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task,
+ mTaskThumbnailViewDeprecated, mIconView,
STAGE_POSITION_UNDEFINED);
- mSnapshotView.bind(task);
+ if (enableRefactorTaskThumbnail()) {
+ bindTaskThumbnailView();
+ } else {
+ mTaskThumbnailViewDeprecated.bind(task);
+ }
setOrientationState(orientedState);
}
+ private void bindTaskThumbnailView() {
+ // TODO(b/335649589): TaskView's VM will already have access to TaskThumbnailView's VM
+ // so there will be no need to access TaskThumbnailView's VM through the TaskThumbnailView
+ mTaskThumbnailView.getViewModel().bind(new TaskThumbnail(mTask, isRunningTask()));
+ }
+
/**
* Sets up an on-click listener and the visibility for show_windows icon on top of the task.
*/
@@ -745,25 +781,29 @@
return null;
}
- public TaskThumbnailView getThumbnail() {
- return mSnapshotView;
+ public TaskThumbnailViewDeprecated getThumbnail() {
+ return mTaskThumbnailViewDeprecated;
}
void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
+ if (enableRefactorTaskThumbnail()) {
+ // TODO(b/334825222) add thumbnail logic
+ return;
+ }
if (mTask != null && thumbnailDatas != null) {
final ThumbnailData thumbnailData = thumbnailDatas.get(mTask.key.id);
if (thumbnailData != null) {
- mSnapshotView.setThumbnail(mTask, thumbnailData);
+ mTaskThumbnailViewDeprecated.setThumbnail(mTask, thumbnailData);
return;
}
}
- mSnapshotView.refresh();
+ mTaskThumbnailViewDeprecated.refresh();
}
/** TODO(b/197033698) Remove all usages of above method and migrate to this one */
- public TaskThumbnailView[] getThumbnails() {
- return new TaskThumbnailView[]{mSnapshotView};
+ public TaskThumbnailViewDeprecated[] getThumbnails() {
+ return new TaskThumbnailViewDeprecated[]{mTaskThumbnailViewDeprecated};
}
public TaskViewIcon getIconView() {
@@ -869,6 +909,8 @@
getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
if (ActivityManagerWrapper.getInstance()
.startActivityFromRecents(mTask.key, opts.options)) {
+ Log.d(TAG, "launchTaskAnimated - startActivityFromRecents: " + Arrays.toString(
+ getTaskIds()));
ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
RecentsView recentsView = getRecentsView();
if (recentsView.getRunningTaskViewId() != -1) {
@@ -894,6 +936,7 @@
return null;
}
} else {
+ Log.d(TAG, "launchTaskAnimated - mTask is null");
return null;
}
}
@@ -948,7 +991,10 @@
if (isQuickswitch) {
opts.setFreezeRecentTasksReordering();
}
- opts.setDisableStartingWindow(mSnapshotView.shouldShowSplashView());
+ // TODO(b/334826842) add splash functionality to new TTV
+ if (!enableRefactorTaskThumbnail()) {
+ opts.setDisableStartingWindow(mTaskThumbnailViewDeprecated.shouldShowSplashView());
+ }
Task.TaskKey key = mTask.key;
UI_HELPER_EXECUTOR.execute(() -> {
if (!ActivityManagerWrapper.getInstance().startActivityFromRecents(key, opts)) {
@@ -1035,6 +1081,8 @@
}
});
anim.start();
+ Log.d(TAG, "launchTasks - composeRecentsLaunchAnimator: " + Arrays.toString(
+ getTaskIds()));
recentsView.onTaskLaunchedInLiveTileMode();
return runnableList;
} else {
@@ -1069,7 +1117,10 @@
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
mThumbnailLoadRequest = thumbnailCache.updateThumbnailInBackground(
mTask, thumbnail -> {
- mSnapshotView.setThumbnail(mTask, thumbnail);
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334825222) add thumbnail state
+ mTaskThumbnailViewDeprecated.setThumbnail(mTask, thumbnail);
+ }
});
}
if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
@@ -1087,7 +1138,10 @@
}
} else {
if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
- mSnapshotView.setThumbnail(null, null);
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334825222) add thumbnail state
+ mTaskThumbnailViewDeprecated.setThumbnail(null, null);
+ }
// Reset the task thumbnail reference as well (it will be fetched from the cache or
// reloaded next time we need it)
mTask.thumbnail = null;
@@ -1195,11 +1249,15 @@
// TODO(b/271468547), we should default to setting trasnlations only on the snapshot instead
// of a hybrid of both margins and translations
- LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
+ LayoutParams snapshotParams = (LayoutParams) getSnapshotView().getLayoutParams();
snapshotParams.topMargin = thumbnailTopMargin;
- mSnapshotView.setLayoutParams(snapshotParams);
+ getSnapshotView().setLayoutParams(snapshotParams);
- mSnapshotView.getTaskOverlay().updateOrientationState(orientationState);
+ // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
+ // and if it's still necessary we should support that in the new TTV class.
+ if (!enableRefactorTaskThumbnail()) {
+ mTaskThumbnailViewDeprecated.getTaskOverlay().updateOrientationState(orientationState);
+ }
mDigitalWellBeingToast.initialize(mTask);
}
@@ -1288,7 +1346,10 @@
setAlpha(mStableAlpha);
setIconScaleAndDim(1);
setColorTint(0, 0);
- mSnapshotView.resetViewTransforms();
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/335399428) add split select functionality to new TTV
+ mTaskThumbnailViewDeprecated.resetViewTransforms();
+ }
}
public void setStableAlpha(float parentAlpha) {
@@ -1301,7 +1362,12 @@
resetPersistentViewTransforms();
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
- mSnapshotView.setThumbnail(mTask, null);
+ // TODO(b/334825222): Implement thumbnail/snapshot for the new [TaskThumbnailView].
+ if (enableRefactorTaskThumbnail()) {
+ notifyIsRunningTaskUpdated();
+ } else {
+ mTaskThumbnailViewDeprecated.setThumbnail(mTask, null);
+ }
setOverlayEnabled(false);
onTaskListVisibilityChanged(false);
mBorderEnabled = false;
@@ -1314,12 +1380,14 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (mContainer.getDeviceProfile().isTablet) {
+ DeviceProfile deviceProfile = mContainer.getDeviceProfile();
+ int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
+ if (deviceProfile.isTablet) {
setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : right - left);
- setPivotY(mSnapshotView.getTop());
+ setPivotY(thumbnailTopMargin);
} else {
setPivotX((right - left) * 0.5f);
- setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
+ setPivotY(thumbnailTopMargin + (getHeight() - thumbnailTopMargin) * 0.5f);
}
SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(0, 0, getWidth(), getHeight());
setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT);
@@ -1387,11 +1455,17 @@
}
protected void applyThumbnailSplashAlpha() {
- mSnapshotView.setSplashAlpha(mTaskThumbnailSplashAlpha);
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334826842) add splash functionality to new TTV
+ mTaskThumbnailViewDeprecated.setSplashAlpha(mTaskThumbnailSplashAlpha);
+ }
}
protected void refreshTaskThumbnailSplash() {
- mSnapshotView.refreshSplashView();
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334826842) add splash functionality to new TTV
+ mTaskThumbnailViewDeprecated.refreshSplashView();
+ }
}
private void setSplitSelectTranslationX(float x) {
@@ -1670,7 +1744,11 @@
progress = Utilities.boundToRange(progress, 0, 1);
mFullscreenProgress = progress;
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
- mSnapshotView.getTaskOverlay().setFullscreenProgress(progress);
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334826840) Add corner rounding to new TTV
+ mTaskThumbnailViewDeprecated.getTaskOverlay().setFullscreenProgress(progress);
+ }
+
RecentsView recentsView = mContainer.getOverviewPanel();
// Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
// oversized and banner would look disproportionately large.
@@ -1683,7 +1761,10 @@
protected void updateSnapshotRadius() {
updateCurrentFullscreenParams();
- mSnapshotView.setFullscreenParams(mCurrentFullscreenParams);
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334826840) Add corner rounding to new TTV
+ mTaskThumbnailViewDeprecated.setFullscreenParams(mCurrentFullscreenParams);
+ }
}
void updateCurrentFullscreenParams() {
@@ -1796,7 +1877,11 @@
}
public void setOverlayEnabled(boolean overlayEnabled) {
- mSnapshotView.setOverlayEnabled(overlayEnabled);
+ // TODO(b/335606129) Investigate the usage of [TaskOverlay] in the new TaskThumbnailView.
+ // and if it's still necessary we should support that in the new TTV class.
+ if (!enableRefactorTaskThumbnail()) {
+ mTaskThumbnailViewDeprecated.setOverlayEnabled(overlayEnabled);
+ }
}
public void initiateSplitSelect(SplitPositionOption splitPositionOption) {
@@ -1808,7 +1893,10 @@
* Set a color tint on the snapshot and supporting views.
*/
public void setColorTint(float amount, int tintColor) {
- mSnapshotView.setDimAlpha(amount);
+ if (!enableRefactorTaskThumbnail()) {
+ // TODO(b/334832108) Add scrim to new TTV
+ mTaskThumbnailViewDeprecated.setDimAlpha(amount);
+ }
mIconView.setIconColorTint(tintColor, amount);
mDigitalWellBeingToast.setBannerColorTint(tintColor, amount);
}
@@ -1834,6 +1922,10 @@
}
}
+ private View getSnapshotView() {
+ return enableRefactorTaskThumbnail() ? mTaskThumbnailView : mTaskThumbnailViewDeprecated;
+ }
+
/**
* We update and subsequently draw these in {@link #setFullscreenProgress(float)}.
*/
@@ -1878,7 +1970,7 @@
}
public class TaskIdAttributeContainer {
- private final TaskThumbnailView mThumbnailView;
+ private final TaskThumbnailViewDeprecated mThumbnailView;
private final Task mTask;
private final TaskViewIcon mIconView;
/** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
@@ -1886,7 +1978,7 @@
@IdRes
private final int mA11yNodeId;
- public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView,
+ public TaskIdAttributeContainer(Task task, TaskThumbnailViewDeprecated thumbnailView,
TaskViewIcon iconView, int stagePosition) {
this.mTask = task;
this.mThumbnailView = thumbnailView;
@@ -1896,7 +1988,7 @@
R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo;
}
- public TaskThumbnailView getThumbnailView() {
+ public TaskThumbnailViewDeprecated getThumbnailView() {
return mThumbnailView;
}
diff --git a/quickstep/tests/OWNERS b/quickstep/tests/OWNERS
index c271803..02e8ebc 100644
--- a/quickstep/tests/OWNERS
+++ b/quickstep/tests/OWNERS
@@ -2,4 +2,3 @@
sunnygoyal@google.com
winsonc@google.com
hyunyoungs@google.com
-mateuszc@google.com
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
index 58be345..0f06d98 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
@@ -12,10 +12,10 @@
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.SCREEN_PIN_LONG_PRESS_THRESHOLD;
-import static com.android.quickstep.OverviewCommandHelper.TYPE_HOME;
-import static com.android.quickstep.OverviewCommandHelper.TYPE_TOGGLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -31,7 +31,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.quickstep.OverviewCommandHelper;
+import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.AssistUtils;
@@ -52,8 +52,6 @@
@Mock
TouchInteractionService mockService;
@Mock
- OverviewCommandHelper mockCommandHelper;
- @Mock
Handler mockHandler;
@Mock
AssistUtils mockAssistUtils;
@@ -68,13 +66,26 @@
@Mock
View mockView;
+ private int mHomePressCount;
+ private int mOverviewToggleCount;
+ private final TaskbarNavButtonCallbacks mCallbacks = new TaskbarNavButtonCallbacks() {
+ @Override
+ public void onNavigateHome() {
+ mHomePressCount++;
+ }
+
+ @Override
+ public void onToggleOverview() {
+ mOverviewToggleCount++;
+ }
+ };
+
private TaskbarNavButtonController mNavButtonController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mockService.getDisplayId()).thenReturn(DISPLAY_ID);
- when(mockService.getOverviewCommandHelper()).thenReturn(mockCommandHelper);
when(mockService.getApplicationContext())
.thenReturn(InstrumentationRegistry.getInstrumentation().getTargetContext()
.getApplicationContext());
@@ -82,8 +93,12 @@
when(mockTaskbarControllers.getTaskbarActivityContext())
.thenReturn(mockTaskbarActivityContext);
doReturn(mockStatsLogManager).when(mockTaskbarActivityContext).getStatsLogManager();
- mNavButtonController = new TaskbarNavButtonController(mockService,
- mockSystemUiProxy, mockHandler, mockAssistUtils);
+ mNavButtonController = new TaskbarNavButtonController(
+ mockService,
+ mCallbacks,
+ mockSystemUiProxy,
+ mockHandler,
+ mockAssistUtils);
}
@Test
@@ -154,20 +169,20 @@
@Test
public void testPressHome() {
mNavButtonController.onButtonClick(BUTTON_HOME, mockView);
- verify(mockCommandHelper, times(1)).addCommand(TYPE_HOME);
+ assertThat(mHomePressCount).isEqualTo(1);
}
@Test
public void testPressRecents() {
mNavButtonController.onButtonClick(BUTTON_RECENTS, mockView);
- verify(mockCommandHelper, times(1)).addCommand(TYPE_TOGGLE);
+ assertThat(mOverviewToggleCount).isEqualTo(1);
}
@Test
- public void testPressRecentsWithScreenPinned() {
+ public void testPressRecentsWithScreenPinned_noNavigationToOverview() {
mNavButtonController.updateSysuiFlags(SYSUI_STATE_SCREEN_PINNING);
mNavButtonController.onButtonClick(BUTTON_RECENTS, mockView);
- verify(mockCommandHelper, times(0)).addCommand(TYPE_TOGGLE);
+ assertThat(mOverviewToggleCount).isEqualTo(0);
}
@Test
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index d90e048..3d8484d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -130,18 +130,90 @@
assertThat(handle.translationY).isEqualTo(0)
}
- private class TestBubbleBarViewAnimatorScheduler : BubbleBarViewAnimator.Scheduler {
+ @Test
+ fun animateBubbleInForStashed_tapAnimatingBubble() {
+ lateinit var overflowView: BubbleView
+ lateinit var bubbleView: BubbleView
+ lateinit var bubble: BubbleBarBubble
+ val bubbleBarView = BubbleBarView(context)
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ bubbleBarView.layoutParams = FrameLayout.LayoutParams(0, 0)
+ val inflater = LayoutInflater.from(context)
- var delayedBlock: (() -> Unit)? = null
- private set
+ val bitmap = ColorDrawable(Color.WHITE).toBitmap(width = 20, height = 20)
+ overflowView =
+ inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
+ overflowView.setOverflow(BubbleBarOverflow(overflowView), bitmap)
+ bubbleBarView.addView(overflowView)
- override fun post(block: () -> Unit) {
- block.invoke()
+ val bubbleInfo = BubbleInfo("key", 0, null, null, 0, context.packageName, null, false)
+ bubbleView =
+ inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
+ bubble =
+ BubbleBarBubble(bubbleInfo, bubbleView, bitmap, bitmap, Color.WHITE, Path(), "")
+ bubbleView.setBubble(bubble)
+ bubbleBarView.addView(bubbleView)
+ }
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+
+ val bubbleStashController = mock<BubbleStashController>()
+ whenever(bubbleStashController.isStashed).thenReturn(true)
+
+ val handle = View(context)
+ val handleAnimator = PhysicsAnimator.getInstance(handle)
+ whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
+
+ val animator =
+ BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ animator.animateBubbleInForStashed(bubble)
}
- override fun postDelayed(delayMillis: Long, block: () -> Unit) {
+ // let the animation start and wait for it to complete
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+
+ assertThat(handle.alpha).isEqualTo(0)
+ assertThat(handle.translationY).isEqualTo(-70)
+ assertThat(overflowView.visibility).isEqualTo(INVISIBLE)
+ assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
+ assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
+ assertThat(bubbleView.alpha).isEqualTo(1)
+ assertThat(bubbleView.translationY).isEqualTo(-20)
+ assertThat(bubbleView.scaleY).isEqualTo(1)
+
+ // verify the hide bubble animation is pending
+ assertThat(animatorScheduler.delayedBlock).isNotNull()
+
+ animator.onBubbleClickedWhileAnimating()
+
+ assertThat(animatorScheduler.delayedBlock).isNull()
+ assertThat(overflowView.visibility).isEqualTo(VISIBLE)
+ assertThat(overflowView.alpha).isEqualTo(1)
+ assertThat(bubbleView.alpha).isEqualTo(1)
+ assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
+ assertThat(bubbleBarView.background).isNotNull()
+ assertThat(bubbleBarView.isAnimatingNewBubble).isFalse()
+ }
+
+ private class TestBubbleBarViewAnimatorScheduler : BubbleBarViewAnimator.Scheduler {
+
+ var delayedBlock: Runnable? = null
+ private set
+
+ override fun post(block: Runnable) {
+ block.run()
+ }
+
+ override fun postDelayed(delayMillis: Long, block: Runnable) {
check(delayedBlock == null) { "there is already a pending block waiting to run" }
delayedBlock = block
}
+
+ override fun cancel(block: Runnable) {
+ check(delayedBlock == block) { "the pending block does not match the canceled block" }
+ delayedBlock = null
+ }
}
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
new file mode 100644
index 0000000..e71192f
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 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.task.thumbnail
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.systemui.shared.recents.model.Task
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class TaskThumbnailViewModelTest {
+ private val systemUnderTest = TaskThumbnailViewModel()
+
+ @Test
+ fun initialStateIsUninitialized() {
+ assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.Uninitialized)
+ }
+
+ @Test
+ fun bindRunningTask_thenStateIs_LiveTile() {
+ val taskThumbnail = TaskThumbnail(Task(), isRunning = true)
+ systemUnderTest.bind(taskThumbnail)
+
+ assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.LiveTile)
+ }
+
+ @Test
+ fun bindRunningTaskThenStoppedTask_thenStateIs_Uninitialized() {
+ // TODO(b/334825222): Change the expectation here when snapshot state is implemented
+ val task = Task()
+ val runningTask = TaskThumbnail(task, isRunning = true)
+ val stoppedTask = TaskThumbnail(task, isRunning = false)
+ systemUnderTest.bind(runningTask)
+ assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.LiveTile)
+
+ systemUnderTest.bind(stoppedTask)
+ assertThat(systemUnderTest.uiState.value).isEqualTo(TaskThumbnailUiState.Uninitialized)
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
index ca5fb70..fc757b4 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractTaplTestsTaskbar.java
@@ -55,7 +55,7 @@
"com.android.launcher3.testcomponent.BaseTestingActivity");
mLauncherLayout = TestUtil.setLauncherDefaultLayout(mTargetContext, layoutBuilder);
AbstractLauncherUiTest.initialize(this);
- startAppFastInFullscreen(CALCULATOR_APP_PACKAGE);
+ startAppFast(CALCULATOR_APP_PACKAGE);
mLauncher.enableBlockTimeout(true);
mLauncher.showTaskbarIfHidden();
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
index 857a4e3..7708233 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
import android.util.Log;
@@ -29,6 +28,8 @@
import androidx.test.filters.LargeTest;
import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.tapl.PrivateSpaceContainer;
+import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ScreenRecordRule;
import org.junit.After;
@@ -43,7 +44,9 @@
public class TaplPrivateSpaceTest extends AbstractQuickStepTest {
private int mProfileUserId;
- private boolean mPrivateProfileSetupSuccessful;
+
+ private static final String PRIVATE_PROFILE_NAME = "LauncherPrivateProfile";
+ private static final String INSTALLED_APP_NAME = "Aardwolf";
private static final String TAG = "TaplPrivateSpaceTest";
@Override
@@ -52,8 +55,6 @@
initialize(this);
createAndStartPrivateProfileUser();
- assumeTrue("Private Profile Setup not successful, aborting",
- mPrivateProfileSetupSuccessful);
mDevice.pressHome();
waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
@@ -72,7 +73,7 @@
private void createAndStartPrivateProfileUser() {
String createUserOutput = executeShellCommand("pm create-user --profileOf 0 --user-type "
- + "android.os.usertype.profile.PRIVATE LauncherPrivateProfile");
+ + "android.os.usertype.profile.PRIVATE " + PRIVATE_PROFILE_NAME);
updatePrivateProfileSetupSuccessful("pm create-user", createUserOutput);
String[] tokens = createUserOutput.split("\\s+");
mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]);
@@ -86,24 +87,57 @@
@After
public void removePrivateProfile() {
- String output = executeShellCommand("pm remove-user " + mProfileUserId);
- updateProfileRemovalSuccessful("pm remove-user", output);
- waitForPrivateSpaceRemoval();
+ String userListOutput = executeShellCommand("pm list users");
+ if (isPrivateProfilePresent("pm list users", userListOutput)) {
+ String output = executeShellCommand("pm remove-user " + mProfileUserId);
+ updateProfileRemovalSuccessful("pm remove-user", output);
+ waitForPrivateSpaceRemoval();
+ }
}
@Test
@ScreenRecordRule.ScreenRecord // b/334946529
public void testPrivateSpaceContainerIsPresent() {
- assumeTrue(mPrivateProfileSetupSuccessful);
// Scroll to the bottom of All Apps
executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
- waitForResumed("Launcher internal state is still Background");
// Verify Unlocked View elements are present.
assertNotNull("Private Space Unlocked View not found, or is not correct",
mLauncher.getAllApps().getPrivateSpaceUnlockedView());
}
+ @Test
+ @ScreenRecordRule.ScreenRecord // b/334946529
+ public void testUserInstalledAppIsShownAboveDivider() throws IOException {
+ // Ensure that the App is not installed in main user otherwise, it may not be found in
+ // PS container.
+ TestUtil.uninstallDummyApp();
+ // Install the app in Private Profile
+ TestUtil.installDummyAppForUser(mProfileUserId);
+ waitForLauncherUIUpdate();
+ // Scroll to the bottom of All Apps
+ executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+
+ // Verify the Installed App is displayed in correct position.
+ PrivateSpaceContainer psContainer = mLauncher.getAllApps().getPrivateSpaceUnlockedView();
+ psContainer.verifyInstalledAppIsPresent(INSTALLED_APP_NAME);
+ }
+
+ @Test
+ @ScreenRecordRule.ScreenRecord // b/334946529
+ public void testPrivateSpaceAppLongPressUninstallMenu() throws IOException {
+ // Ensure that the App is not installed in main user otherwise, it may not be found in
+ // PS container.
+ TestUtil.uninstallDummyApp();
+ // Install the app in Private Profile
+ TestUtil.installDummyAppForUser(mProfileUserId);
+ waitForLauncherUIUpdate();
+ // Scroll to the bottom of All Apps
+ executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+ // Get the "uninstall" menu item.
+ mLauncher.getAllApps().getAppIcon(INSTALLED_APP_NAME).openMenu().getMenuItem("Uninstall");
+ }
+
private void waitForPrivateSpaceSetup() {
waitForLauncherCondition("Private Profile not setup",
launcher -> launcher.getAppsView().hasPrivateProfile(),
@@ -129,7 +163,7 @@
private void updatePrivateProfileSetupSuccessful(String cli, String output) {
Log.d(TAG, "updatePrivateProfileSetupSuccessful, cli=" + cli + " " + "output="
+ output);
- mPrivateProfileSetupSuccessful = output.startsWith("Success");
+ assertTrue(output, output.startsWith("Success"));
}
private void updateProfileRemovalSuccessful(String cli, String output) {
@@ -137,6 +171,11 @@
assertTrue(output, output.startsWith("Success"));
}
+ private boolean isPrivateProfilePresent(String cli, String output) {
+ Log.d(TAG, "updatePrivateProfilePresent, cli=" + cli + " " + "output=" + output);
+ return output.contains(PRIVATE_PROFILE_NAME);
+ }
+
private String executeShellCommand(String command) {
try {
return mDevice.executeShellCommand(command);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
index a9ff161..df73e09 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
import android.graphics.Rect;
@@ -25,7 +23,6 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
-import com.android.launcher3.util.rule.TestStabilityRule;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
@@ -48,7 +45,6 @@
@Test
@NavigationModeSwitch(mode = NavigationModeSwitchRule.Mode.THREE_BUTTON)
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
public void testThreeButtonsTaskbarBoundsAfterConfigChangeDuringIme() {
Rect taskbarBoundsBefore = getTaskbar().getVisibleBounds();
// Go home and to an IME activity (any configuration change would do, as long as it
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
index 68c9bf9..4ffb6bd 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitAnimationControllerTest.kt
@@ -31,7 +31,7 @@
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.quickstep.views.GroupedTaskView
import com.android.quickstep.views.IconView
-import com.android.quickstep.views.TaskThumbnailView
+import com.android.quickstep.views.TaskThumbnailViewDeprecated
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
import com.android.systemui.shared.recents.model.Task
@@ -55,7 +55,7 @@
private val mockSplitSelectStateController: SplitSelectStateController = mock()
// TaskView
private val mockTaskView: TaskView = mock()
- private val mockThumbnailView: TaskThumbnailView = mock()
+ private val mockThumbnailView: TaskThumbnailViewDeprecated = mock()
private val mockBitmap: Bitmap = mock()
private val mockIconView: IconView = mock()
private val mockTaskViewDrawable: Drawable = mock()
@@ -200,7 +200,16 @@
doNothing()
.whenever(spySplitAnimationController)
.composeRecentsSplitLaunchAnimatorLegacy(
- any(), any(), any(), any(), any(), any(), any(), any(), any())
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any()
+ )
spySplitAnimationController.playSplitLaunchAnimation(
mockGroupedTaskView,
@@ -219,7 +228,16 @@
verify(spySplitAnimationController)
.composeRecentsSplitLaunchAnimatorLegacy(
- any(), any(), any(), any(), any(), any(), any(), any(), any())
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any(),
+ any()
+ )
}
@Test
diff --git a/res/drawable/ic_private_profile_app_scroller_badge.xml b/res/drawable/ic_private_profile_app_scroller_badge.xml
index b52a277..ede42b9 100644
--- a/res/drawable/ic_private_profile_app_scroller_badge.xml
+++ b/res/drawable/ic_private_profile_app_scroller_badge.xml
@@ -21,8 +21,8 @@
<path
android:pathData="M16.0007 2.66602L5.33398 6.66602V14.786C5.33398 21.5194 9.88065 27.7993 16.0007 29.3327C22.1207 27.7993 26.6673 21.5194 26.6673 14.786V6.66602L16.0007 2.66602ZM20.0007 19.9993V22.666H17.334V23.9993H14.6673V17.1193C12.7473 16.546 11.334 14.786 11.334 12.666C11.334 10.0927 13.4273 7.99935 16.0007 7.99935C18.574 7.99935 20.6673 10.0927 20.6673 12.666C20.6673 14.7727 19.254 16.546 17.334 17.1193V19.9993H20.0007Z"
android:fillType="evenOdd"
- android:fillColor="@android:color/white" />
+ android:fillColor="?android:attr/textColorPrimaryInverse" />
<path
android:pathData="M16 14.666C17.1046 14.666 18 13.7706 18 12.666C18 11.5614 17.1046 10.666 16 10.666C14.8954 10.666 14 11.5614 14 12.666C14 13.7706 14.8954 14.666 16 14.666Z"
- android:fillColor="@android:color/white" />
+ android:fillColor="?android:attr/textColorPrimaryInverse" />
</vector>
diff --git a/res/layout/private_space_header.xml b/res/layout/private_space_header.xml
index 65f1004..cefe394 100644
--- a/res/layout/private_space_header.xml
+++ b/res/layout/private_space_header.xml
@@ -25,7 +25,9 @@
android:clipToOutline="true"
android:gravity="center_vertical"
android:textDirection="locale"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:contentDescription="@string/ps_container_lock_button_content_description"
+ android:importantForAccessibility="yes">
<LinearLayout
android:id="@+id/settingsAndLockGroup"
@@ -40,7 +42,6 @@
android:layout_width="@dimen/ps_header_image_height"
android:layout_height="@dimen/ps_header_image_height"
android:background="@drawable/ps_settings_background"
- android:layout_marginEnd="@dimen/ps_header_settings_icon_margin_end"
android:src="@drawable/ic_ps_settings"
android:contentDescription="@string/ps_container_settings" />
<LinearLayout
@@ -49,8 +50,8 @@
android:layout_height="@dimen/ps_header_image_height"
android:background="@drawable/ps_lock_background"
android:gravity="center_vertical"
- android:layout_marginEnd="@dimen/ps_header_layout_margin"
- android:contentDescription="@string/ps_container_lock_unlock_button">
+ android:layout_marginEnd="@dimen/ps_lock_button_margin_end"
+ android:contentDescription="@string/ps_container_lock_button_content_description">
<ImageView
android:id="@+id/lock_icon"
android:layout_width="@dimen/ps_lock_icon_size"
@@ -96,6 +97,7 @@
android:gravity="center_vertical"
android:layout_marginStart="@dimen/ps_header_layout_margin"
android:text="@string/ps_container_title"
- android:theme="@style/PrivateSpaceHeaderTextStyle"/>
+ android:theme="@style/PrivateSpaceHeaderTextStyle"
+ android:importantForAccessibility="no"/>
</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index 12453a5..8f786bf 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -78,7 +78,7 @@
android:gravity="center_horizontal"
android:textSize="@dimen/widget_cell_font_size"
android:textColor="?android:attr/textColorSecondary"
- android:maxLines="2"
+ android:maxLines="3"
android:ellipsize="end"
android:fadingEdge="horizontal"
android:alpha="0.7" />
diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml
index 065c2ed..0a1407e 100644
--- a/res/layout/widgets_bottom_sheet_content.xml
+++ b/res/layout/widgets_bottom_sheet_content.xml
@@ -25,11 +25,10 @@
android:layout_width="@dimen/bottom_sheet_handle_width"
android:layout_height="@dimen/bottom_sheet_handle_height"
android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/bottom_sheet_handle_margin"
+ android:layout_marginBottom="@dimen/widgets_bottom_sheet_handle_margin"
android:visibility="gone"
android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/>
<TextView
- style="@style/TextHeadline"
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -41,8 +40,13 @@
android:id="@+id/widgets_table_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:fadeScrollbars="false"
- android:layout_marginTop="16dp">
+ android:layout_marginTop="24dp"
+ android:layout_marginBottom="24dp"
+ android:layout_marginHorizontal="@dimen/widget_bottom_sheet_horizontal_margin"
+ android:background="@drawable/widgets_surface_background"
+ android:scrollbarThumbVertical="@drawable/widget_picker_preview_pane_scroll_thumb"
+ android:clipToOutline="true"
+ android:clipChildren="true">
<include layout="@layout/widgets_table_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/values/config.xml b/res/values/config.xml
index 393a197..648a50c 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -76,6 +76,7 @@
<string name="taskbar_model_callbacks_factory_class" translatable="false"></string>
<string name="taskbar_view_callbacks_factory_class" translatable="false"></string>
<string name="launcher_restore_event_logger_class" translatable="false"></string>
+ <string name="taskbar_edu_tooltip_controller_class" translatable="false"></string>
<!-- Used for determining category of a widget presented in widget recommendations. -->
<string name="widget_recommendation_category_provider_class" translatable="false"></string>
<string name="api_wrapper_class" translatable="false"></string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5ff9902..31def04 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -209,6 +209,8 @@
<dimen name="widget_list_left_pane_horizontal_margin">0dp</dimen>
<dimen name="widget_list_horizontal_margin_two_pane">24dp</dimen>
<dimen name="widget_picker_vertical_margin_right_pane">24dp</dimen>
+ <!-- Margin on sides of the widgets scrollview in widgets bottom sheet -->
+ <dimen name="widget_bottom_sheet_horizontal_margin">16dp</dimen>
<dimen name="widget_preview_shadow_blur">0.5dp</dimen>
<dimen name="widget_preview_key_shadow_distance">1dp</dimen>
@@ -476,6 +478,7 @@
<dimen name="bottom_sheet_handle_width">32dp</dimen>
<dimen name="bottom_sheet_handle_height">4dp</dimen>
<dimen name="bottom_sheet_handle_margin">16dp</dimen>
+ <dimen name="widgets_bottom_sheet_handle_margin">24dp</dimen>
<dimen name="bottom_sheet_handle_corner_radius">2dp</dimen>
<!-- State transition -->
@@ -491,12 +494,12 @@
<!-- Private Space parameters -->
<dimen name="ps_container_corner_radius">24dp</dimen>
- <dimen name="ps_header_height">64dp</dimen>
+ <dimen name="ps_header_height">72dp</dimen>
<dimen name="ps_header_relative_layout_height">48dp</dimen>
<dimen name="ps_header_image_height">48dp</dimen>
<dimen name="ps_header_text_height">24dp</dimen>
<dimen name="ps_header_layout_margin">16dp</dimen>
- <dimen name="ps_header_settings_icon_margin_end">4dp</dimen>
+ <dimen name="ps_lock_button_margin_end">12dp</dimen>
<dimen name="ps_header_text_size">16sp</dimen>
<dimen name="ps_button_height">40dp</dimen>
<dimen name="ps_button_width">40dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e1c7d64..da5b709 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -487,8 +487,10 @@
<string name="ps_container_title">Private</string>
<!-- Description for Private Space Settings button -->
<string name="ps_container_settings">Private Space Settings</string>
- <!-- Description for Private Space Lock/Unlock button -->
- <string name="ps_container_lock_unlock_button">Lock/Unlock Private Space</string>
+ <!-- Description for Private Space Unlock button -->
+ <string name="ps_container_unlock_button_content_description">Private, unlocked.</string>
+ <!-- Description for Private Space Lock button -->
+ <string name="ps_container_lock_button_content_description">Private, locked.</string>
<string name="ps_container_lock_title">Lock</string>
<!-- Description for Private Space Transition button -->
<string name="ps_container_transition">Private Space Transitioning</string>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 83236d1..a7284e5 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -631,7 +631,7 @@
if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
getIconBounds(mDotParams.iconBounds);
Utilities.scaleRectAboutCenter(mDotParams.iconBounds,
- IconShape.getNormalizationScale());
+ IconShape.INSTANCE.get(getContext()).getNormalizationScale());
final int scrollX = getScrollX();
final int scrollY = getScrollY();
canvas.translate(scrollX, scrollY);
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 72758f2..98dade5 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -123,7 +123,7 @@
private OnTouchListener mInterceptTouchListener;
private final ArrayList<DelegatedCellDrawing> mDelegatedCellDrawings = new ArrayList<>();
- final PreviewBackground mFolderLeaveBehind = new PreviewBackground();
+ final PreviewBackground mFolderLeaveBehind = new PreviewBackground(getContext());
private static final int[] BACKGROUND_STATE_ACTIVE = new int[] { android.R.attr.state_active };
private static final int[] BACKGROUND_STATE_DEFAULT = EMPTY_STATE_SET;
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index d2633e0..159e17f 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -257,7 +257,7 @@
@Override
public void onSystemIconStateChanged(String iconState) {
- IconShape.init(mContext);
+ IconShape.INSTANCE.get(mContext).pickBestShape(mContext);
refreshAndReloadLauncher();
LauncherPrefs.get(mContext).put(ICON_STATE, iconState);
}
diff --git a/src/com/android/launcher3/MainProcessInitializer.java b/src/com/android/launcher3/MainProcessInitializer.java
index 3d7e11e..9944ef6 100644
--- a/src/com/android/launcher3/MainProcessInitializer.java
+++ b/src/com/android/launcher3/MainProcessInitializer.java
@@ -19,7 +19,6 @@
import android.content.Context;
import com.android.launcher3.graphics.BitmapCreationCheck;
-import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -36,7 +35,6 @@
protected void init(Context context) {
FileLog.setDir(context.getApplicationContext().getFilesDir());
- IconShape.init(context);
if (BitmapCreationCheck.ENABLED) {
BitmapCreationCheck.startTracking(context);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 1c23644..cc9f08e 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -485,7 +485,10 @@
super.onVisibilityAggregated(isVisible);
}
- protected boolean isPageInTransition() {
+ /**
+ * Returns true if the page is in the middle of transition to another page
+ */
+ public boolean isPageInTransition() {
return mIsPageInTransition;
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 0fc3211..f03dcab 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1955,7 +1955,7 @@
// In order to keep everything continuous, we hand off the currently rendered
// folder background to the newly created icon. This preserves animation state.
fi.setFolderBackground(mFolderCreateBg);
- mFolderCreateBg = new PreviewBackground();
+ mFolderCreateBg = new PreviewBackground(getContext());
fi.performCreateAnimation(destInfo, v, sourceInfo, d, folderLocation, scale);
} else {
fi.prepareCreateAnimation(v);
@@ -2670,7 +2670,7 @@
boolean userFolderPending = willCreateUserFolder(info, mDragOverView, false);
if (mDragMode == DRAG_MODE_NONE && userFolderPending) {
- mFolderCreateBg = new PreviewBackground();
+ mFolderCreateBg = new PreviewBackground(getContext());
mFolderCreateBg.setup(mLauncher, mLauncher, null,
mDragOverView.getMeasuredWidth(), mDragOverView.getPaddingTop());
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 60df7c5..a810331 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -22,7 +22,6 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_USER_INSTALLED_APPS_COUNT;
import android.content.Context;
-import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
@@ -362,7 +361,7 @@
// Split of private space apps into user-installed and system apps.
Map<Boolean, List<AppInfo>> split = mPrivateApps.stream()
.collect(Collectors.partitioningBy(mPrivateProviderManager
- .splitIntoUserInstalledAndSystemApps()));
+ .splitIntoUserInstalledAndSystemApps(mActivityContext)));
// TODO(b/329688630): switch to the pulled LayoutStaticSnapshot atom
mActivityContext
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index 38fe138..551fa94 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -80,9 +80,7 @@
import com.android.launcher3.views.RecyclerViewFastScroller;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import java.util.function.Predicate;
/**
@@ -105,7 +103,6 @@
}
}
};
- private Set<String> mPreInstalledSystemPackages = new HashSet<>();
private Intent mAppInstallerIntent = new Intent();
private PrivateAppsSectionDecorator mPrivateAppsSectionDecorator;
private boolean mPrivateSpaceSettingsAvailable;
@@ -115,6 +112,8 @@
private Runnable mOnPSHeaderAdded;
@Nullable
private RelativeLayout mPSHeader;
+ private final String mLockedStateContentDesc;
+ private final String mUnLockedStateContentDesc;
public PrivateProfileManager(UserManager userManager,
ActivityAllAppsContainerView<?> allApps,
@@ -128,6 +127,10 @@
UI_HELPER_EXECUTOR.post(() -> initializeInBackgroundThread(appContext));
mPsHeaderHeight = mAllApps.getContext().getResources().getDimensionPixelSize(
R.dimen.ps_header_height);
+ mLockedStateContentDesc = mAllApps.getContext()
+ .getString(R.string.ps_container_lock_button_content_description);
+ mUnLockedStateContentDesc = mAllApps.getContext()
+ .getString(R.string.ps_container_unlock_button_content_description);
}
/** Adds Private Space Header to the layout. */
@@ -264,8 +267,6 @@
ApiWrapper apiWrapper = ApiWrapper.INSTANCE.get(appContext);
UserHandle profileUser = getProfileUser();
if (profileUser != null) {
- mPreInstalledSystemPackages = new HashSet<>(
- apiWrapper.getPreInstalledSystemPackages(profileUser));
mAppInstallerIntent = apiWrapper
.getAppMarketActivityIntent(BuildConfig.APPLICATION_ID, profileUser);
}
@@ -349,10 +350,12 @@
* Splits private apps into user installed and system apps.
* When the list of system apps is empty, all apps are treated as system.
*/
- public Predicate<AppInfo> splitIntoUserInstalledAndSystemApps() {
- return appInfo -> !mPreInstalledSystemPackages.isEmpty()
+ public Predicate<AppInfo> splitIntoUserInstalledAndSystemApps(Context context) {
+ List<String> preInstallApps = UserCache.getInstance(context)
+ .getPreInstallApps(getProfileUser());
+ return appInfo -> !preInstallApps.isEmpty()
&& (appInfo.componentName == null
- || !(mPreInstalledSystemPackages.contains(appInfo.componentName.getPackageName())));
+ || !(preInstallApps.contains(appInfo.componentName.getPackageName())));
}
/** Add Private Space Header view elements based upon {@link UserProfileState} */
@@ -401,11 +404,13 @@
lockText.setVisibility(VISIBLE);
lockButton.setVisibility(VISIBLE);
lockButton.setOnClickListener(view -> lockingAction(/* lock */ true));
+ lockButton.setContentDescription(mUnLockedStateContentDesc);
}
case STATE_DISABLED -> {
lockText.setVisibility(GONE);
lockButton.setVisibility(VISIBLE);
lockButton.setOnClickListener(view -> lockingAction(/* lock */ false));
+ lockButton.setContentDescription(mLockedStateContentDesc);
}
default -> lockButton.setVisibility(GONE);
}
@@ -415,9 +420,14 @@
if (getCurrentState() == STATE_DISABLED) {
header.setOnClickListener(view -> lockingAction(/* lock */ false));
header.setClickable(true);
+ // Add header as accessibility target when disabled.
+ header.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ header.setContentDescription(mLockedStateContentDesc);
} else {
header.setOnClickListener(null);
header.setClickable(false);
+ // Remove header from accessibility target when enabled.
+ header.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 7a2ec97..7ef3209 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.BubbleTextView.TEXT_ALPHA_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
-import static com.android.launcher3.graphics.IconShape.getShape;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -45,6 +44,8 @@
import com.android.launcher3.anim.PropertyResetListener;
import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
+import com.android.launcher3.graphics.IconShape;
+import com.android.launcher3.graphics.IconShape.ShapeDelegate;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
@@ -233,8 +234,9 @@
}
play(a, getAnimator(mFolder.mFooter, ALPHA, 0, 1f), footerStartDelay, footerAlphaDuration);
+ ShapeDelegate shapeDelegate = IconShape.INSTANCE.get(mContext).getShape();
// Create reveal animator for the folder background
- play(a, getShape().createRevealAnimator(
+ play(a, shapeDelegate.createRevealAnimator(
mFolder, startRect, endRect, finalRadius, !mIsOpening));
// Create reveal animator for the folder content (capture the top 4 icons 2x2)
@@ -246,10 +248,9 @@
int left = mContent.getPaddingLeft() + page * lp.width;
Rect contentStart = new Rect(left, 0, left + width, height);
Rect contentEnd = new Rect(left, 0, left + lp.width, lp.height);
- play(a, getShape().createRevealAnimator(
+ play(a, shapeDelegate.createRevealAnimator(
mFolder.getContent(), contentStart, contentEnd, finalRadius, !mIsOpening));
-
// Fade in the folder name, as the text can overlap the icons when grid size is small.
mFolder.mFolderName.setAlpha(mIsOpening ? 0f : 1f);
play(a, getAnimator(mFolder.mFolderName, View.ALPHA, 0, 1),
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 4d88b68..00636a3 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -112,7 +112,7 @@
@Thunk BubbleTextView mFolderName;
- PreviewBackground mBackground = new PreviewBackground();
+ PreviewBackground mBackground = new PreviewBackground(getContext());
private boolean mBackgroundIsVisible = true;
FolderGridOrganizer mPreviewVerifier;
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index ec03803..df41d47 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -19,7 +19,6 @@
import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
-import static com.android.launcher3.graphics.IconShape.getShape;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.Animator;
@@ -49,6 +48,8 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.celllayout.DelegatedCellDrawing;
+import com.android.launcher3.graphics.IconShape;
+import com.android.launcher3.graphics.IconShape.ShapeDelegate;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
@@ -66,6 +67,7 @@
@VisibleForTesting protected static final float HOVER_SCALE = 1.1f;
@VisibleForTesting protected static final int HOVER_ANIMATION_DURATION = 300;
+ private final Context mContext;
private final PorterDuffXfermode mShadowPorterDuffXfermode
= new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
private RadialGradient mShadowShader = null;
@@ -138,6 +140,10 @@
}
};
+ public PreviewBackground(Context context) {
+ mContext = context;
+ }
+
/**
* Draws folder background under cell layout
*/
@@ -254,6 +260,10 @@
drawShadow(canvas);
}
+ private ShapeDelegate getShape() {
+ return IconShape.INSTANCE.get(mContext).getShape();
+ }
+
public void drawShadow(Canvas canvas) {
if (!DRAW_SHADOW) {
return;
diff --git a/src/com/android/launcher3/graphics/IconShape.java b/src/com/android/launcher3/graphics/IconShape.java
index f82b07e..5f8f2dc 100644
--- a/src/com/android/launcher3/graphics/IconShape.java
+++ b/src/com/android/launcher3/graphics/IconShape.java
@@ -22,7 +22,6 @@
import android.animation.FloatArrayEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -35,7 +34,6 @@
import android.graphics.Region.Op;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
-import android.os.Build;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.View;
@@ -45,6 +43,8 @@
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.views.ClipPathView;
import org.xmlpull.v1.XmlPullParser;
@@ -57,38 +57,94 @@
/**
* Abstract representation of the shape of an icon shape
*/
-public abstract class IconShape {
+public final class IconShape implements SafeCloseable {
- private static IconShape sInstance = new Circle();
- private static float sNormalizationScale = ICON_VISIBLE_AREA_FACTOR;
+ public static final MainThreadInitializedObject<IconShape> INSTANCE =
+ new MainThreadInitializedObject<>(IconShape::new);
- public static IconShape getShape() {
- return sInstance;
+
+ private ShapeDelegate mDelegate = new Circle();
+ private float mNormalizationScale = ICON_VISIBLE_AREA_FACTOR;
+
+ private IconShape(Context context) {
+ pickBestShape(context);
}
- public static float getNormalizationScale() {
- return sNormalizationScale;
+ public ShapeDelegate getShape() {
+ return mDelegate;
}
- public boolean enableShapeDetection(){
- return false;
- };
+ public float getNormalizationScale() {
+ return mNormalizationScale;
+ }
- public abstract void drawShape(Canvas canvas, float offsetX, float offsetY, float radius,
- Paint paint);
+ @Override
+ public void close() { }
- public abstract void addToPath(Path path, float offsetX, float offsetY, float radius);
+ /**
+ * Initializes the shape which is closest to the {@link AdaptiveIconDrawable}
+ */
+ public void pickBestShape(Context context) {
+ // Pick any large size
+ final int size = 200;
- public abstract <T extends View & ClipPathView> Animator createRevealAnimator(T target,
- Rect startRect, Rect endRect, float endRadius, boolean isReversed);
+ Region full = new Region(0, 0, size, size);
+ Region iconR = new Region();
+ AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
+ new ColorDrawable(Color.BLACK), new ColorDrawable(Color.BLACK));
+ drawable.setBounds(0, 0, size, size);
+ iconR.setPath(drawable.getIconMask(), full);
+
+ Path shapePath = new Path();
+ Region shapeR = new Region();
+
+ // Find the shape with minimum area of divergent region.
+ int minArea = Integer.MAX_VALUE;
+ ShapeDelegate closestShape = null;
+ for (ShapeDelegate shape : getAllShapes(context)) {
+ shapePath.reset();
+ shape.addToPath(shapePath, 0, 0, size / 2f);
+ shapeR.setPath(shapePath, full);
+ shapeR.op(iconR, Op.XOR);
+
+ int area = GraphicsUtils.getArea(shapeR);
+ if (area < minArea) {
+ minArea = area;
+ closestShape = shape;
+ }
+ }
+
+ if (closestShape != null) {
+ mDelegate = closestShape;
+ }
+
+ // Initialize shape properties
+ mNormalizationScale = IconNormalizer.normalizeAdaptiveIcon(drawable, size, null);
+ }
+
+
+
+ public interface ShapeDelegate {
+
+ default boolean enableShapeDetection() {
+ return false;
+ }
+
+ void drawShape(Canvas canvas, float offsetX, float offsetY, float radius, Paint paint);
+
+ void addToPath(Path path, float offsetX, float offsetY, float radius);
+
+ <T extends View & ClipPathView> ValueAnimator createRevealAnimator(T target,
+ Rect startRect, Rect endRect, float endRadius, boolean isReversed);
+ }
/**
* Abstract shape where the reveal animation is a derivative of a round rect animation
*/
- private static abstract class SimpleRectShape extends IconShape {
+ private static abstract class SimpleRectShape implements ShapeDelegate {
@Override
- public final <T extends View & ClipPathView> Animator createRevealAnimator(T target,
+ public final <T extends View & ClipPathView> ValueAnimator createRevealAnimator(T target,
Rect startRect, Rect endRect, float endRadius, boolean isReversed) {
return new RoundedRectRevealOutlineProvider(
getStartRadius(startRect), endRadius, startRect, endRect) {
@@ -105,7 +161,7 @@
/**
* Abstract shape which draws using {@link Path}
*/
- private static abstract class PathShape extends IconShape {
+ private static abstract class PathShape implements ShapeDelegate {
private final Path mTmpPath = new Path();
@@ -121,7 +177,7 @@
Rect startRect, Rect endRect, float endRadius, Path outPath);
@Override
- public final <T extends View & ClipPathView> Animator createRevealAnimator(T target,
+ public final <T extends View & ClipPathView> ValueAnimator createRevealAnimator(T target,
Rect startRect, Rect endRect, float endRadius, boolean isReversed) {
Path path = new Path();
AnimatorUpdateListener listener =
@@ -203,7 +259,7 @@
}
}
- public static class RoundedSquare extends SimpleRectShape {
+ private static class RoundedSquare extends SimpleRectShape {
/**
* Ratio of corner radius to half size.
@@ -237,7 +293,7 @@
}
}
- public static class TearDrop extends PathShape {
+ private static class TearDrop extends PathShape {
/**
* Radio of short radius to large radius, based on the shape options defined in the config.
@@ -289,7 +345,7 @@
}
}
- public static class Squircle extends PathShape {
+ private static class Squircle extends PathShape {
/**
* Radio of radius to circle radius, based on the shape options defined in the config.
@@ -375,14 +431,7 @@
}
}
- /**
- * Initializes the shape which is closest to the {@link AdaptiveIconDrawable}
- */
- public static void init(Context context) {
- pickBestShape(context);
- }
-
- private static IconShape getShapeDefinition(String type, float radius) {
+ private static ShapeDelegate getShapeDefinition(String type, float radius) {
switch (type) {
case "Circle":
return new Circle();
@@ -397,8 +446,8 @@
}
}
- private static List<IconShape> getAllShapes(Context context) {
- ArrayList<IconShape> result = new ArrayList<>();
+ private static List<ShapeDelegate> getAllShapes(Context context) {
+ ArrayList<ShapeDelegate> result = new ArrayList<>();
try (XmlResourceParser parser = context.getResources().getXml(R.xml.folder_shapes)) {
// Find the root tag
@@ -416,7 +465,7 @@
if (type == XmlPullParser.START_TAG) {
AttributeSet attrs = Xml.asAttributeSet(parser);
TypedArray a = context.obtainStyledAttributes(attrs, radiusAttr);
- IconShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
+ ShapeDelegate shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
a.recycle();
result.add(shape);
@@ -428,42 +477,4 @@
return result;
}
- @TargetApi(Build.VERSION_CODES.O)
- protected static void pickBestShape(Context context) {
- // Pick any large size
- final int size = 200;
-
- Region full = new Region(0, 0, size, size);
- Region iconR = new Region();
- AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
- new ColorDrawable(Color.BLACK), new ColorDrawable(Color.BLACK));
- drawable.setBounds(0, 0, size, size);
- iconR.setPath(drawable.getIconMask(), full);
-
- Path shapePath = new Path();
- Region shapeR = new Region();
-
- // Find the shape with minimum area of divergent region.
- int minArea = Integer.MAX_VALUE;
- IconShape closestShape = null;
- for (IconShape shape : getAllShapes(context)) {
- shapePath.reset();
- shape.addToPath(shapePath, 0, 0, size / 2f);
- shapeR.setPath(shapePath, full);
- shapeR.op(iconR, Op.XOR);
-
- int area = GraphicsUtils.getArea(shapeR);
- if (area < minArea) {
- minArea = area;
- closestShape = shape;
- }
- }
-
- if (closestShape != null) {
- sInstance = closestShape;
- }
-
- // Initialize shape properties
- sNormalizationScale = IconNormalizer.normalizeAdaptiveIcon(drawable, size, null);
- }
}
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index 513377a..7331c6f 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -78,7 +78,8 @@
private MonochromeIconFactory mMonochromeIconFactory;
protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
- super(context, fillResIconDpi, iconBitmapSize, IconShape.getShape().enableShapeDetection());
+ super(context, fillResIconDpi, iconBitmapSize,
+ IconShape.INSTANCE.get(context).getShape().enableShapeDetection());
mMonoIconEnabled = Themes.isThemedIconEnabled(context);
mPoolId = poolId;
}
diff --git a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
index 456cde8..480e8f3 100644
--- a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
+++ b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
@@ -246,7 +246,8 @@
protected void setCurrentItem(T item) {
mCurrentItem = item;
- mShift = 0;
+ // Set it to end value directly to skip the animation for outline
+ mShift = Flags.enableFocusOutline() ? 1 : 0;
mTargetItem = null;
}
diff --git a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
index 4653bf1..21d157a 100644
--- a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
+++ b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
@@ -19,6 +19,7 @@
import android.graphics.Rect;
import android.view.View;
+import com.android.launcher3.Flags;
import com.android.launcher3.PagedView;
/**
@@ -35,6 +36,28 @@
}
@Override
+ protected boolean shouldDraw(View item) {
+ if (Flags.enableFocusOutline()) {
+ // Not draw outline in page transition because the outline just remains fully
+ // persistent during the transition and does not look smooth
+ return super.shouldDraw(item) && !isInPageTransition(item);
+ } else {
+ return super.shouldDraw(item);
+ }
+ }
+
+ private boolean isInPageTransition(View view) {
+ if (view == null || !(view.getParent() instanceof View)) {
+ return false;
+ }
+ boolean isInTransition = false;
+ if (view instanceof PagedView) {
+ isInTransition = ((PagedView<?>) view).isPageInTransition();
+ }
+ return isInTransition || isInPageTransition((View) view.getParent());
+ }
+
+ @Override
public void viewToRect(View v, Rect outRect) {
// Using FocusedRect here allows views to provide their custom rect for drawing outline,
// e.g. making the Rect bigger than the content to leave some padding between view and
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index 185e0b5..b7b557d 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -24,6 +24,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.ArrayMap;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
@@ -81,6 +82,9 @@
@NonNull
private Map<UserHandle, UserIconInfo> mUserToSerialMap;
+ @NonNull
+ private Map<UserHandle, List<String>> mUserToPreInstallAppMap;
+
private UserCache(Context context) {
mContext = context;
mUserToSerialMap = Collections.emptyMap();
@@ -120,6 +124,20 @@
@WorkerThread
private void updateCache() {
mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers();
+ mUserToPreInstallAppMap = fetchPreInstallApps();
+ }
+
+ @WorkerThread
+ private Map<UserHandle, List<String>> fetchPreInstallApps() {
+ Map<UserHandle, List<String>> userToPreInstallApp = new ArrayMap<>();
+ mUserToSerialMap.forEach((userHandle, userIconInfo) -> {
+ // Fetch only for private profile, as other profiles have no usages yet.
+ List<String> preInstallApp = userIconInfo.isPrivate()
+ ? ApiWrapper.INSTANCE.get(mContext).getPreInstalledSystemPackages(userHandle)
+ : new ArrayList<>();
+ userToPreInstallApp.put(userHandle, preInstallApp);
+ });
+ return userToPreInstallApp;
}
/**
@@ -172,6 +190,15 @@
}
/**
+ * Returns the pre-installed apps for a user.
+ */
+ @NonNull
+ public List<String> getPreInstallApps(UserHandle user) {
+ List<String> preInstallApp = mUserToPreInstallAppMap.get(user);
+ return preInstallApp == null ? new ArrayList<>() : preInstallApp;
+ }
+
+ /**
* Get a non-themed {@link UserBadgeDrawable} based on the provided {@link UserHandle}.
*/
@Nullable
diff --git a/src/com/android/launcher3/util/LockedUserState.kt b/src/com/android/launcher3/util/LockedUserState.kt
index 0a87594..94f9e4f 100644
--- a/src/com/android/launcher3/util/LockedUserState.kt
+++ b/src/com/android/launcher3/util/LockedUserState.kt
@@ -56,12 +56,16 @@
private fun notifyUserUnlocked() {
mUserUnlockedActions.executeAllAndDestroy()
- mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
+ Executors.THREAD_POOL_EXECUTOR.execute {
+ mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
+ }
}
/** Stops the receiver from listening for ACTION_USER_UNLOCK broadcasts. */
override fun close() {
- mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
+ Executors.THREAD_POOL_EXECUTOR.execute {
+ mUserUnlockedReceiver.unregisterReceiverSafely(mContext)
+ }
}
/**
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.kt b/src/com/android/launcher3/util/OnboardingPrefs.kt
index 370b4c8..ac6e97c 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.kt
+++ b/src/com/android/launcher3/util/OnboardingPrefs.kt
@@ -76,7 +76,5 @@
@JvmField
val HOTSEAT_LONGPRESS_TIP_SEEN = backedUpItem("launcher.hotseat_longpress_tip_seen", false)
- @JvmField
- val TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN =
- backedUpItem("launcher.taskbar_circle_to_search_edu_seen", false)
+ @JvmField val TASKBAR_SEARCH_EDU_SEEN = backedUpItem("launcher.taskbar_search_edu_seen", false)
}
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
index b2b4959..51749a7 100644
--- a/src/com/android/launcher3/util/VibratorWrapper.java
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -19,14 +19,12 @@
import static android.os.VibrationEffect.createPredefined;
import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.SuppressLint;
-import android.content.ContentResolver;
import android.content.Context;
-import android.database.ContentObserver;
import android.media.AudioAttributes;
+import android.net.Uri;
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -51,6 +49,8 @@
public static final VibrationEffect EFFECT_CLICK =
createPredefined(VibrationEffect.EFFECT_CLICK);
+ private static final Uri HAPTIC_FEEDBACK_URI =
+ Settings.System.getUriFor(HAPTIC_FEEDBACK_ENABLED);
private static final float LOW_TICK_SCALE = 0.9f;
private static final float DRAG_TEXTURE_SCALE = 0.03f;
@@ -76,8 +76,9 @@
private final Context mContext;
private final Vibrator mVibrator;
private final boolean mHasVibrator;
+ private final SettingsCache.OnChangeListener mHapticChangeListener =
+ isEnabled -> mIsHapticFeedbackEnabled = isEnabled;
- private ContentObserver mHapticFeedbackObserver;
private boolean mIsHapticFeedbackEnabled;
private VibratorWrapper(Context context) {
@@ -85,16 +86,9 @@
mVibrator = context.getSystemService(Vibrator.class);
mHasVibrator = mVibrator.hasVibrator();
if (mHasVibrator) {
- final ContentResolver resolver = context.getContentResolver();
- mIsHapticFeedbackEnabled = isHapticFeedbackEnabled(resolver);
- mHapticFeedbackObserver = new ContentObserver(MAIN_EXECUTOR.getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- mIsHapticFeedbackEnabled = isHapticFeedbackEnabled(resolver);
- }
- };
- resolver.registerContentObserver(Settings.System.getUriFor(HAPTIC_FEEDBACK_ENABLED),
- false /* notifyForDescendants */, mHapticFeedbackObserver);
+ SettingsCache cache = SettingsCache.INSTANCE.get(mContext);
+ cache.register(HAPTIC_FEEDBACK_URI, mHapticChangeListener);
+ mIsHapticFeedbackEnabled = cache.getValue(HAPTIC_FEEDBACK_URI, 0);
} else {
mIsHapticFeedbackEnabled = false;
}
@@ -129,8 +123,9 @@
@Override
public void close() {
- if (mHapticFeedbackObserver != null) {
- mContext.getContentResolver().unregisterContentObserver(mHapticFeedbackObserver);
+ if (mHasVibrator) {
+ SettingsCache.INSTANCE.get(mContext)
+ .unregister(HAPTIC_FEEDBACK_URI, mHapticChangeListener);
}
}
@@ -183,10 +178,6 @@
mLastDragTime = 0;
}
- private boolean isHapticFeedbackEnabled(ContentResolver resolver) {
- return Settings.System.getInt(resolver, HAPTIC_FEEDBACK_ENABLED, 0) == 1;
- }
-
/** Vibrates with the given effect if haptic feedback is available and enabled. */
public void vibrate(VibrationEffect vibrationEffect) {
if (mHasVibrator && mIsHapticFeedbackEnabled) {
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index 5d3fa9b..172f968 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -18,12 +18,11 @@
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.Utilities.boundToRange;
import static com.android.launcher3.Utilities.mapToRange;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static java.lang.Math.max;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
@@ -142,14 +141,10 @@
if (mIsAdaptiveIcon) {
if (!isOpening && progress >= shapeProgressStart) {
if (mRevealAnimator == null) {
- mRevealAnimator = (ValueAnimator) IconShape.getShape().createRevealAnimator(
- this, mStartRevealRect, mOutline, mTaskCornerRadius, !isOpening);
- mRevealAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mRevealAnimator = null;
- }
- });
+ mRevealAnimator = IconShape.INSTANCE.get(getContext()).getShape()
+ .createRevealAnimator(this, mStartRevealRect,
+ mOutline, mTaskCornerRadius, !isOpening);
+ mRevealAnimator.addListener(forEndCallback(() -> mRevealAnimator = null));
mRevealAnimator.start();
// We pause here so we can set the current fraction ourselves.
mRevealAnimator.pause();
@@ -230,7 +225,8 @@
mStartRevealRect.set(0, 0, originalWidth, originalHeight);
if (!isFolderIcon) {
- Utilities.scaleRectAboutCenter(mStartRevealRect, IconShape.getNormalizationScale());
+ Utilities.scaleRectAboutCenter(mStartRevealRect,
+ IconShape.INSTANCE.get(getContext()).getNormalizationScale());
}
if (dp.isLandscape) {
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index e5b5daa..749554c 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -141,9 +141,17 @@
if (enableWidgetTapToAdd()) {
scrollToWidgetCell(wc);
+
if (mWidgetCellWithAddButton != null) {
- // If there is a add button currently showing, hide it.
- mWidgetCellWithAddButton.hideAddButton(/* animate= */ true);
+ if (mWidgetCellWithAddButton.isShowingAddButton()) {
+ // If there is a add button currently showing, hide it.
+ mWidgetCellWithAddButton.hideAddButton(/* animate= */ true);
+ } else {
+ // The last recorded widget cell to show an add button is no longer showing it,
+ // likely because the widget cell has been recycled or lost focus. If this is
+ // the cell that has been clicked, we will show it below.
+ mWidgetCellWithAddButton = null;
+ }
}
if (mWidgetCellWithAddButton != wc) {
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index ab007fb..ea167d7 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -110,6 +110,7 @@
private int mSourceContainer = CONTAINER_WIDGETS_TRAY;
private CancellableTask mIconLoadRequest;
+ private boolean mIsShowingAddButton = false;
public WidgetCell(Context context) {
this(context, null);
@@ -534,6 +535,9 @@
* @param callback Callback to be set on the button.
*/
public void showAddButton(View.OnClickListener callback) {
+ if (mIsShowingAddButton) return;
+ mIsShowingAddButton = true;
+
mWidgetAddButton.setAlpha(0F);
mWidgetAddButton.setVisibility(VISIBLE);
mWidgetAddButton.setOnClickListener(callback);
@@ -555,6 +559,9 @@
* Hide tap to add button.
*/
public void hideAddButton(boolean animate) {
+ if (!mIsShowingAddButton) return;
+ mIsShowingAddButton = false;
+
mWidgetAddButton.setOnClickListener(null);
mWidgetAddButton.animate().cancel();
mWidgetTextContainer.animate().cancel();
@@ -579,4 +586,8 @@
.alpha(1F)
.setDuration(ADD_BUTTON_FADE_DURATION_MS);
}
+
+ public boolean isShowingAddButton() {
+ return mIsShowingAddButton;
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index b14ec42..3be6c68 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.IntProperty;
import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -50,22 +49,6 @@
* Bottom sheet for the "Widgets" system shortcut in the long-press popup.
*/
public class WidgetsBottomSheet extends BaseWidgetSheet {
- private static final String TAG = "WidgetsBottomSheet";
-
- private static final IntProperty<View> PADDING_BOTTOM =
- new IntProperty<View>("paddingBottom") {
- @Override
- public void setValue(View view, int paddingBottom) {
- view.setPadding(view.getPaddingLeft(), view.getPaddingTop(),
- view.getPaddingRight(), paddingBottom);
- }
-
- @Override
- public Integer get(View view) {
- return view.getPaddingBottom();
- }
- };
-
private static final int DEFAULT_CLOSE_DURATION = 200;
private static final long EDUCATION_TIP_DELAY_MS = 300;
@@ -119,9 +102,6 @@
mContent = findViewById(R.id.widgets_bottom_sheet);
setContentBackgroundWithParent(
getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet), mContent);
- View scrollView = findViewById(R.id.widgets_table_scroll_view);
- scrollView.setOutlineProvider(mViewOutlineProvider);
- scrollView.setClipToOutline(true);
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 28eeb10..b3fcefa 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
+import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_LIST;
import android.animation.Animator;
import android.content.Context;
@@ -1094,10 +1095,35 @@
default:
break;
}
- mWidgetsListItemAnimator = new DefaultItemAnimator();
+ mWidgetsListItemAnimator = new DefaultItemAnimator() {
+ @Override
+ public boolean animateChange(RecyclerView.ViewHolder oldHolder,
+ RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft,
+ int toTop) {
+ // As we expand an item, the content / widgets list that appears (with add
+ // event) also gets change events as its previews load asynchronously. The
+ // super implementation of animateChange cancels the animations on it - breaking
+ // the "add animation". Instead, here, we skip "change" animation for content
+ // list - because we want it to either appear or disappear. And, the previews
+ // themselves have their own animation when loaded, so, we don't need change
+ // animations for them anyway. Below, we do-nothing.
+ if (oldHolder.getItemViewType() == VIEW_TYPE_WIDGETS_LIST) {
+ dispatchChangeStarting(oldHolder, true);
+ dispatchChangeFinished(oldHolder, true);
+ return true;
+ }
+ return super.animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft,
+ toTop);
+ }
+ };
// Disable change animations because it disrupts the item focus upon adapter item
// change.
mWidgetsListItemAnimator.setSupportsChangeAnimations(false);
+ // Make the moves a bit faster, so that the amount of time for which user sees the
+ // bottom-sheet background before "add" animation starts is less making it smoother.
+ mWidgetsListItemAnimator.setChangeDuration(90);
+ mWidgetsListItemAnimator.setMoveDuration(90);
+ mWidgetsListItemAnimator.setAddDuration(300);
}
private int getEmptySpaceHeight() {
diff --git a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
index 5e0e203..edaf474 100644
--- a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
+++ b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
@@ -31,6 +31,7 @@
/** An utility class which groups {@link WidgetItem}s into a table. */
public final class WidgetsTableUtils {
+ private static final int MAX_ITEMS_IN_ROW = 3;
/**
* Groups widgets in the following order:
@@ -125,7 +126,8 @@
widgetItemsAtRow.add(widgetItem);
containerSizeForRow = containerSize;
currentRowWidth = containerWidth;
- } else if ((currentRowWidth + containerWidth) <= rowPx
+ } else if (widgetItemsAtRow.size() < MAX_ITEMS_IN_ROW
+ && (currentRowWidth + containerWidth) <= rowPx
&& widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))
&& containerSize.equals(containerSizeForRow)) {
// Group items in the same row if
diff --git a/tests/OWNERS b/tests/OWNERS
index b5ee7d7..6b8643c 100644
--- a/tests/OWNERS
+++ b/tests/OWNERS
@@ -3,4 +3,3 @@
sunnygoyal@google.com
winsonc@google.com
hyunyoungs@google.com
-mateuszc@google.com
diff --git a/tests/shared/com/android/launcher3/testing/OWNERS b/tests/shared/com/android/launcher3/testing/OWNERS
new file mode 100644
index 0000000..02e8ebc
--- /dev/null
+++ b/tests/shared/com/android/launcher3/testing/OWNERS
@@ -0,0 +1,4 @@
+vadimt@google.com
+sunnygoyal@google.com
+winsonc@google.com
+hyunyoungs@google.com
diff --git a/tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java b/tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
index 423ca24..d2238ff 100644
--- a/tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
+++ b/tests/src/com/android/launcher3/allapps/AlphabeticalAppsListTest.java
@@ -98,7 +98,7 @@
when(mPrivateProfileManager.addPrivateSpaceHeader(any()))
.thenAnswer(answer(this::addPrivateSpaceHeader));
when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(mPrivateProfileManager.splitIntoUserInstalledAndSystemApps())
+ when(mPrivateProfileManager.splitIntoUserInstalledAndSystemApps(any()))
.thenReturn(iteminfo -> iteminfo.componentName == null
|| !iteminfo.componentName.getPackageName()
.equals("com.android.launcher3.tests.camera"));
@@ -127,7 +127,7 @@
when(mPrivateProfileManager.addSystemAppsDivider(any()))
.thenAnswer(answer(this::addSystemAppsDivider));
when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(mPrivateProfileManager.splitIntoUserInstalledAndSystemApps())
+ when(mPrivateProfileManager.splitIntoUserInstalledAndSystemApps(mContext))
.thenReturn(iteminfo -> iteminfo.componentName == null
|| !iteminfo.componentName.getPackageName()
.equals("com.android.launcher3.tests.camera"));
diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
index 2a4d21d..b6b2261 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
@@ -167,7 +167,6 @@
}
@Test
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/320703862
public void transitioningToUnlocked_resetCallsPostUnlock() throws Exception {
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
@@ -185,7 +184,6 @@
}
@Test
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
public void transitioningToLocked_resetCallsExecuteLock() throws Exception {
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
index 9363ce8..512b2ac 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
@@ -71,6 +71,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.function.Predicate;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -279,10 +280,8 @@
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
- .thenReturn(iteminfo -> iteminfo.componentName == null
- || !iteminfo.componentName.getPackageName()
- .equals(CAMERA_PACKAGE_NAME));
+ doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
+ .splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
.addPrivateSpaceHeader(any());
@@ -316,10 +315,8 @@
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
- .thenReturn(iteminfo -> iteminfo.componentName == null
- || !iteminfo.componentName.getPackageName()
- .equals(CAMERA_PACKAGE_NAME));
+ doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
+ .splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
.addPrivateSpaceHeader(any());
@@ -353,10 +350,8 @@
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
- .thenReturn(iteminfo -> iteminfo.componentName == null
- || !iteminfo.componentName.getPackageName()
- .equals(CAMERA_PACKAGE_NAME));
+ doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
+ .splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
.addPrivateSpaceHeader(any());
@@ -390,10 +385,8 @@
when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
- when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
- .thenReturn(iteminfo -> iteminfo.componentName == null
- || !iteminfo.componentName.getPackageName()
- .equals(CAMERA_PACKAGE_NAME));
+ doReturn(splitIntoUserInstalledAndSystemApps()).when(privateProfileManager)
+ .splitIntoUserInstalledAndSystemApps(any());
doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
@@ -465,4 +458,10 @@
}
return appInfos.toArray(AppInfo[]::new);
}
+
+ private Predicate<AppInfo> splitIntoUserInstalledAndSystemApps() {
+ return iteminfo -> iteminfo.componentName == null
+ || !iteminfo.componentName.getPackageName()
+ .equals(CAMERA_PACKAGE_NAME);
+ }
}
diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
index d64d096..1c41ded 100644
--- a/tests/src/com/android/launcher3/dragging/TaplDragTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
@@ -21,8 +21,6 @@
import static com.android.launcher3.util.TestConstants.AppNames.PHOTOS_APP_NAME;
import static com.android.launcher3.util.TestConstants.AppNames.STORE_APP_NAME;
import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -43,8 +41,6 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.util.TestUtil;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
-import com.android.launcher3.util.rule.TestStabilityRule;
import org.junit.Test;
@@ -67,9 +63,6 @@
*/
@Test
@PortraitLandscape
- @ScreenRecord
- // Staging; will be promoted to presubmit if stable
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
@PlatinumTest(focusArea = "launcher")
public void testDragToFolder() {
// TODO: add the use case to drag an icon to an existing folder. Currently it either fails
diff --git a/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java b/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java
index 715a1f8..7242e9c 100644
--- a/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java
+++ b/tests/src/com/android/launcher3/folder/PreviewBackgroundTest.java
@@ -30,6 +30,7 @@
import android.view.animation.PathInterpolator;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.launcher3.CellLayout;
@@ -50,7 +51,8 @@
@Mock
CellLayout mCellLayout;
- private final PreviewBackground mPreviewBackground = new PreviewBackground();
+ private final PreviewBackground mPreviewBackground =
+ new PreviewBackground(InstrumentationRegistry.getInstrumentation().getContext());
@Before
public void setUp() {
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index d3a6355..328558d 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -8,8 +8,6 @@
import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -98,7 +96,6 @@
}
@Test
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/325283522
public void testCacheUpdate_update_apps() {
// Run on model executor so that no other task runs in the middle.
runOnExecutorSync(MODEL_EXECUTOR, () -> {
@@ -129,7 +126,6 @@
}
@Test
- @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/325283522
public void testSessionUpdate_updates_pending_apps() {
// Run on model executor so that no other task runs in the middle.
runOnExecutorSync(MODEL_EXECUTOR, () -> {
diff --git a/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt b/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt
index 2e209a4..c4a4c9b 100644
--- a/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt
+++ b/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt
@@ -24,13 +24,11 @@
import com.android.launcher3.util.LauncherModelHelper
import com.android.launcher3.util.LauncherModelHelper.*
import com.android.launcher3.util.TestUtil
-import com.android.launcher3.util.rule.TestStabilityRule
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import java.util.concurrent.CountDownLatch
import org.junit.After
import org.junit.Before
-import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -58,8 +56,6 @@
TEST_ACTIVITY14
)
- @get:Rule(order = 0) val testStabilityRule = TestStabilityRule()
-
@Before
fun setUp() {
modelHelper = LauncherModelHelper()
@@ -91,9 +87,6 @@
@Test
@Throws(Exception::class)
- @TestStabilityRule.Stability(
- flavors = TestStabilityRule.LOCAL or TestStabilityRule.PLATFORM_POSTSUBMIT
- ) // b/319923578
fun folderLoadedWithHighRes_max_3x3() {
val idp = LauncherAppState.getIDP(modelHelper.sandboxContext)
idp.numFolderColumns = intArrayOf(3, 3, 3, 3)
@@ -107,9 +100,6 @@
@Test
@Throws(Exception::class)
- @TestStabilityRule.Stability(
- flavors = TestStabilityRule.LOCAL or TestStabilityRule.PLATFORM_POSTSUBMIT
- ) // b/319923578
fun folderLoadedWithHighRes_max_4x4() {
val idp = LauncherAppState.getIDP(modelHelper.sandboxContext)
idp.numFolderColumns = intArrayOf(4, 4, 4, 4)
@@ -123,10 +113,6 @@
@Test
@Throws(Exception::class)
- // Stress tests are long. We permanently demote them from presubmit to match the presubmit SLO.
- @TestStabilityRule.Stability(
- flavors = TestStabilityRule.LOCAL or TestStabilityRule.PLATFORM_POSTSUBMIT
- ) // b/319923578
fun folderLoadedWithHighRes_differentFolderConfigurations() {
val idp = LauncherAppState.getIDP(modelHelper.sandboxContext)
idp.numFolderColumns = intArrayOf(4, 3, 4, 4)
diff --git a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
index 5731e2a..28a001f 100644
--- a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
@@ -56,7 +56,7 @@
@Spy private var userManagerState: UserManagerState? = UserManagerState()
- @get:Rule val setFlagsRule = SetFlagsRule().apply { initAllFlagsToReleaseConfigDefault() }
+ @get:Rule val setFlagsRule = SetFlagsRule()
@Before
fun setup() {
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index c2e73fc..6bbcf85 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -24,18 +24,29 @@
import android.content.pm.PackageInstaller
import android.content.pm.ShortcutInfo
import android.os.UserHandle
+import android.platform.test.annotations.EnableFlags
import android.util.LongSparseArray
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING
import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherSettings.Favorites
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
+import com.android.launcher3.Utilities
import com.android.launcher3.Utilities.EMPTY_PERSON_ARRAY
+import com.android.launcher3.backuprestore.LauncherRestoreEventLogger
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_INFO
+import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_WIDGET_PROVIDER
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.PROFILE_DELETED
import com.android.launcher3.model.data.FolderInfo
import com.android.launcher3.model.data.IconRequestInfo
import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.LauncherAppWidgetInfo
+import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
+import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_UI_NOT_READY
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.pm.UserCache
import com.android.launcher3.shortcuts.ShortcutKey
@@ -43,11 +54,14 @@
import com.android.launcher3.util.PackageManagerHelper
import com.android.launcher3.util.PackageUserKey
import com.android.launcher3.util.UserIconInfo
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
import com.android.launcher3.widget.WidgetInflater
+import com.android.launcher3.widget.WidgetSections
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import org.junit.Before
import org.junit.Test
+import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.RETURNS_DEEP_STUBS
import org.mockito.Mockito.mock
@@ -56,8 +70,10 @@
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
class WorkspaceItemProcessorTest {
@@ -73,29 +89,31 @@
@Mock private lateinit var mockUserManagerState: UserManagerState
@Mock private lateinit var mockWidgetInflater: WidgetInflater
- private lateinit var intent: Intent
- private lateinit var userHandle: UserHandle
- private lateinit var iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>>
- private lateinit var componentName: ComponentName
- private lateinit var unlockedUsersArray: LongSparseArray<Boolean>
- private lateinit var keyToPinnedShortcutsMap: MutableMap<ShortcutKey, ShortcutInfo>
- private lateinit var installingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo>
- private lateinit var allDeepShortcuts: MutableList<ShortcutInfo>
+ private var intent: Intent = Intent()
+ private var mUserHandle: UserHandle = UserHandle(0)
+ private var mIconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>> = mutableListOf()
+ private var mComponentName: ComponentName = ComponentName("package", "class")
+ private var mUnlockedUsersArray: LongSparseArray<Boolean> = LongSparseArray()
+ private var mKeyToPinnedShortcutsMap: MutableMap<ShortcutKey, ShortcutInfo> = mutableMapOf()
+ private var mInstallingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = hashMapOf()
+ private var mAllDeepShortcuts: MutableList<ShortcutInfo> = mutableListOf()
+ private var mWidgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> =
+ mutableMapOf()
+ private var mPendingPackages: MutableSet<PackageUserKey> = mutableSetOf()
private lateinit var itemProcessorUnderTest: WorkspaceItemProcessor
@Before
fun setup() {
- userHandle = UserHandle(0)
+ mUserHandle = UserHandle(0)
mockIconRequestInfo = mock<IconRequestInfo<WorkspaceItemInfo>>()
- iconRequestInfos = mutableListOf(mockIconRequestInfo)
mockWorkspaceInfo = mock<WorkspaceItemInfo>()
mockBgDataModel = mock<BgDataModel>()
- componentName = ComponentName("package", "class")
- unlockedUsersArray = LongSparseArray<Boolean>(1).apply { put(101, true) }
+ mComponentName = ComponentName("package", "class")
+ mUnlockedUsersArray = LongSparseArray<Boolean>(1).apply { put(101, true) }
intent =
Intent().apply {
- component = componentName
+ component = mComponentName
`package` = "pkg"
putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "")
}
@@ -112,17 +130,17 @@
}
mockPmHelper =
mock<PackageManagerHelper>().apply {
- whenever(getAppLaunchIntent(componentName.packageName, userHandle))
+ whenever(getAppLaunchIntent(mComponentName.packageName, mUserHandle))
.thenReturn(intent)
}
mockLauncherApps =
mock<LauncherApps>().apply {
- whenever(isPackageEnabled("package", userHandle)).thenReturn(true)
- whenever(isActivityEnabled(componentName, userHandle)).thenReturn(true)
+ whenever(isPackageEnabled("package", mUserHandle)).thenReturn(true)
+ whenever(isActivityEnabled(mComponentName, mUserHandle)).thenReturn(true)
}
mockCursor =
mock(LoaderCursor::class.java, RETURNS_DEEP_STUBS).apply {
- user = userHandle
+ user = mUserHandle
itemType = ITEM_TYPE_APPLICATION
id = 1
restoreFlag = 1
@@ -137,15 +155,18 @@
mockUserCache =
mock<UserCache>().apply {
val userIconInfo =
- mock<UserIconInfo>().apply() { whenever(isPrivate).thenReturn(false) }
+ mock<UserIconInfo>().apply { whenever(isPrivate).thenReturn(false) }
whenever(getUserInfo(any())).thenReturn(userIconInfo)
}
mockUserManagerState = mock<UserManagerState>()
mockWidgetInflater = mock<WidgetInflater>()
- keyToPinnedShortcutsMap = mutableMapOf()
- installingPkgs = hashMapOf()
- allDeepShortcuts = mutableListOf()
+ mKeyToPinnedShortcutsMap = mutableMapOf()
+ mInstallingPkgs = hashMapOf()
+ mAllDeepShortcuts = mutableListOf()
+ mWidgetProvidersMap = mutableMapOf()
+ mIconRequestInfos = mutableListOf()
+ mPendingPackages = mutableSetOf()
}
/**
@@ -159,18 +180,18 @@
userCache: UserCache = mockUserCache,
userManagerState: UserManagerState = mockUserManagerState,
launcherApps: LauncherApps = mockLauncherApps,
- shortcutKeyToPinnedShortcuts: Map<ShortcutKey, ShortcutInfo> = keyToPinnedShortcutsMap,
+ shortcutKeyToPinnedShortcuts: Map<ShortcutKey, ShortcutInfo> = mKeyToPinnedShortcutsMap,
app: LauncherAppState = mockAppState,
bgDataModel: BgDataModel = mockBgDataModel,
- widgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> = mutableMapOf(),
+ widgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> = mWidgetProvidersMap,
widgetInflater: WidgetInflater = mockWidgetInflater,
pmHelper: PackageManagerHelper = mockPmHelper,
- iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>> = mutableListOf(),
+ iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>> = mIconRequestInfos,
isSdCardReady: Boolean = false,
- pendingPackages: MutableSet<PackageUserKey> = mutableSetOf(),
- unlockedUsers: LongSparseArray<Boolean> = unlockedUsersArray,
- installingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = hashMapOf(),
- allDeepShortcuts: MutableList<ShortcutInfo> = mutableListOf()
+ pendingPackages: MutableSet<PackageUserKey> = mPendingPackages,
+ unlockedUsers: LongSparseArray<Boolean> = mUnlockedUsersArray,
+ installingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = mInstallingPkgs,
+ allDeepShortcuts: MutableList<ShortcutInfo> = mAllDeepShortcuts
) =
WorkspaceItemProcessor(
c = cursor,
@@ -241,8 +262,8 @@
fun `When app has empty String target package then mark deleted`() {
// Given
- componentName = ComponentName("", "")
- intent.component = componentName
+ mComponentName = ComponentName("", "")
+ intent.component = mComponentName
intent.`package` = ""
// When
@@ -267,7 +288,7 @@
.isEqualTo(0)
// currently gets marked restored twice, although markRestore() has check for restoreFlag
verify(mockCursor, times(2)).markRestored()
- assertThat(iconRequestInfos).containsExactly(mockIconRequestInfo)
+ assertThat(mIconRequestInfos).containsExactly(mockIconRequestInfo)
verify(mockCursor).checkAndAddItem(mockWorkspaceInfo, mockBgDataModel, null)
}
@@ -277,12 +298,12 @@
// Given
mockLauncherApps =
mock<LauncherApps>().apply {
- whenever(isPackageEnabled("package", userHandle)).thenReturn(true)
- whenever(isActivityEnabled(componentName, userHandle)).thenReturn(false)
+ whenever(isPackageEnabled("package", mUserHandle)).thenReturn(true)
+ whenever(isActivityEnabled(mComponentName, mUserHandle)).thenReturn(false)
}
mockPmHelper =
mock<PackageManagerHelper>().apply {
- whenever(getAppLaunchIntent(componentName.packageName, userHandle))
+ whenever(getAppLaunchIntent(mComponentName.packageName, mUserHandle))
.thenReturn(intent)
}
@@ -295,7 +316,7 @@
.that(mockCursor.restoreFlag)
.isEqualTo(0)
verify(mockCursor.updater().put(Favorites.INTENT, intent.toUri(0))).commit()
- assertThat(iconRequestInfos).containsExactly(mockIconRequestInfo)
+ assertThat(mIconRequestInfos).containsExactly(mockIconRequestInfo)
verify(mockCursor).checkAndAddItem(mockWorkspaceInfo, mockBgDataModel, null)
}
@@ -305,12 +326,13 @@
// Given
mockLauncherApps =
mock<LauncherApps>().apply {
- whenever(isPackageEnabled("package", userHandle)).thenReturn(true)
- whenever(isActivityEnabled(componentName, userHandle)).thenReturn(false)
+ whenever(isPackageEnabled("package", mUserHandle)).thenReturn(true)
+ whenever(isActivityEnabled(mComponentName, mUserHandle)).thenReturn(false)
}
mockPmHelper =
mock<PackageManagerHelper>().apply {
- whenever(getAppLaunchIntent(componentName.packageName, userHandle)).thenReturn(null)
+ whenever(getAppLaunchIntent(mComponentName.packageName, mUserHandle))
+ .thenReturn(null)
}
// When
@@ -349,20 +371,20 @@
whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
}
val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user)
- keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
- iconRequestInfos = mutableListOf()
+ mKeyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
+ mIconRequestInfos = mutableListOf()
// When
itemProcessorUnderTest =
- createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
+ createWorkspaceItemProcessorUnderTest(allDeepShortcuts = mAllDeepShortcuts)
itemProcessorUnderTest.processItem()
// Then
assertWithMessage("item restoreFlag should be set to 0")
.that(mockCursor.restoreFlag)
.isEqualTo(0)
- assertThat(iconRequestInfos).isEmpty()
- assertThat(allDeepShortcuts).containsExactly(expectedShortcutInfo)
+ assertThat(mIconRequestInfos).isEmpty()
+ assertThat(mAllDeepShortcuts).containsExactly(expectedShortcutInfo)
verify(mockCursor).markRestored()
verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull())
}
@@ -372,8 +394,8 @@
// Given
mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT
- iconRequestInfos = mutableListOf()
- keyToPinnedShortcutsMap = hashMapOf()
+ mIconRequestInfos = mutableListOf()
+ mKeyToPinnedShortcutsMap = hashMapOf()
// When
itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
@@ -383,7 +405,7 @@
assertWithMessage("item restoreFlag should be set to 0")
.that(mockCursor.restoreFlag)
.isEqualTo(0)
- assertThat(iconRequestInfos).isEmpty()
+ assertThat(mIconRequestInfos).isEmpty()
verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
verify(mockCursor)
.markDeleted(
@@ -408,25 +430,25 @@
whenever(disabledReason).thenReturn(0)
whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
}
- iconRequestInfos = mutableListOf()
+ mIconRequestInfos = mutableListOf()
// Make sure shortcuts map has expected key from expected package
- intent.`package` = componentName.packageName
+ intent.`package` = mComponentName.packageName
val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user)
- keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
+ mKeyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
// set intent package back to null to test scenario
intent.`package` = null
// When
itemProcessorUnderTest =
- createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
+ createWorkspaceItemProcessorUnderTest(allDeepShortcuts = mAllDeepShortcuts)
itemProcessorUnderTest.processItem()
// Then
assertWithMessage("item restoreFlag should be set to 0")
.that(mockCursor.restoreFlag)
.isEqualTo(0)
- assertThat(iconRequestInfos).isEmpty()
- assertThat(allDeepShortcuts).containsExactly(expectedShortcutInfo)
+ assertThat(mIconRequestInfos).isEmpty()
+ assertThat(mAllDeepShortcuts).containsExactly(expectedShortcutInfo)
verify(mockCursor).markRestored()
verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull())
}
@@ -478,4 +500,346 @@
assertThat(actualFolderInfo.options).isEqualTo(expectedFolderInfo.options)
verify(mockCursor).checkAndAddItem(actualFolderInfo, mockBgDataModel, null)
}
+
+ @Test
+ fun `When valid TYPE_REAL App Widget then add item`() {
+
+ // Given
+ val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
+ val expectedComponentName =
+ ComponentName.unflattenFromString(expectedProvider)!!.flattenToString()
+ val expectedRestoreStatus = FLAG_UI_NOT_READY
+ val expectedAppWidgetId = 0
+ mockCursor.apply {
+ itemType = ITEM_TYPE_APPWIDGET
+ user = mUserHandle
+ restoreFlag = FLAG_UI_NOT_READY
+ container = CONTAINER_DESKTOP
+ whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
+ whenever(appWidgetProvider).thenReturn(expectedProvider)
+ whenever(appWidgetId).thenReturn(expectedAppWidgetId)
+ whenever(spanX).thenReturn(2)
+ whenever(spanY).thenReturn(1)
+ whenever(options).thenReturn(0)
+ whenever(appWidgetSource).thenReturn(20)
+ whenever(applyCommonProperties(any())).thenCallRealMethod()
+ whenever(
+ updater()
+ .put(Favorites.APPWIDGET_PROVIDER, expectedComponentName)
+ .put(Favorites.APPWIDGET_ID, expectedAppWidgetId)
+ .put(Favorites.RESTORED, expectedRestoreStatus)
+ .commit()
+ )
+ .thenReturn(1)
+ }
+ val expectedWidgetInfo =
+ LauncherAppWidgetInfo().apply {
+ appWidgetId = expectedAppWidgetId
+ providerName = ComponentName.unflattenFromString(expectedProvider)
+ restoreStatus = expectedRestoreStatus
+ }
+ val expectedWidgetProviderInfo =
+ mock<LauncherAppWidgetProviderInfo>().apply {
+ provider = ComponentName.unflattenFromString(expectedProvider)
+ whenever(user).thenReturn(mUserHandle)
+ }
+ val inflationResult =
+ WidgetInflater.InflationResult(
+ type = WidgetInflater.TYPE_REAL,
+ widgetInfo = expectedWidgetProviderInfo
+ )
+ mockWidgetInflater =
+ mock<WidgetInflater>().apply {
+ whenever(inflateAppWidget(any())).thenReturn(inflationResult)
+ }
+ val packageUserKey = PackageUserKey("com.google.android.testApp", mUserHandle)
+ mInstallingPkgs[packageUserKey] = PackageInstaller.SessionInfo()
+
+ // When
+ itemProcessorUnderTest =
+ createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
+ itemProcessorUnderTest.processItem()
+
+ // Then
+ val widgetInfoCaptor = ArgumentCaptor.forClass(LauncherAppWidgetInfo::class.java)
+ verify(mockCursor).checkAndAddItem(widgetInfoCaptor.capture(), eq(mockBgDataModel))
+ val actualWidgetInfo = widgetInfoCaptor.value
+ with(actualWidgetInfo) {
+ assertThat(providerName).isEqualTo(expectedWidgetInfo.providerName)
+ assertThat(restoreStatus).isEqualTo(expectedWidgetInfo.restoreStatus)
+ assertThat(targetComponent).isEqualTo(expectedWidgetInfo.targetComponent)
+ assertThat(appWidgetId).isEqualTo(expectedWidgetInfo.appWidgetId)
+ }
+ val expectedComponentKey =
+ ComponentKey(expectedWidgetProviderInfo.provider, expectedWidgetProviderInfo.user)
+ assertThat(mWidgetProvidersMap[expectedComponentKey]).isEqualTo(expectedWidgetProviderInfo)
+ }
+
+ @Test
+ fun `When valid Pending Widget then checkAndAddItem`() {
+
+ // Given
+ mockCursor =
+ mock<LoaderCursor>().apply {
+ itemType = ITEM_TYPE_APPWIDGET
+ id = 1
+ user = UserHandle(1)
+ restoreFlag = FLAG_UI_NOT_READY
+ container = CONTAINER_DESKTOP
+ whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
+ whenever(appWidgetProvider)
+ .thenReturn("com.google.android.testApp/com.android.testApp.testAppProvider")
+ whenever(appWidgetId).thenReturn(0)
+ whenever(spanX).thenReturn(2)
+ whenever(spanY).thenReturn(1)
+ whenever(options).thenReturn(0)
+ whenever(appWidgetSource).thenReturn(20)
+ whenever(applyCommonProperties(any())).thenCallRealMethod()
+ }
+ val mockProviderInfo =
+ mock<LauncherAppWidgetProviderInfo>().apply {
+ provider = mock()
+ whenever(user).thenReturn(UserHandle(1))
+ }
+ val inflationResult =
+ WidgetInflater.InflationResult(
+ type = WidgetInflater.TYPE_PENDING,
+ widgetInfo = mockProviderInfo
+ )
+ mockWidgetInflater =
+ mock<WidgetInflater>().apply {
+ whenever(inflateAppWidget(any())).thenReturn(inflationResult)
+ }
+ itemProcessorUnderTest =
+ createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
+
+ // When
+ itemProcessorUnderTest.processItem()
+
+ // Then
+ verify(mockCursor).checkAndAddItem(any(), any())
+ }
+
+ @Test
+ fun `When Unrestored Pending App Widget then mark deleted`() {
+
+ // Given
+ val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
+ mockCursor =
+ mock<LoaderCursor>().apply {
+ itemType = ITEM_TYPE_APPWIDGET
+ id = 1
+ user = UserHandle(1)
+ restoreFlag = FLAG_UI_NOT_READY
+ container = CONTAINER_DESKTOP
+ whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
+ whenever(appWidgetProvider).thenReturn(expectedProvider)
+ whenever(appWidgetId).thenReturn(0)
+ whenever(spanX).thenReturn(2)
+ whenever(spanY).thenReturn(1)
+ whenever(options).thenReturn(0)
+ whenever(appWidgetSource).thenReturn(20)
+ whenever(applyCommonProperties(any())).thenCallRealMethod()
+ }
+ mInstallingPkgs = hashMapOf()
+ val inflationResult =
+ WidgetInflater.InflationResult(type = WidgetInflater.TYPE_PENDING, widgetInfo = null)
+ mockWidgetInflater =
+ mock<WidgetInflater>().apply {
+ whenever(inflateAppWidget(any())).thenReturn(inflationResult)
+ }
+ val expectedComponentName = ComponentName.unflattenFromString(expectedProvider)
+
+ // When
+ itemProcessorUnderTest =
+ createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
+ itemProcessorUnderTest.processItem()
+
+ // Then
+ verify(mockCursor)
+ .markDeleted(
+ "processWidget: Unrestored Pending widget removed: id=1, appWidgetId=0, component=$expectedComponentName, restoreFlag:=4",
+ LauncherRestoreEventLogger.RestoreError.APP_NOT_INSTALLED
+ )
+ }
+
+ @Test
+ fun `When Pending App Widget has not started restore then update db and add item`() {
+
+ val mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .mockStatic(WidgetSections::class.java)
+ .startMocking()
+ try {
+ // Given
+ val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
+ val expectedComponentName =
+ ComponentName.unflattenFromString(expectedProvider)!!.flattenToString()
+ val expectedRestoreStatus = FLAG_UI_NOT_READY or FLAG_RESTORE_STARTED
+ val expectedAppWidgetId = 0
+ mockCursor.apply {
+ itemType = ITEM_TYPE_APPWIDGET
+ user = mUserHandle
+ restoreFlag = FLAG_UI_NOT_READY
+ container = CONTAINER_DESKTOP
+ whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
+ whenever(appWidgetProvider).thenReturn(expectedProvider)
+ whenever(appWidgetId).thenReturn(expectedAppWidgetId)
+ whenever(spanX).thenReturn(2)
+ whenever(spanY).thenReturn(1)
+ whenever(options).thenReturn(0)
+ whenever(appWidgetSource).thenReturn(20)
+ whenever(applyCommonProperties(any())).thenCallRealMethod()
+ whenever(
+ updater()
+ .put(Favorites.APPWIDGET_PROVIDER, expectedComponentName)
+ .put(Favorites.APPWIDGET_ID, expectedAppWidgetId)
+ .put(Favorites.RESTORED, expectedRestoreStatus)
+ .commit()
+ )
+ .thenReturn(1)
+ }
+ val inflationResult =
+ WidgetInflater.InflationResult(
+ type = WidgetInflater.TYPE_PENDING,
+ widgetInfo = null
+ )
+ mockWidgetInflater =
+ mock<WidgetInflater>().apply {
+ whenever(inflateAppWidget(any())).thenReturn(inflationResult)
+ }
+ val packageUserKey = PackageUserKey("com.google.android.testApp", mUserHandle)
+ mInstallingPkgs[packageUserKey] = PackageInstaller.SessionInfo()
+
+ // When
+ itemProcessorUnderTest =
+ createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
+ itemProcessorUnderTest.processItem()
+
+ // Then
+ val expectedWidgetInfo =
+ LauncherAppWidgetInfo().apply {
+ appWidgetId = expectedAppWidgetId
+ providerName = ComponentName.unflattenFromString(expectedProvider)
+ restoreStatus = expectedRestoreStatus
+ }
+ verify(
+ mockCursor
+ .updater()
+ .put(Favorites.APPWIDGET_PROVIDER, expectedProvider)
+ .put(Favorites.APPWIDGET_ID, expectedAppWidgetId)
+ .put(Favorites.RESTORED, expectedRestoreStatus)
+ )
+ .commit()
+ val widgetInfoCaptor = ArgumentCaptor.forClass(LauncherAppWidgetInfo::class.java)
+ verify(mockCursor).checkAndAddItem(widgetInfoCaptor.capture(), eq(mockBgDataModel))
+ val actualWidgetInfo = widgetInfoCaptor.value
+ with(actualWidgetInfo) {
+ assertThat(providerName).isEqualTo(expectedWidgetInfo.providerName)
+ assertThat(restoreStatus).isEqualTo(expectedWidgetInfo.restoreStatus)
+ assertThat(targetComponent).isEqualTo(expectedWidgetInfo.targetComponent)
+ assertThat(appWidgetId).isEqualTo(expectedWidgetInfo.appWidgetId)
+ }
+ } finally {
+ mockitoSession.finishMocking()
+ }
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_SUPPORT_FOR_ARCHIVING)
+ fun `When Archived Pending App Widget then checkAndAddItem`() {
+ val mockitoSession =
+ ExtendedMockito.mockitoSession().mockStatic(Utilities::class.java).startMocking()
+ try {
+ // Given
+ val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
+ val expectedComponentName = ComponentName.unflattenFromString(expectedProvider)
+ val expectedPackage = expectedComponentName!!.packageName
+ mockPmHelper =
+ mock<PackageManagerHelper>().apply {
+ whenever(isAppArchived(expectedPackage)).thenReturn(true)
+ }
+ mockCursor =
+ mock<LoaderCursor>().apply {
+ itemType = ITEM_TYPE_APPWIDGET
+ id = 1
+ user = UserHandle(1)
+ restoreFlag = FLAG_UI_NOT_READY
+ container = CONTAINER_DESKTOP
+ whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
+ whenever(appWidgetProvider).thenReturn(expectedProvider)
+ whenever(appWidgetId).thenReturn(0)
+ whenever(spanX).thenReturn(2)
+ whenever(spanY).thenReturn(1)
+ whenever(options).thenReturn(0)
+ whenever(appWidgetSource).thenReturn(20)
+ whenever(applyCommonProperties(any())).thenCallRealMethod()
+ }
+ mInstallingPkgs = hashMapOf()
+ val inflationResult =
+ WidgetInflater.InflationResult(
+ type = WidgetInflater.TYPE_PENDING,
+ widgetInfo = null
+ )
+ mockWidgetInflater =
+ mock<WidgetInflater>().apply {
+ whenever(inflateAppWidget(any())).thenReturn(inflationResult)
+ }
+ itemProcessorUnderTest =
+ createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
+
+ // When
+ itemProcessorUnderTest.processItem()
+
+ // Then
+ verify(mockCursor).checkAndAddItem(any(), any())
+ } finally {
+ mockitoSession.finishMocking()
+ }
+ }
+
+ @Test
+ fun `When widget inflation result is TYPE_DELETE then mark deleted`() {
+ // Given
+ val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
+ val expectedComponentName = ComponentName.unflattenFromString(expectedProvider)
+ val expectedPackage = expectedComponentName!!.packageName
+ mockPmHelper =
+ mock<PackageManagerHelper>().apply {
+ whenever(isAppArchived(expectedPackage)).thenReturn(true)
+ }
+ mockCursor =
+ mock<LoaderCursor>().apply {
+ itemType = ITEM_TYPE_APPWIDGET
+ id = 1
+ user = UserHandle(1)
+ container = CONTAINER_DESKTOP
+ whenever(spanX).thenReturn(2)
+ whenever(spanY).thenReturn(1)
+ whenever(appWidgetProvider).thenReturn(expectedProvider)
+ whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
+ whenever(applyCommonProperties(any())).thenCallRealMethod()
+ }
+ mInstallingPkgs = hashMapOf()
+ val inflationResult =
+ WidgetInflater.InflationResult(
+ type = WidgetInflater.TYPE_DELETE,
+ widgetInfo = null,
+ reason = "test_delete_reason",
+ restoreErrorType = MISSING_WIDGET_PROVIDER
+ )
+ mockWidgetInflater =
+ mock<WidgetInflater>().apply {
+ whenever(inflateAppWidget(any())).thenReturn(inflationResult)
+ }
+ itemProcessorUnderTest =
+ createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
+
+ // When
+ itemProcessorUnderTest.processItem()
+
+ // Then
+ verify(mockCursor).markDeleted(inflationResult.reason, inflationResult.restoreErrorType)
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 9c289d6..99e15ba 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -15,10 +15,7 @@
*/
package com.android.launcher3.ui;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
-import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -29,7 +26,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import android.app.ActivityOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -575,21 +571,6 @@
true /* newTask */);
}
- /** alternative of startAppFast where app is guaranteed to launch in fullscreen mode */
- public static void startAppFastInFullscreen(String packageName) {
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
- options.setLaunchDisplayId(DEFAULT_DISPLAY);
- options.setLaunchActivityType(ACTIVITY_TYPE_STANDARD);
-
- startIntent(
- getInstrumentation().getContext().getPackageManager().getLaunchIntentForPackage(
- packageName),
- By.pkg(packageName).depth(0),
- true /* newTask */,
- options);
- }
-
public static void startTestActivity(String activityName, String activityLabel) {
final String packageName = getAppPackageName();
final Intent intent = getInstrumentation().getContext().getPackageManager().
@@ -625,8 +606,7 @@
false /* newTask */);
}
- private static void startIntent(
- Intent intent, BySelector selector, boolean newTask, ActivityOptions options) {
+ private static void startIntent(Intent intent, BySelector selector, boolean newTask) {
intent.addCategory(Intent.CATEGORY_LAUNCHER);
if (newTask) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
@@ -634,12 +614,7 @@
intent.addFlags(
Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
}
-
- if (options != null) {
- getInstrumentation().getTargetContext().startActivity(intent, options.toBundle());
- } else {
- getInstrumentation().getTargetContext().startActivity(intent);
- }
+ getInstrumentation().getTargetContext().startActivity(intent);
assertTrue("App didn't start: " + selector,
TestHelpers.wait(Until.hasObject(selector), DEFAULT_UI_TIMEOUT));
@@ -650,10 +625,6 @@
DEFAULT_ACTIVITY_TIMEOUT, launcherInstrumentation);
}
- private static void startIntent(Intent intent, BySelector selector, boolean newTask) {
- startIntent(intent, selector, newTask, null);
- }
-
public static ActivityInfo resolveSystemAppInfo(String category) {
return getInstrumentation().getContext().getPackageManager().resolveActivity(
new Intent(Intent.ACTION_MAIN).addCategory(category),
diff --git a/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java b/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
index 3411fc1..e49f2b1 100644
--- a/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
+++ b/tests/src/com/android/launcher3/ui/ActivityAllAppsContainerViewTest.java
@@ -69,13 +69,7 @@
private WorkProfileManager mWorkManager;
private Context mContext;
- @Rule public final SetFlagsRule mSetFlagsRule = getFlagsRule();
-
- private SetFlagsRule getFlagsRule() {
- SetFlagsRule flagsRule = new SetFlagsRule();
- flagsRule.initAllFlagsToReleaseConfigDefault();
- return flagsRule;
- }
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setUp() {
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
index 342eedf..4a67600 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
@@ -21,8 +21,9 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.Launcher;
+import com.android.launcher3.util.rule.ScreenRecordRule.KeepRecordOnSuccess;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,6 +32,7 @@
@RunWith(AndroidJUnit4.class)
public class TaplTestsLauncher3Test extends AbstractLauncherUiTest<Launcher> {
+ @KeepRecordOnSuccess
@ScreenRecord // b/322823478
@Test
public void testDevicePressMenu() throws Exception {
diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
index e08d37c..70a3dd0 100644
--- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
@@ -45,6 +45,7 @@
import com.android.launcher3.allapps.WorkProfileManager;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule.KeepRecordOnSuccess;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import com.android.launcher3.util.rule.TestStabilityRule.Stability;
@@ -196,6 +197,7 @@
}
+ @KeepRecordOnSuccess
@ScreenRecord // b/322823478
@Test
public void testEdu() {
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
index 7845dec..9dbd866 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
@@ -86,7 +86,6 @@
* A custom shortcut is a 1x1 widget that launches a specific intent when user tap on it.
* Custom shortcuts are replaced by deep shortcuts after api 25.
*/
- @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
@Test
@PortraitLandscape
public void testDragCustomShortcut() throws Throwable {
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java
index 9afde0d..490cff2 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java
@@ -29,6 +29,7 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.LauncherLayoutBuilder;
import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
import org.junit.After;
import org.junit.Before;
@@ -67,6 +68,7 @@
* move between workspaces. After, make sure we can launch an app from the Workspace.
* @throws Exception if we can't set the defaults icons that will appear at the beginning.
*/
+ @ScreenRecord // b/331261431
@Test
public void testWorkspace() throws Exception {
// Set workspace that includes the chrome Activity app icon on the hotseat.
diff --git a/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java b/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java
index 7a5cf2c..ff96afb 100644
--- a/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java
+++ b/tests/src/com/android/launcher3/util/rule/ScreenRecordRule.java
@@ -49,6 +49,9 @@
return base;
}
+ final Boolean keepRecordOnSuccess = description.getAnnotation(KeepRecordOnSuccess.class)
+ != null;
+
return new Statement() {
@Override
public void evaluate() throws Throwable {
@@ -70,7 +73,7 @@
device.executeShellCommand("kill -INT " + screenRecordPid);
Log.e(TAG, "Screenrecord captured at: " + outputFile);
output.close();
- if (success) {
+ if (success && !keepRecordOnSuccess) {
automation.executeShellCommand("rm " + outputFile);
}
}
@@ -85,4 +88,14 @@
@Target(ElementType.METHOD)
public @interface ScreenRecord {
}
+
+
+ /**
+ * Interface to indicate that we should keep the screen record even if the test succeeds, use
+ * sparingly since it uses a lof of memory.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public @interface KeepRecordOnSuccess {
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
index 2c16e01..daddd2f 100644
--- a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
@@ -16,6 +16,8 @@
package com.android.launcher3.tapl;
+import android.graphics.Point;
+
import androidx.test.uiautomator.UiObject2;
/**
@@ -57,4 +59,16 @@
private void verifyDividerIsPresent() {
mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID);
}
+
+ /**
+ * Verifies that a user installed app is present above the divider.
+ */
+ public void verifyInstalledAppIsPresent(String appName) {
+ HomeAppIcon appIcon = mLauncher.getAllApps().getAppIcon(appName);
+ final Point iconCenter = appIcon.mObject.getVisibleCenter();
+ UiObject2 divider = mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID);
+ final Point dividerCenter = divider.getVisibleCenter();
+ mLauncher.assertTrue("Installed App: " + appName + " is not above the divider",
+ iconCenter.y < dividerCenter.y);
+ }
}