Merge "Turn ENABLE_PIP_APP_ICON_OVERLAY on by default" into tm-qpr-dev
diff --git a/OWNERS b/OWNERS
index 962d63a..2d7a014 100644
--- a/OWNERS
+++ b/OWNERS
@@ -29,6 +29,7 @@
sihua@google.com
sunnygoyal@google.com
tracyzhou@google.com
+tsuharesu@google.com
twickham@google.com
vadimt@google.com
victortulias@google.com
@@ -36,4 +37,4 @@
xuqiu@google.com
per-file FeatureFlags.java, globs = set noparent
-per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com
+per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com, captaincole@google.com
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index c8a7d85..c638ba9 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -130,7 +130,7 @@
optional int32 cardinality = 2;
}
-// Next value 43
+// Next value 44
enum Attribute {
UNKNOWN = 0;
DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat
@@ -176,6 +176,7 @@
ALL_APPS_SEARCH_RESULT_ASSISTANT_MEMORY = 31;
ALL_APPS_SEARCH_RESULT_VIDEO = 41;
ALL_APPS_SEARCH_RESULT_SYSTEM_POINTER = 42;
+ ALL_APPS_SEARCH_RESULT_EDUCARD = 43;
// Web suggestions provided by AGA
ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39;
diff --git a/quickstep/res/layout/taskbar_all_apps_button.xml b/quickstep/res/layout/taskbar_all_apps_button.xml
index 6b665e5..c50db2e 100644
--- a/quickstep/res/layout/taskbar_all_apps_button.xml
+++ b/quickstep/res/layout/taskbar_all_apps_button.xml
@@ -21,5 +21,4 @@
android:layout_height="@dimen/taskbar_icon_min_touch_size"
android:contentDescription="@string/all_apps_button_label"
android:backgroundTint="@android:color/transparent"
- android:icon="@drawable/ic_all_apps_button"
/>
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 01f7612..126b22d 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Speld vas"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vormvry"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen onlangse items nie"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programgebruikinstellings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Vee alles uit"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Onlangse programme"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index d309f87..3269543 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ሰካ"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ነፃ ቅጽ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ምንም የቅርብ ጊዜ ንጥሎች የሉም"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"የመተግበሪያ አጠቃቀም ቅንብሮች"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ሁሉንም አጽዳ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"የቅርብ ጊዜ መተግበሪያዎች"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 4ac1c67..b064608 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"تثبيت"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"شكل مجاني"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ليست هناك عناصر تم استخدامها مؤخرًا"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"إعدادات استخدام التطبيق"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"محو الكل"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"التطبيقات المستخدمة مؤخرًا"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"شريط التنقل"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"الانتقال إلى يمين الشاشة أو أعلاها"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"الانتقال إلى يسار الشاشة أو أسفلها"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index c2a0679..e5123a0 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"পিন"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"কোনো শেহতীয়া বস্তু নাই"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"আটাইবোৰ মচক"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"শেহতীয়া এপসমূহ"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 0368018..e0c3b26 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Sancın"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Sərbəst rejim"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Son elementlər yoxdur"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tətbiq istifadə ayarları"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hamısını silin"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Son tətbiqlər"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 6129a1d..b5db6cc 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Podešavanja korišćenja aplikacije"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index c01ce84..bb7087f 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Замацаваць"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Адвольная форма"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Няма новых элементаў"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налады выкарыстання праграмы"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ачысціць усё"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Нядаўнія праграмы"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панэль навігацыі"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перамясціць уверх/улева"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 5b99616..234b12b 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Фиксиране"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Свободна форма"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Няма скорошни елементи"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки за използването на приложенията"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Изчистване на всички"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Скорошни приложения"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 7f2799c..2e2ff63 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"পিন করুন"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ফ্রি-ফর্ম"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"কোনো সাম্প্রতিক আইটেম নেই"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"অ্যাপ ব্যবহারের সেটিংস"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"সবকিছু খালি করুন"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"সম্প্রতি ব্যবহৃত অ্যাপ"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index f247c9f..5c8a887 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodan oblik"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke korištenja aplikacije"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 828b5b7..4407cdd 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixa"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Format lliure"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hi ha cap element recent"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuració d\'ús d\'aplicacions"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Esborra-ho tot"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicacions recents"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index d7e73d5..6a38bce 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Připnout"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Neomezený režim"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Žádné nedávné položky"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavení využití aplikací"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Vymazat vše"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Poslední aplikace"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index cfeb02b..a0e636e 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fastgør"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Frit format"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nye elementer"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Indstillinger for appforbrug"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ryd alt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Seneste apps"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index 0dba565..fe149e1 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixieren"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform-Modus"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Kürzlich geöffnete Apps"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Navigationsleiste"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Nach oben / Nach links verschieben"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Nach unten / Nach rechts verschieben"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# weitere App anzeigen.}other{# weitere Apps anzeigen.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 8588465..05c00fb 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Καρφίτσωμα"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Ελεύθερη μορφή"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Δεν υπάρχουν πρόσφατα στοιχεία"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ρυθμίσεις χρήσης εφαρμογής"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Διαγραφή όλων"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Πρόσφατες εφαρμογές"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index b3d595d..542083c 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index efcda32..5afc013 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -22,6 +22,7 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
+ <string name="recents_empty_desktop_message" msgid="1358240150311509733">"No desktop items"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index b3d595d..542083c 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index b3d595d..542083c 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 7f02ebd..1b9e5d1 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -22,6 +22,7 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
+ <string name="recents_empty_desktop_message" msgid="1358240150311509733">"No desktop items"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 7106959..1ddb2df 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración de uso de la app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recientes"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover a la parte superior o izquierda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover a la parte inferior o derecha"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 1cd2431..f0433af 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No hay nada reciente"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicaciones recientes"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 238ddb7..0e9c09e 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kinnita"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vabavorm"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hiljutisi üksusi pole"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Rakenduse kasutuse seaded"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Sule kõik"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Hiljutised rakendused"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index c31eb18..cbb1af8 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ainguratu"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Modu librea"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ez dago azkenaldi honetako ezer"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Aplikazioen erabileraren ezarpenak"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Garbitu guztiak"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Azken aplikazioak"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 6383712..dd64195 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"پین"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"بدون موارد اخیر"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"تنظیمات استفاده از برنامه"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"پاک کردن همه"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"برنامههای اخیر"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index f7a4fa3..d517cb7 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kiinnitä"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vapaamuotoinen"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ei viimeaikaisia kohteita"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Sovelluksen käyttöasetukset"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Poista kaikki"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Viimeisimmät sovellukset"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 56b77ed..13cc7ac 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Épingler"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forme libre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Aucun élément récent"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres d\'utilisation de l\'application"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Applications récentes"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 0fe9308..16266f8 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Épingler"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Format libre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Aucun élément récent"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres de consommation de l\'application"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Applications récentes"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barre de navigation"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Déplacer en haut ou à gauche"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer en bas ou à droite"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre appli.}one{Afficher # autre appli.}other{Afficher # autre applis.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 6f6dd1c..a51ca6a 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma libre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Non hai elementos recentes"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Barra de navegación"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover á parte superior ou á esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover á parte inferior ou á dereita"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 66b6169..e925a6a 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"પિન કરો"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ફ્રિફોર્મ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"તાજેતરની કોઈ આઇટમ નથી"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ઍપ વપરાશનું સેટિંગ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"બધું સાફ કરો"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"તાજેતરની ઍપ"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"નૅવિગેશન બાર"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"સૌથી ઉપર ડાબી બાજુએ ખસેડો"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"સૌથી નીચે જમણી બાજુએ ખસેડો"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 989d351..90bb17a 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -22,6 +22,7 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करना"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ़्रीफ़ॉर्म"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"हाल ही में इस्तेमाल किया गया कोई ऐप्लिकेशन नहीं है"</string>
+ <string name="recents_empty_desktop_message" msgid="1358240150311509733">"डेस्कटॉप पर कोई आइटम नहीं मिला"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सभी ऐप्लिकेशन बंद करें"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index dd8ca31..66835a4 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Prikvači"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Izbriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 5946a7e..10086da 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Kitűzés"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Szabad forma"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nincsenek mostanában használt elemek"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Alkalmazáshasználati beállítások"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Összes törlése"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Legutóbbi alkalmazások"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 96db2d7..d0d24bb 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ամրացնել"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Կամայական ձև"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Վերջին տարրեր չկան"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Հավելվածի օգտագործման կարգավորումներ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Փակել բոլորը"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Վերջին օգտագործած հավելվածները"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Նավիգացիայի գոտի"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Տեղափոխել վերևի ձախ անկյուն"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Տեղափոխել ներքևի աջ անկյուն"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index a961b28..ed9d0ff 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Sematkan"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Format bebas"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item yang baru dibuka"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setelan penggunaan aplikasi"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hapus semua"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikasi terbaru"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Menu navigasi"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Pindahkan ke atas/kiri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pindahkan ke bawah/kanan"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tampilkan # aplikasi lain.}other{Tampilkan # aplikasi lain.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 8bf2e0e..ffa899f 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Festa"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Frjálst snið"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Engin nýleg atriði"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Notkunarstillingar forrits"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hreinsa allt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nýleg forrit"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 94707e8..0cf9ec2 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Blocca su schermo"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma libera"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nessun elemento recente"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Impostazioni di utilizzo delle app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Cancella tutto"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"App recenti"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index c6a97f2..94978ea 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"הצמדה"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"מצב חופשי"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"אין פריטים אחרונים"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"הגדרות שימוש באפליקציה"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ניקוי הכול"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"אפליקציות אחרונות"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index c5b588b..72d2409 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"フリーフォーム"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"最近のアイテムはありません"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"アプリの使用状況の設定"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"すべてクリア"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使ったアプリ"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index f6c3aac..fc791b5 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ჩამაგრება"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"თავისუფალი ფორმა"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ბოლოს გამოყენებული ერთეულები არ არის"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"აპების გამოყენების პარამეტრები"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ყველას გასუფთავება"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ბოლოდროინდელი აპები"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 1f7f69c..414aa17 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Бекіту"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Еркін форма"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Соңғы элементтер жоқ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Қолданбаны пайдалану параметрлері"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Барлығын өшіру"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Соңғы пайдаланылған қолданбалар"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Навигация жолағы"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жоғары/солға жылжыту"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index 20cdb56..3bbc946 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ខ្ទាស់"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"មុខងារទម្រង់សេរី"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"មិនមានធាតុថ្មីៗទេ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ការកំណត់ការប្រើប្រាស់កម្មវិធី"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"សម្អាតទាំងអស់"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"កម្មវិធីថ្មីៗ"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 58e172c..5beb0d0 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ಪಿನ್ ಮಾಡಿ"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ಮುಕ್ತಸ್ವರೂಪ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ಆ್ಯಪ್ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 9f8dea5..2d463d9 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"고정"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"자유 형식"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"최근 항목이 없습니다."</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"앱 사용 설정"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"모두 삭제"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"최근 앱"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 7d7a021..b3ebffb 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Кадап коюу"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Эркин форма режими"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Акыркы колдонмолор жок"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Колдонмону пайдалануу параметрлери"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Баарын тазалоо"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Акыркы колдонмолор"</string>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index e40c543..0e7af50 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ປັກໝຸດ"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ຮູບແບບອິດສະຫລະ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ບໍ່ມີລາຍການຫຼ້າສຸດ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ການຕັ້ງຄ່າການນຳໃຊ້ແອັບ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ລຶບລ້າງທັງໝົດ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ແອັບຫຼ້າສຸດ"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index ee3e312..6db6b03 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Prisegti"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Laisva forma"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nėra jokių naujausių elementų"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programos naudojimo nustatymai"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Išvalyti viską"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Naujausios programos"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index fd251ab..540a084 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Piespraust"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Brīva forma"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nav nesenu vienumu."</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Pēdējās izmantotās lietotnes"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index dd24098..588d333 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Закачи"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Нема неодамнешни ставки"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Поставки за користење на апликациите"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Избриши ги сите"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Неодамнешни апликации"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Лента за навигација"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести долу десно"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index d84ea16..08b166f 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"പിൻ ചെയ്യുക"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ഫ്രീഫോം"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ആപ്പ് ഉപയോഗ ക്രമീകരണം"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"എല്ലാം മായ്ക്കുക"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"സമീപകാല ആപ്പുകൾ"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index acdb8b1..cbf6b77 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Бэхлэх"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Чөлөөтэй хувьсах"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Сүүлийн үеийн зүйл алга"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Апп ашиглалтын тохиргоо"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг устгах"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Саяхны аппууд"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 3000f2f..edd6024 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करा"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ्रीफॉर्म"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"कोणतेही अलीकडील आयटम नाहीत"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अॅप वापर सेटिंग्ज"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"नेव्हिगेशन बार"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सर्वात वरती/डावीकडे हलवा"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"तळाशी/उजवीकडे हलवा"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{आणखी # अॅप दाखवा.}other{आणखी # अॅप्स दाखवा.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index edb36f1..72a831a 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Semat"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Bentuk bebas"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Tiada item terbaharu"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tetapan penggunaan apl"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Kosongkan semua"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apl terbaharu"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 632c0be..6c01fba 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ပင်ထိုးရန်"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"အလွတ်ပုံစံ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"အက်ပ်အသုံးပြုမှု ဆက်တင်များ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးရှင်းရန်"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"လတ်တလောသုံး အက်ပ်များ"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index b2d36ba..cdfc476 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fest"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nylige elementer"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Innstillinger for appbruk"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Fjern alt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nylige apper"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 26d2e16..b8d952d 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"पिन गर्नुहोस्"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"फ्रिफर्म"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"हालसालैको कुनै पनि वस्तु छैन"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"एपको उपयोगका सेटिङहरू"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"सबै मेटाउनुहोस्"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"हालसालैका एपहरू"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index b7a4998..1c13ac0 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Vastzetten"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Vrije vorm"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen recente items"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Instellingen voor app-gebruik"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Alles wissen"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recente apps"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 8605b34..7711b7c 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ପିନ୍"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ଫ୍ରିଫର୍ମ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"କୌଣସି ସାମ୍ପ୍ରତିକ ଆଇଟମ୍ ନାହିଁ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ଆପ ବ୍ୟବହାର ସେଟିଂସ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ବର୍ତ୍ତମାନର ଆପ୍"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 50191be..cd1a5a5 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ਪਿੰਨ ਕਰੋ"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"ਫ੍ਰੀਫਾਰਮ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ਐਪ ਵਰਤੋਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ਹਾਲੀਆ ਐਪਾਂ"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"ਨੈਵੀਗੇਸ਼ਨ ਵਾਲੀ ਪੱਟੀ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ਸਿਖਰਲੇ/ਖੱਬੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ਹੇਠਾਂ/ਸੱਜੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 024e8fe..db7c9cf 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Przypnij"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Tryb dowolny"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Brak ostatnich elementów"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ustawienia użycia aplikacji"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Wyczyść wszystko"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Ostatnie aplikacje"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 88b5858..25a3570 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Definições de utilização de aplicações"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 1f5ba9a..a6d26e4 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configurações de uso do app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Apps recentes"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index e33584f..e785d03 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixează"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formă liberă"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Niciun element recent"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplicații recente"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 83b43b2..55c9b15 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Закрепить"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Произвольная форма"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Здесь пока ничего нет."</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки использования приложения"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Очистить все"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Недавние приложения"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 3d807a0..30c83df 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"අමුණන්න"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"මෑත අයිතම නැත"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"යෙදුම් භාවිත සැකසීම්"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"සියල්ල හිස් කරන්න"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"මෑත යෙදුම්"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 9690125..e008a42 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pripnúť"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Voľný režim"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Žiadne nedávne položky"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavenia využívania aplikácie"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Vymazať všetko"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedávne aplikácie"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 1ba97e9..66238b2 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Pripni"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Prosta oblika"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ni nedavnih elementov"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavitve uporabe aplikacij"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Počisti vse"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 4fd06a6..9cdff52 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Gozhdo"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Formë e lirë"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nuk ka asnjë artikull të fundit"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikacionet e fundit"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 4966a49..a090988 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Закачи"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Слободни облик"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Нема недавних ставки"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Подешавања коришћења апликације"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Обриши све"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Недавне апликације"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index c29f8fd..c3ce758 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fäst"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Listan med de senaste åtgärderna är tom"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Inställningar för appanvändning"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Rensa alla"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Senaste apparna"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 6ba4542..772b58a 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Bandika"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Muundo huru"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Hakuna vipengee vya hivi karibuni"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mipangilio ya matumizi ya programu"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Ondoa zote"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Programu za hivi karibuni"</string>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 4c479b0..9b602c0 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"பின் செய்தல்"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"குறிப்பிட்ட வடிவமில்லாத பயன்முறை"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"சமீபத்தியவை எதுவுமில்லை"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ஆப்ஸ் உபயோக அமைப்புகள்"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"எல்லாம் அழி"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"சமீபத்திய ஆப்ஸ்"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 885d8ee..e78dde1 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"పిన్ చేయి"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"సంప్రదాయేతర"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"యాప్ వినియోగ సెట్టింగ్లు"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"అన్నీ తీసివేయండి"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ఇటీవలి యాప్లు"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index a3d4342..4784735 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"ปักหมุด"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"รูปแบบอิสระ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ไม่มีรายการล่าสุด"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"การตั้งค่าการใช้แอป"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"ล้างทั้งหมด"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"แอปล่าสุด"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"แถบนำทาง"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ย้ายไปที่ด้านบนหรือด้านซ้าย"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ย้ายไปที่ด้านล่างหรือด้านขวา"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 47e2e1f..4120e88 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"I-pin"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Walang kamakailang item"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Mga kamakailang app"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 892b0c5..003eede 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Sabitle"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Serbest çalışma"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yeni öğe yok"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Son uygulamalar"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 029fc9d..7b5922d 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Закріпити"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Довільна форма"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Немає нещодавніх додатків"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налаштування використання додатка"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Очистити все"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Нещодавні додатки"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Панель навігації"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перемістити вгору або вліво"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перемістити вниз або вправо"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}"</string>
+ <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>
</resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 4f9f6e4..c58b72d 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"پن کریں"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"فری فارم"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"کوئی حالیہ آئٹم نہیں"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ایپ کے استعمال کی ترتیبات"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"سبھی کو صاف کریں"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"حالیہ ایپس"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index ca6527d..39949b0 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -22,6 +22,7 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Mahkamlash"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Erkin shakl"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
+ <string name="recents_empty_desktop_message" msgid="1358240150311509733">"Ish stoli elementlari topilmadi"</string>
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ilovadan foydalanish sozlamalari"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Hammasini tozalash"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Yaqinda ishlatilgan ilovalar"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 249c006..178e6fe 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Ghim"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"Dạng tự do"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Không có mục gần đây nào"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<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>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Ứng dụng gần đây"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Thanh điều hướng"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Chuyển lên trên cùng/sang bên trái"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Chuyển xuống dưới cùng/sang bên phải"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <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>
+ <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>
</resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index b16940a..731c6c7 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"自由窗口"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"近期没有任何内容"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"应用使用设置"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近用过的应用"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index 4ca142d..aeccfd2 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"最近沒有任何項目"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使用的應用程式"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index ff94081..748581f 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"最近沒有任何項目"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"最近使用的應用程式"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index e76c6d1..06ef5f6 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -22,6 +22,8 @@
<string name="recent_task_option_pin" msgid="7929860679018978258">"Phina"</string>
<string name="recent_task_option_freeform" msgid="48863056265284071">"I-Freeform"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Azikho izinto zakamuva"</string>
+ <!-- no translation found for recents_empty_desktop_message (1358240150311509733) -->
+ <skip />
<string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Izilungiselelo zokusetshenziswa kohlelo lokusebenza"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Sula konke"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Izinhlelo zokusebenza zakamuva"</string>
@@ -117,8 +119,6 @@
<string name="taskbar_phone_a11y_title" msgid="4933360237131229395">"Ibha yokufuna"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Hamba phezulu/kwesokunxele"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Hamba phansi/kwesokudla"</string>
- <!-- no translation found for quick_switch_overflow (6935266023013283353) -->
- <skip />
- <!-- no translation found for quick_switch_split_task (5598194724255333896) -->
- <skip />
+ <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>
+ <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>
</resources>
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index a91507c..d581582 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -49,4 +49,6 @@
<item name="config_wallpaperMaxScale" format="float" type="dimen">
@*android:dimen/config_wallpaperMaxScale
</item>
+
+ <string name="setup_wizard_pkg" translatable="false" />
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index bd71a9f..126ab7c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -286,6 +286,8 @@
<dimen name="taskbar_back_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_home_button_left_margin_kids">48dp</dimen>
<dimen name="taskbar_icon_size_kids">32dp</dimen>
+ <dimen name="taskbar_all_apps_button_translation_x_offset">6dp</dimen>
+
<!-- Transient taskbar -->
<dimen name="transient_taskbar_size">72dp</dimen>
@@ -295,6 +297,7 @@
<dimen name="transient_taskbar_shadow_blur">40dp</dimen>
<dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
<dimen name="transient_taskbar_stashed_size">32dp</dimen>
+ <dimen name="transient_taskbar_all_apps_button_translation_x_offset">4dp</dimen>
<!-- An additional touch slop to prevent x-axis movement during the swipe up to show taskbar -->
<dimen name="transient_taskbar_clamped_offset_bound">16dp</dimen>
<!-- Taskbar swipe up thresholds -->
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 347c492..9ff2cfc 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -112,7 +112,6 @@
import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.model.data.ItemInfo;
@@ -557,11 +556,7 @@
final boolean scrimEnabled = ENABLE_SCRIM_FOR_APP_LAUNCH.get();
if (scrimEnabled) {
- boolean useTaskbarColor = mDeviceProfile.isTaskbarPresentInApps
- && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
- int scrimColor = useTaskbarColor
- ? mLauncher.getResources().getColor(R.color.taskbar_background)
- : Themes.getAttrColor(mLauncher, R.attr.overviewScrimColor);
+ int scrimColor = Themes.getAttrColor(mLauncher, R.attr.overviewScrimColor);
int scrimColorTrans = ColorUtils.setAlphaComponent(scrimColor, 0);
int[] colors = isAppOpening
? new int[]{scrimColorTrans, scrimColor}
@@ -575,29 +570,6 @@
scrim.setDuration(CONTENT_SCRIM_DURATION);
scrim.setInterpolator(DEACCEL_1_5);
- if (useTaskbarColor) {
- // Hide the taskbar background color since it would duplicate the scrim.
- scrim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- LauncherTaskbarUIController taskbarUIController =
- mLauncher.getTaskbarUIController();
- if (taskbarUIController != null) {
- taskbarUIController.forceHideBackground(true);
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- LauncherTaskbarUIController taskbarUIController =
- mLauncher.getTaskbarUIController();
- if (taskbarUIController != null) {
- taskbarUIController.forceHideBackground(false);
- }
- }
- });
- }
-
launcherAnimator.play(scrim);
}
}
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 9f3be69..0dde1bd 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -118,7 +118,7 @@
private void sendEvent(AppTarget target, LauncherAtom.ItemInfo locationInfo, int eventId,
int targetPredictor) {
// TODO: remove the running test check when b/231648228 is fixed.
- if (target != null && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (target != null && !Utilities.isRunningInTestHarness()) {
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(getContainer(locationInfo))
.build();
diff --git a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
index 20c8c44..2b6f77f 100644
--- a/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
+++ b/quickstep/src/com/android/launcher3/splitscreen/SplitShortcut.kt
@@ -32,8 +32,8 @@
import com.android.launcher3.views.ActivityContext
/**
- * Shortcut to allow starting split. Default interaction for [onClick] is to launch
- * split selection mode
+ * Shortcut to allow starting split. Default interaction for [onClick] is to launch split selection
+ * mode
*/
abstract class SplitShortcut<T>(
iconResId: Int,
diff --git a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
index ff7c138..c165750 100644
--- a/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/FallbackTaskbarUIController.java
@@ -82,7 +82,8 @@
public Animator createAnimToRecentsState(RecentsState toState, long duration) {
boolean useStashedLauncherState = toState.hasOverviewActions();
boolean stashedLauncherState =
- useStashedLauncherState && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
+ useStashedLauncherState && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()
+ && toState == RecentsState.MODAL_TASK;
TaskbarStashController stashController = mControllers.taskbarStashController;
// Set both FLAG_IN_STASHED_LAUNCHER_STATE and FLAG_IN_APP to ensure the state is respected.
// For all other states, just use the current stashed-in-app setting (e.g. if long clicked).
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 3046076..ac2c44b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -41,7 +41,6 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
@@ -86,7 +85,6 @@
};
// Initialized in init.
- private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
private TaskbarKeyguardController mKeyguardController;
private final TaskbarLauncherStateController
mTaskbarLauncherStateController = new TaskbarLauncherStateController();
@@ -100,8 +98,6 @@
super.init(taskbarControllers);
mTaskbarLauncherStateController.init(mControllers, mLauncher);
- mTaskbarOverrideBackgroundAlpha = mControllers.taskbarDragLayerController
- .getOverrideBackgroundAlpha();
mLauncher.setTaskbarUIController(this);
mKeyguardController = taskbarControllers.taskbarKeyguardController;
@@ -202,15 +198,7 @@
*/
public Animator createAnimToLauncher(@NonNull LauncherState toState,
@NonNull RecentsAnimationCallbacks callbacks, long duration) {
- AnimatorSet set = new AnimatorSet();
- Animator taskbarState = mTaskbarLauncherStateController
- .createAnimToLauncher(toState, callbacks, duration);
- long halfDuration = Math.round(duration * 0.5f);
- Animator translation =
- mControllers.taskbarTranslationController.createAnimToLauncher(halfDuration);
-
- set.playTogether(taskbarState, translation);
- return set;
+ return mTaskbarLauncherStateController.createAnimToLauncher(toState, callbacks, duration);
}
public boolean isDraggingItem() {
@@ -256,13 +244,6 @@
}
/**
- * Sets whether the background behind the taskbar/nav bar should be hidden.
- */
- public void forceHideBackground(boolean forceHide) {
- mTaskbarOverrideBackgroundAlpha.updateValue(forceHide ? 0 : 1);
- }
-
- /**
* Starts a Taskbar EDU flow, if the user should see one upon launching an application.
*/
public void showEduOnAppLaunch() {
@@ -291,7 +272,7 @@
* Returns {@code true} if a Taskbar education should be shown on application launch.
*/
public boolean shouldShowEduOnAppLaunch() {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
return false;
}
@@ -318,21 +299,6 @@
instanceId);
}
- @Override
- public void setSystemGestureInProgress(boolean inProgress) {
- super.setSystemGestureInProgress(inProgress);
- if (DisplayController.isTransientTaskbar(mLauncher)) {
- forceHideBackground(false);
- return;
- }
- if (!FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- // Launcher's ScrimView will draw the background throughout the gesture. But once the
- // gesture ends, start drawing taskbar's background again since launcher might stop
- // drawing.
- forceHideBackground(inProgress);
- }
- }
-
/**
* Animates Taskbar elements during a transition to a Launcher state that should use in-app
* layouts.
@@ -401,10 +367,6 @@
public void dumpLogs(String prefix, PrintWriter pw) {
super.dumpLogs(prefix, pw);
- pw.println(String.format(
- "%s\tmTaskbarOverrideBackgroundAlpha=%.2f",
- prefix,
- mTaskbarOverrideBackgroundAlpha.value));
pw.println(String.format("%s\tTaskbar in-app display progress:", prefix));
mTaskbarInAppDisplayProgressMultiProp.dump(
prefix + "\t",
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index ab52adb..2864ac7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -24,7 +24,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
-import static com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS;
+import static com.android.launcher3.Utilities.isRunningInTestHarness;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
@@ -45,6 +45,7 @@
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
@@ -88,6 +89,7 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.PackageManagerHelper;
@@ -105,7 +107,6 @@
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
-import java.util.function.Consumer;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
@@ -218,8 +219,8 @@
new TaskbarScrimViewController(this, taskbarScrimView),
new TaskbarUnfoldAnimationController(this, unfoldTransitionProgressProvider,
mWindowManager,
- new RotationChangeProvider(WindowManagerGlobal.getWindowManagerService(), this,
- getMainExecutor())),
+ new RotationChangeProvider(c.getSystemService(DisplayManager.class), this,
+ getMainThreadHandler())),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this),
@@ -336,8 +337,7 @@
int windowFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
- if (DisplayController.isTransientTaskbar(this)
- && !IS_RUNNING_IN_TEST_HARNESS) {
+ if (DisplayController.isTransientTaskbar(this) && !isRunningInTestHarness()) {
windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
}
@@ -876,9 +876,14 @@
* as if the user tapped on it (preserving the split pair). Otherwise, launch it normally
* (potentially breaking a split pair).
*/
- private void launchFromTaskbarPreservingSplitIfVisible(RecentsView recents, ItemInfo info) {
+ private void launchFromTaskbarPreservingSplitIfVisible(@Nullable RecentsView recents,
+ ItemInfo info) {
+ if (recents == null) {
+ return;
+ }
+ ComponentKey componentToBeLaunched = new ComponentKey(info.getTargetComponent(), info.user);
recents.getSplitSelectController().findLastActiveTaskAndRunCallback(
- info.getTargetComponent(),
+ componentToBeLaunched,
foundTask -> {
if (foundTask != null) {
TaskView foundTaskView =
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
index 2bfc7dd..1a54576 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
@@ -41,12 +41,15 @@
public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2;
// Taskbar EDU overlay is open above the Taskbar. */
public static final int FLAG_AUTOHIDE_SUSPEND_EDU_OPEN = 1 << 3;
+ // Taskbar in immersive mode in overview
+ public static final int FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER = 1 << 4;
@IntDef(flag = true, value = {
FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
FLAG_AUTOHIDE_SUSPEND_DRAGGING,
FLAG_AUTOHIDE_SUSPEND_TOUCHING,
FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
+ FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AutohideSuspendFlag {}
@@ -92,6 +95,10 @@
return mAutohideSuspendFlags != 0;
}
+ public boolean isSuspendedForTransientTaskbarInOverview() {
+ return (mAutohideSuspendFlags & FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER) != 0;
+ }
+
@Override
public void dumpLogs(String prefix, PrintWriter pw) {
pw.println(prefix + "TaskbarAutohideSuspendController:");
@@ -106,6 +113,8 @@
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING");
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING");
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_EDU_OPEN, "FLAG_AUTOHIDE_SUSPEND_EDU_OPEN");
+ appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER,
+ "FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER");
return str.toString();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index 37d9090..e00bc59 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -79,6 +79,7 @@
/**
* Sets the roundness of the round corner above Taskbar. No effect on transient Taskkbar.
+ *
* @param cornerRoundness 0 has no round corner, 1 has complete round corner.
*/
fun setCornerRoundness(cornerRoundness: Float) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 267bee1..7c4071f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -127,10 +127,6 @@
return mAssistantBgTaskbar;
}
- public AnimatedFloat getOverrideBackgroundAlpha() {
- return mBgOverride;
- }
-
public AnimatedFloat getTaskbarBackgroundOffset() {
return mBgOffset;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 00dfaf2..bc582e2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -28,7 +28,6 @@
import com.airbnb.lottie.model.KeyPath
import com.android.launcher3.R
import com.android.launcher3.Utilities
-import com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
@@ -56,7 +55,8 @@
class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
LoggableTaskbarController {
- private val isTooltipEnabled = !IS_RUNNING_IN_TEST_HARNESS && ENABLE_TASKBAR_EDU_TOOLTIP.get()
+ private val isTooltipEnabled: Boolean
+ get() = !Utilities.isRunningInTestHarness() && ENABLE_TASKBAR_EDU_TOOLTIP.get()
private val isOpen: Boolean
get() = tooltip?.isOpen ?: false
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index a6f59fe..f32e025 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -51,8 +51,11 @@
onTaskbarWindowHeightOrInsetsChanged()
}
private val gestureNavSettingsObserver =
- GestureNavigationSettingsObserver(context.mainThreadHandler, context,
- this::onTaskbarWindowHeightOrInsetsChanged)
+ GestureNavigationSettingsObserver(
+ context.mainThreadHandler,
+ context,
+ this::onTaskbarWindowHeightOrInsetsChanged
+ )
// Initialized in init.
private lateinit var controllers: TaskbarControllers
@@ -71,13 +74,7 @@
ITYPE_LEFT_GESTURES,
ITYPE_RIGHT_GESTURES,
),
- intArrayOf(
- SOURCE_FRAME,
- SOURCE_FRAME,
- SOURCE_FRAME,
- SOURCE_DISPLAY,
- SOURCE_DISPLAY
- )
+ intArrayOf(SOURCE_FRAME, SOURCE_FRAME, SOURCE_FRAME, SOURCE_DISPLAY, SOURCE_DISPLAY)
)
onTaskbarWindowHeightOrInsetsChanged()
@@ -102,7 +99,7 @@
)
val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
- val res = context.resources;
+ val res = context.resources
for (provider in windowLayoutParams.providedInsets) {
if (
provider.type == ITYPE_EXTRA_NAVIGATION_BAR ||
@@ -157,6 +154,7 @@
/**
* @return [Insets] where the [bottomInset] is either used as a bottom inset or
+ *
* ```
* right/left inset if using 3 button nav
* ```
@@ -174,20 +172,25 @@
/**
* Sets {@param providesInsetsTypes} as the inset types provided by {@param params}.
+ *
* @param params The window layout params.
* @param providesInsetsTypes The inset types we would like this layout params to provide.
*/
- fun setProvidesInsetsTypes(params: WindowManager.LayoutParams, providesInsetsTypes: IntArray,
- providesInsetsSources: IntArray) {
+ fun setProvidesInsetsTypes(
+ params: WindowManager.LayoutParams,
+ providesInsetsTypes: IntArray,
+ providesInsetsSources: IntArray
+ ) {
params.providedInsets = arrayOfNulls<InsetsFrameProvider>(providesInsetsTypes.size)
for (i in providesInsetsTypes.indices) {
- params.providedInsets[i] = InsetsFrameProvider(providesInsetsTypes[i],
- providesInsetsSources[i], null, null)
+ params.providedInsets[i] =
+ InsetsFrameProvider(providesInsetsTypes[i], providesInsetsSources[i], null, null)
}
}
/**
* Called to update the touchable insets.
+ *
* @see InternalInsetsInfo.setTouchableInsets
*/
fun updateInsetsTouchability(insetsInfo: ViewTreeObserver.InternalInsetsInfo) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 0b86155..5ac0570 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -433,6 +433,14 @@
});
animatorSet.play(stashAnimator);
}
+
+ if (isAnimatingToLauncher() || mLauncherState == LauncherState.NORMAL) {
+ // Translate back to 0 at a shorter or same duration as the icon alignment animation.
+ // This ensures there is no jump after switching to hotseat, e.g. when swiping up from
+ // overview to home. Currently we do duration / 2 just to make it feel snappier.
+ animatorSet.play(mControllers.taskbarTranslationController
+ .createAnimToResetTranslation(duration / 2));
+ }
}
private boolean isInLauncher() {
@@ -460,7 +468,7 @@
updateIconAlphaForHome(taskbarWillBeVisible ? 1 : 0);
// Sync the first frame where we swap taskbar and hotseat.
- if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (firstFrameVisChanged && mCanSyncViews && !Utilities.isRunningInTestHarness()) {
ViewRootSync.synchronizeNextDraw(mLauncher.getHotseat(),
mControllers.taskbarActivityContext.getDragLayer(),
() -> {});
@@ -471,6 +479,7 @@
if (mControllers.taskbarActivityContext.isDestroyed()) {
Log.e("b/260135164", "updateIconAlphaForHome is called after Taskbar is destroyed",
new Exception());
+ return;
}
mIconAlphaForHome.setValue(alpha);
boolean hotseatVisible = alpha == 0
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 4110822..8c91833 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -130,10 +130,10 @@
? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
: null;
int configDiff = mOldConfig.diff(newConfig);
+ int configDiffForRecreate = configDiff;
int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
| ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE
| ActivityInfo.CONFIG_SCREEN_SIZE;
- boolean requiresRecreate = (configDiff & configsRequiringRecreate) != 0;
if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
&& mTaskbarActivityContext != null && dp != null
&& !isPhoneMode(dp)) {
@@ -146,12 +146,19 @@
int oldWidth = isOrientationChange ? oldDp.heightPx : oldDp.widthPx;
int oldHeight = isOrientationChange ? oldDp.widthPx : oldDp.heightPx;
if (dp.widthPx == oldWidth && dp.heightPx == oldHeight) {
- configDiff &= ~ActivityInfo.CONFIG_SCREEN_SIZE;
- requiresRecreate = (configDiff & configsRequiringRecreate) != 0;
+ configDiffForRecreate &= ~ActivityInfo.CONFIG_SCREEN_SIZE;
+ }
+ }
+ if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0) {
+ // Only recreate for theme changes, not other UI mode changes such as docking.
+ int oldUiNightMode = (mOldConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
+ int newUiNightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
+ if (oldUiNightMode == newUiNightMode) {
+ configDiffForRecreate &= ~ActivityInfo.CONFIG_UI_MODE;
}
}
- if (requiresRecreate) {
+ if ((configDiffForRecreate & configsRequiringRecreate) != 0) {
recreateTaskbar();
} else {
// Config change might be handled without re-creating the taskbar
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 50f5d9e..babafd5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -297,7 +297,7 @@
}
return supportsVisualStashing()
&& isInApp()
- && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || mEnableManualStashingDuringTests)
+ && (!Utilities.isRunningInTestHarness() || mEnableManualStashingDuringTests)
&& !DisplayController.isTransientTaskbar(mActivity);
}
@@ -460,7 +460,9 @@
return;
}
- if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()) {
+ if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()
+ && !mControllers.taskbarAutohideSuspendController
+ .isSuspendedForTransientTaskbarInOverview()) {
// Avoid stashing if autohide is currently suspended.
return;
}
@@ -721,7 +723,7 @@
}
}
play(as, mControllers.taskbarViewController
- .createRevealAnimToIsStashed(isStashed, isInApp()), 0, duration, EMPHASIZED);
+ .createRevealAnimToIsStashed(isStashed), 0, duration, EMPHASIZED);
if (skipInterpolator != null) {
as.setInterpolator(skipInterpolator);
@@ -955,6 +957,8 @@
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAGS_IN_APP)) {
notifyStashChange(/* visible */ hasAnyFlag(FLAGS_IN_APP),
/* stashed */ isStashedInApp());
+ mControllers.taskbarAutohideSuspendController.updateFlag(
+ TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER, !isInApp());
}
if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) {
if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL)) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index a6b2a8a..062b4ce 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -135,9 +135,9 @@
}
/**
- * Returns an animation to reset the taskbar translation for animation back to launcher.
+ * Returns an animation to reset the taskbar translation to {@code 0}.
*/
- public ObjectAnimator createAnimToLauncher(long duration) {
+ public ObjectAnimator createAnimToResetTranslation(long duration) {
ObjectAnimator animator = ObjectAnimator.ofFloat(mTranslationYForSwipe, VALUE, 0);
animator.setInterpolator(Interpolators.LINEAR);
animator.setDuration(duration);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 3479255..b552e9b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -30,16 +30,15 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
-import com.android.systemui.shared.recents.model.Task;
import java.io.PrintWriter;
-import java.util.function.Consumer;
/**
* Base class for providing different taskbar UI
@@ -189,8 +188,12 @@
if (recentsView == null) {
return;
}
+
+ ComponentKey componentToBeStaged = new ComponentKey(
+ splitSelectSource.itemInfo.getTargetComponent(),
+ splitSelectSource.itemInfo.user);
recentsView.getSplitSelectController().findLastActiveTaskAndRunCallback(
- splitSelectSource.intent.getComponent(),
+ componentToBeStaged,
foundTask -> {
splitSelectSource.alreadyRunningTaskId = foundTask == null
? INVALID_TASK_ID
@@ -206,8 +209,9 @@
*/
public void triggerSecondAppForSplit(ItemInfoWithIcon info, Intent intent, View startingView) {
RecentsView recents = getRecentsView();
+ ComponentKey secondAppComponent = new ComponentKey(info.getTargetComponent(), info.user);
recents.getSplitSelectController().findLastActiveTaskAndRunCallback(
- info.getTargetComponent(),
+ secondAppComponent,
foundTask -> {
if (foundTask != null) {
TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index c1e85aa..0b275a8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -89,6 +89,8 @@
private float mTransientTaskbarMinWidth;
+ private float mTransientTaskbarAllAppsButtonTranslationXOffset;
+
public TaskbarView(@NonNull Context context) {
this(context, null);
}
@@ -108,9 +110,14 @@
mActivityContext = ActivityContext.lookupContext(context);
mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds();
Resources resources = getResources();
+ boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext);
mIsRtl = Utilities.isRtl(resources);
mTransientTaskbarMinWidth = mContext.getResources().getDimension(
R.dimen.transient_taskbar_min_width);
+ mTransientTaskbarAllAppsButtonTranslationXOffset =
+ resources.getDimension(isTransientTaskbar
+ ? R.dimen.transient_taskbar_all_apps_button_translation_x_offset
+ : R.dimen.taskbar_all_apps_button_translation_x_offset);
int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
int actualIconSize = mActivityContext.getDeviceProfile().iconSizePx;
@@ -130,9 +137,12 @@
if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
.inflate(R.layout.taskbar_all_apps_button, this, false);
+ mAllAppsButton.setIconDrawable(resources.getDrawable(isTransientTaskbar
+ ? R.drawable.ic_transient_taskbar_all_apps_button
+ : R.drawable.ic_taskbar_all_apps_button));
mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
- mAllAppsButton.setForegroundTint(mActivityContext.getColor(
- DisplayController.isTransientTaskbar(mActivityContext)
+ mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
+ mAllAppsButton.setForegroundTint(mActivityContext.getColor(isTransientTaskbar
? R.color.all_apps_button_color
: R.color.all_apps_button_color_dark));
@@ -276,6 +286,8 @@
}
if (mAllAppsButton != null) {
+ mAllAppsButton.setTranslationXForTaskbarAllAppsIcon(getChildCount() > 0
+ ? mTransientTaskbarAllAppsButtonTranslationXOffset : 0f);
addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
// if only all apps button present, don't include divider view.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index c708838..2f8cae8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -17,6 +17,8 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.anim.AnimatedFloat.VALUE;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
@@ -26,13 +28,15 @@
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
+import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_ALIGNMENT_ANIM;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_REVEAL_ANIM;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.graphics.Rect;
-import android.util.FloatProperty;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
@@ -42,10 +46,10 @@
import androidx.core.graphics.ColorUtils;
import androidx.core.view.OneShotPreDrawListener;
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
+import com.android.launcher3.Reorderable;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.AnimatedFloat;
@@ -55,7 +59,6 @@
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
@@ -64,6 +67,7 @@
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.MultiPropertyFactory;
+import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.MultiValueAlpha;
import java.io.PrintWriter;
@@ -303,7 +307,7 @@
* @param isStashed When true, the icon crops vertically to the size of the stashed handle.
* When false, the reverse happens.
*/
- public AnimatorSet createRevealAnimToIsStashed(boolean isStashed, boolean isInApp) {
+ public AnimatorSet createRevealAnimToIsStashed(boolean isStashed) {
AnimatorSet as = new AnimatorSet();
Rect stashedBounds = new Rect();
@@ -317,6 +321,10 @@
for (int i = numChildren - 1; i >= 0; i--) {
View child = mTaskbarView.getChildAt(i);
+ if (child == mTaskbarView.getQsb()) {
+ continue;
+ }
+
// Crop the icons to/from the nav handle shape.
as.play(createRevealAnimForView(child, isStashed));
@@ -333,18 +341,34 @@
croppedTransX = newLeft - iconLeft;
}
- as.play(ObjectAnimator.ofFloat(child, ICON_REVEAL_TRANSLATE_X, isStashed
- ? new float[] {croppedTransX}
- : new float[] {croppedTransX, 0}));
-
float croppedTransY = child.getHeight() - stashedBounds.height();
- as.play(ObjectAnimator.ofFloat(child, ICON_REVEAL_TRANSLATE_Y, isStashed
- ? new float[] {croppedTransY}
- : new float[] {croppedTransY, 0}));
- as.addListener(forEndCallback(() -> {
- ICON_REVEAL_TRANSLATE_X.set(child, 0f);
- ICON_REVEAL_TRANSLATE_Y.set(child, 0f);
- }));
+ if (child instanceof Reorderable) {
+ MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
+
+ as.play(ObjectAnimator.ofFloat(mtd.getTranslationX(INDEX_TASKBAR_REVEAL_ANIM),
+ MULTI_PROPERTY_VALUE, isStashed
+ ? new float[] {croppedTransX}
+ : new float[] {croppedTransX, 0}));
+ as.play(ObjectAnimator.ofFloat(mtd.getTranslationX(INDEX_TASKBAR_REVEAL_ANIM),
+ MULTI_PROPERTY_VALUE, isStashed
+ ? new float[] {croppedTransY}
+ : new float[] {croppedTransY, 0}));
+ as.addListener(forEndCallback(() ->
+ mtd.setTranslation(INDEX_TASKBAR_REVEAL_ANIM, 0, 0)));
+ } else {
+ as.play(ObjectAnimator.ofFloat(child,
+ VIEW_TRANSLATE_X, isStashed
+ ? new float[] {croppedTransX}
+ : new float[] {croppedTransX, 0}));
+ as.play(ObjectAnimator.ofFloat(child,
+ VIEW_TRANSLATE_Y, isStashed
+ ? new float[] {croppedTransY}
+ : new float[] {croppedTransY, 0}));
+ as.addListener(forEndCallback(() -> {
+ child.setTranslationX(0);
+ child.setTranslationY(0);
+ }));
+ }
}
return as;
}
@@ -430,14 +454,14 @@
float childCenter = (child.getLeft() + child.getRight()) / 2f;
float halfQsbIconWidthDiff =
(launcherDp.hotseatQsbWidth - taskbarDp.iconSizePx) / 2f;
- setter.addFloat(child, ICON_TRANSLATE_X,
+ setter.addFloat(child, VIEW_TRANSLATE_X,
isRtl ? -halfQsbIconWidthDiff : halfQsbIconWidthDiff,
hotseatIconCenter - childCenter, interpolator);
float scale = ((float) taskbarDp.iconSizePx) / launcherDp.hotseatQsbVisualHeight;
setter.addFloat(child, SCALE_PROPERTY, scale, 1f, interpolator);
- setter.setFloat(child, ICON_TRANSLATE_Y, mTaskbarBottomMargin, interpolator);
+ setter.setFloat(child, VIEW_TRANSLATE_Y, mTaskbarBottomMargin, interpolator);
if (mIsHotseatIconOnTopWhenAligned) {
setter.addFloat(child, VIEW_ALPHA, 0f, 1f,
@@ -474,10 +498,18 @@
+ hotseatCellSize / 2f;
float childCenter = (child.getLeft() + child.getRight()) / 2f;
- setter.setFloat(child, ICON_TRANSLATE_X, hotseatIconCenter - childCenter, interpolator);
+ if (child instanceof Reorderable) {
+ MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
- setter.setFloat(child, ICON_TRANSLATE_Y, mTaskbarBottomMargin, interpolator);
-
+ setter.setFloat(mtd.getTranslationX(INDEX_TASKBAR_ALIGNMENT_ANIM),
+ MULTI_PROPERTY_VALUE, hotseatIconCenter - childCenter, interpolator);
+ setter.setFloat(mtd.getTranslationX(INDEX_TASKBAR_ALIGNMENT_ANIM),
+ MULTI_PROPERTY_VALUE, mTaskbarBottomMargin, interpolator);
+ } else {
+ setter.setFloat(child, VIEW_TRANSLATE_X,
+ hotseatIconCenter - childCenter, interpolator);
+ setter.setFloat(child, VIEW_TRANSLATE_Y, mTaskbarBottomMargin, interpolator);
+ }
setter.setFloat(child, SCALE_PROPERTY, scaleUp, interpolator);
}
@@ -662,107 +694,4 @@
mControllers.uiController.onIconLayoutBoundsChanged();
}
}
-
- public static final FloatProperty<View> ICON_TRANSLATE_X =
- new FloatProperty<View>("taskbarAlignmentTranslateX") {
-
- @Override
- public void setValue(View view, float v) {
- if (view instanceof BubbleTextView) {
- ((BubbleTextView) view).setTranslationXForTaskbarAlignmentAnimation(v);
- } else if (view instanceof FolderIcon) {
- ((FolderIcon) view).setTranslationXForTaskbarAlignmentAnimation(v);
- } else {
- view.setTranslationX(v);
- }
- }
-
- @Override
- public Float get(View view) {
- if (view instanceof BubbleTextView) {
- return ((BubbleTextView) view)
- .getTranslationXForTaskbarAlignmentAnimation();
- } else if (view instanceof FolderIcon) {
- return ((FolderIcon) view).getTranslationXForTaskbarAlignmentAnimation();
- }
- return view.getTranslationX();
- }
- };
-
- public static final FloatProperty<View> ICON_TRANSLATE_Y =
- new FloatProperty<View>("taskbarAlignmentTranslateY") {
-
- @Override
- public void setValue(View view, float v) {
- if (view instanceof BubbleTextView) {
- ((BubbleTextView) view).setTranslationYForTaskbarAlignmentAnimation(v);
- } else if (view instanceof FolderIcon) {
- ((FolderIcon) view).setTranslationYForTaskbarAlignmentAnimation(v);
- } else {
- view.setTranslationY(v);
- }
- }
-
- @Override
- public Float get(View view) {
- if (view instanceof BubbleTextView) {
- return ((BubbleTextView) view)
- .getTranslationYForTaskbarAlignmentAnimation();
- } else if (view instanceof FolderIcon) {
- return ((FolderIcon) view).getTranslationYForTaskbarAlignmentAnimation();
- }
- return view.getTranslationY();
- }
- };
-
- public static final FloatProperty<View> ICON_REVEAL_TRANSLATE_X =
- new FloatProperty<View>("taskbarRevealTranslateX") {
-
- @Override
- public void setValue(View view, float v) {
- if (view instanceof BubbleTextView) {
- ((BubbleTextView) view).setTranslationXForTaskbarRevealAnimation(v);
- } else if (view instanceof FolderIcon) {
- ((FolderIcon) view).setTranslationXForTaskbarRevealAnimation(v);
- } else {
- view.setTranslationX(v);
- }
- }
-
- @Override
- public Float get(View view) {
- if (view instanceof BubbleTextView) {
- return ((BubbleTextView) view).getTranslationXForTaskbarRevealAnimation();
- } else if (view instanceof FolderIcon) {
- return ((FolderIcon) view).getTranslationXForTaskbarRevealAnimation();
- }
- return view.getTranslationX();
- }
- };
-
- public static final FloatProperty<View> ICON_REVEAL_TRANSLATE_Y =
- new FloatProperty<View>("taskbarRevealTranslateY") {
-
- @Override
- public void setValue(View view, float v) {
- if (view instanceof BubbleTextView) {
- ((BubbleTextView) view).setTranslationYForTaskbarRevealAnimation(v);
- } else if (view instanceof FolderIcon) {
- ((FolderIcon) view).setTranslationYForTaskbarRevealAnimation(v);
- } else {
- view.setTranslationY(v);
- }
- }
-
- @Override
- public Float get(View view) {
- if (view instanceof BubbleTextView) {
- return ((BubbleTextView) view).getTranslationYForTaskbarRevealAnimation();
- } else if (view instanceof FolderIcon) {
- return ((FolderIcon) view).getTranslationYForTaskbarRevealAnimation();
- }
- return view.getTranslationY();
- }
- };
-
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index 7a5deb7..5eb240e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -35,7 +35,7 @@
* Controls Taskbar behavior while Voice Interaction Window (assistant) is showing. Specifically:
* - We always hide the taskbar icons or stashed handle, whichever is currently showing.
* - For persistent taskbar, we also move the taskbar background to a new window/layer
- * (TYPE_APPLICATION_OVERLAY) which is behind the assistant.
+ * (TYPE_APPLICATION_OVERLAY) which is behind the assistant.
* - For transient taskbar, we hide the real taskbar background (if it's showing).
*/
class VoiceInteractionWindowController(val context: TaskbarActivityContext) :
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index a82902f..27a4988 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -31,7 +31,7 @@
*
* @property navButtonContainer ViewGroup that holds the 3 navigation buttons.
* @property endContextualContainer ViewGroup that holds the end contextual button (ex, IME
- * dismiss).
+ * dismiss).
* @property startContextualContainer ViewGroup that holds the start contextual button (ex, A11y).
*/
abstract class AbstractNavButtonLayoutter(
diff --git a/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
deleted file mode 100644
index c46809a..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/DeviceFlag.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.provider.DeviceConfig;
-
-import com.android.launcher3.config.FeatureFlags.DebugFlag;
-
-@TargetApi(Build.VERSION_CODES.P)
-public class DeviceFlag extends DebugFlag {
-
- public static final String NAMESPACE_LAUNCHER = "launcher";
-
- private final boolean mDefaultValueInCode;
-
- public DeviceFlag(String key, boolean defaultValue, String description) {
- super(key, getDeviceValue(key, defaultValue), description);
- mDefaultValueInCode = defaultValue;
- }
-
- @Override
- protected StringBuilder appendProps(StringBuilder src) {
- return super.appendProps(src).append(", mDefaultValueInCode=").append(mDefaultValueInCode);
- }
-
- @Override
- public boolean get() {
- // Override this method in order to let Robolectric ShadowDeviceFlag to stub it.
- return super.get();
- }
-
- protected static boolean getDeviceValue(String key, boolean defaultValue) {
- return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, defaultValue);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 951a9b6..a56300a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -68,6 +68,7 @@
import android.graphics.RectF;
import android.hardware.SensorManager;
import android.hardware.devicestate.DeviceStateManager;
+import android.hardware.display.DisplayManager;
import android.media.permission.SafeCloseable;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -136,6 +137,7 @@
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TwoButtonNavbarTouchController;
import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.NavigationMode;
@@ -574,10 +576,13 @@
@Override
public void startSplitSelection(SplitSelectSource splitSelectSource) {
RecentsView recentsView = getOverviewPanel();
+ ComponentKey componentToBeStaged = new ComponentKey(
+ splitSelectSource.itemInfo.getTargetComponent(),
+ splitSelectSource.itemInfo.user);
// Check if there is already an instance of this app running, if so, initiate the split
// using that.
mSplitSelectStateController.findLastActiveTaskAndRunCallback(
- splitSelectSource.intent.getComponent(),
+ componentToBeStaged,
foundTask -> {
splitSelectSource.alreadyRunningTaskId = foundTask == null
? INVALID_TASK_ID
@@ -878,7 +883,7 @@
getMainExecutor(),
/* backgroundExecutor= */ UI_HELPER_EXECUTOR,
/* tracingTagPrefix= */ "launcher",
- WindowManagerGlobal.getWindowManagerService()
+ getSystemService(DisplayManager.class)
);
mUnfoldTransitionProgressProvider = unfoldComponent.getUnfoldTransitionProvider()
@@ -897,9 +902,10 @@
/* context= */ this,
config,
getMainExecutor(),
+ getMainThreadHandler(),
/* backgroundExecutor= */ UI_HELPER_EXECUTOR,
/* tracingTagPrefix= */ "launcher",
- WindowManagerGlobal.getWindowManagerService()
+ getSystemService(DisplayManager.class)
);
final RemoteUnfoldTransitionReceiver remoteUnfoldTransitionProgressProvider =
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index e8e8328..f16b43d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -91,7 +91,7 @@
builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL));
mRecentsView.updateEmptyMessage();
// TODO(b/246283207): Remove logging once root cause of flake detected.
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
Log.d("b/246283207", "RecentsView#setStateWithAnimationInternal getCurrentPage(): "
+ mRecentsView.getCurrentPage()
+ ", getScrollForPage(getCurrentPage())): "
@@ -121,8 +121,7 @@
private void handleSplitSelectionState(@NonNull LauncherState toState,
@NonNull PendingAnimation builder, boolean animate) {
if (toState != OVERVIEW_SPLIT_SELECT) {
- // Not going to split, nothing to do but ensure taskviews are at correct offset
- mRecentsView.resetSplitPrimaryScrollOffset();
+ // Not going to split
return;
}
@@ -153,8 +152,6 @@
as.start();
as.end();
}
-
- mRecentsView.applySplitPrimaryScrollOffset();
}
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
new file mode 100644
index 0000000..177a399
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides.flags;
+
+import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+
+class DebugFlag extends BooleanFlag {
+
+ public final String key;
+ public final String description;
+
+ public final boolean defaultValue;
+
+ boolean mHasBeenChangedAtLeastOnce;
+
+ public DebugFlag(String key, String description, boolean defaultValue, boolean currentValue) {
+ super(currentValue);
+ this.key = key;
+ this.defaultValue = defaultValue;
+ this.description = description;
+ }
+
+ @Override
+ public String toString() {
+ return key + ": defaultValue=" + defaultValue + ", mCurrentValue=" + get();
+ }
+}
diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
similarity index 99%
rename from src/com/android/launcher3/settings/DeveloperOptionsFragment.java
rename to quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index 40fc16e..9384a89 100644
--- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.settings;
+package com.android.launcher3.uioverrides.flags;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_CHANGED;
@@ -63,7 +63,6 @@
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.config.FlagTogglerPrefUi;
import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.OnboardingPrefs;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
new file mode 100644
index 0000000..3900ebb
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides.flags;
+
+class DeviceFlag extends DebugFlag {
+
+ private final boolean mDefaultValueInCode;
+
+ public DeviceFlag(String key, String description, boolean defaultValue,
+ boolean currentValue, boolean defaultValueInCode) {
+ super(key, description, defaultValue, currentValue);
+ mDefaultValueInCode = defaultValueInCode;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + ", mDefaultValueInCode=" + mDefaultValueInCode;
+ }
+}
diff --git a/src/com/android/launcher3/config/FlagTogglerPrefUi.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
similarity index 93%
rename from src/com/android/launcher3/config/FlagTogglerPrefUi.java
rename to quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
index 2eb6e6d..4ca7e31 100644
--- a/src/com/android/launcher3/config/FlagTogglerPrefUi.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3.config;
+package com.android.launcher3.uioverrides.flags;
import static com.android.launcher3.config.FeatureFlags.FLAGS_PREF_NAME;
@@ -33,7 +33,7 @@
import androidx.preference.SwitchPreference;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags.DebugFlag;
+import com.android.launcher3.config.FeatureFlags;
/**
* Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}.
@@ -50,7 +50,7 @@
@Override
public void putBoolean(String key, boolean value) {
- for (DebugFlag flag : FeatureFlags.getDebugFlags()) {
+ for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
if (flag.key.equals(key)) {
SharedPreferences prefs = mContext.getSharedPreferences(
FLAGS_PREF_NAME, Context.MODE_PRIVATE);
@@ -71,7 +71,7 @@
@Override
public boolean getBoolean(String key, boolean defaultValue) {
- for (DebugFlag flag : FeatureFlags.getDebugFlags()) {
+ for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
if (flag.key.equals(key)) {
return mContext.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
.getBoolean(key, flag.defaultValue);
@@ -93,7 +93,7 @@
// flag with a different value than the default. That way, when we flip flags in
// future, engineers will pick up the new value immediately. To accomplish this, we use a
// custom preference data store.
- for (DebugFlag flag : FeatureFlags.getDebugFlags()) {
+ for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
SwitchPreference switchPreference = new SwitchPreference(mContext);
switchPreference.setKey(flag.key);
switchPreference.setDefaultValue(flag.defaultValue);
@@ -149,11 +149,11 @@
}
private boolean anyChanged() {
- for (DebugFlag flag : FeatureFlags.getDebugFlags()) {
+ for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
if (getFlagStateFromSharedPrefs(flag) != flag.get()) {
return true;
}
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
new file mode 100644
index 0000000..84b873d
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides.flags;
+
+import static android.app.ActivityThread.currentApplication;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
+import android.util.Log;
+
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+import com.android.launcher3.config.FeatureFlags.IntFlag;
+import com.android.launcher3.util.ScreenOnTracker;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Helper class to create various flags for system build
+ */
+public class FlagsFactory {
+
+ private static final String TAG = "FlagsFactory";
+
+ private static final FlagsFactory INSTANCE = new FlagsFactory();
+ private static final boolean FLAG_AUTO_APPLY_ENABLED = false;
+
+ public static final String FLAGS_PREF_NAME = "featureFlags";
+ public static final String NAMESPACE_LAUNCHER = "launcher";
+
+ private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
+
+
+ private final Set<String> mKeySet = new HashSet<>();
+ private boolean mRestartRequested = false;
+
+ private FlagsFactory() {
+ if (!FLAG_AUTO_APPLY_ENABLED) {
+ return;
+ }
+ DeviceConfig.addOnPropertiesChangedListener(
+ NAMESPACE_LAUNCHER, UI_HELPER_EXECUTOR, this::onPropertiesChanged);
+ }
+
+ /**
+ * Creates a new debug flag
+ */
+ public static BooleanFlag getDebugFlag(
+ int bugId, String key, boolean defaultValue, String description) {
+ if (Utilities.IS_DEBUG_DEVICE) {
+ SharedPreferences prefs = currentApplication()
+ .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
+ boolean currentValue = prefs.getBoolean(key, defaultValue);
+ DebugFlag flag = new DebugFlag(key, description, defaultValue, currentValue);
+ flag.mHasBeenChangedAtLeastOnce = prefs.contains(key);
+ sDebugFlags.add(flag);
+ return flag;
+ } else {
+ return new BooleanFlag(defaultValue);
+ }
+ }
+
+ /**
+ * Creates a new release flag
+ */
+ public static BooleanFlag getReleaseFlag(
+ int bugId, String key, boolean defaultValueInCode, String description) {
+ INSTANCE.mKeySet.add(key);
+ boolean defaultValue = DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, defaultValueInCode);
+ if (Utilities.IS_DEBUG_DEVICE) {
+ SharedPreferences prefs = currentApplication()
+ .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
+ boolean currentValue = prefs.getBoolean(key, defaultValue);
+ DebugFlag flag = new DeviceFlag(key, description, defaultValue, currentValue,
+ defaultValueInCode);
+ flag.mHasBeenChangedAtLeastOnce = prefs.contains(key);
+ sDebugFlags.add(flag);
+ return flag;
+ } else {
+ return new BooleanFlag(defaultValue);
+ }
+ }
+
+ /**
+ * Creates a new integer flag. Integer flags are always release flags
+ */
+ public static IntFlag getIntFlag(
+ int bugId, String key, int defaultValueInCode, String description) {
+ INSTANCE.mKeySet.add(key);
+ return new IntFlag(DeviceConfig.getInt(NAMESPACE_LAUNCHER, key, defaultValueInCode));
+ }
+
+ static List<DebugFlag> getDebugFlags() {
+ if (!Utilities.IS_DEBUG_DEVICE) {
+ return Collections.emptyList();
+ }
+ List<DebugFlag> flags;
+ synchronized (sDebugFlags) {
+ flags = new ArrayList<>(sDebugFlags);
+ }
+ flags.sort((f1, f2) -> {
+ // Sort first by any prefs that the user has changed, then alphabetically.
+ int changeComparison = Boolean.compare(
+ f2.mHasBeenChangedAtLeastOnce, f1.mHasBeenChangedAtLeastOnce);
+ return changeComparison != 0
+ ? changeComparison
+ : f1.key.compareToIgnoreCase(f2.key);
+ });
+ return flags;
+ }
+
+ /**
+ * Dumps the current flags state to the print writer
+ */
+ public static void dump(PrintWriter pw) {
+ if (!Utilities.IS_DEBUG_DEVICE) {
+ return;
+ }
+ pw.println("DeviceFlags:");
+ synchronized (sDebugFlags) {
+ for (DebugFlag flag : sDebugFlags) {
+ if (flag instanceof DeviceFlag) {
+ pw.println(" " + flag);
+ }
+ }
+ }
+ pw.println("DebugFlags:");
+ synchronized (sDebugFlags) {
+ for (DebugFlag flag : sDebugFlags) {
+ if (!(flag instanceof DeviceFlag)) {
+ pw.println(" " + flag);
+ }
+ }
+ }
+ }
+
+ private void onPropertiesChanged(Properties properties) {
+ if (!Collections.disjoint(properties.getKeyset(), mKeySet)) {
+ // Schedule a restart
+ if (mRestartRequested) {
+ return;
+ }
+ Log.e(TAG, "Flag changed, scheduling restart");
+ mRestartRequested = true;
+ ScreenOnTracker sot = ScreenOnTracker.INSTANCE.get(currentApplication());
+ if (sot.isScreenOn()) {
+ sot.addListener(this::onScreenOnChanged);
+ } else {
+ onScreenOnChanged(false);
+ }
+ }
+ }
+
+ private void onScreenOnChanged(boolean isOn) {
+ if (mRestartRequested && !isOn) {
+ Log.e(TAG, "Restart requested, killing process");
+ System.exit(0);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 8125fc8..e578720 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -24,9 +24,7 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.config.FeatureFlags;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.RecentsView;
@@ -103,10 +101,6 @@
@Override
public int getWorkspaceScrimColor(Launcher launcher) {
- DeviceProfile dp = launcher.getDeviceProfile();
- if (dp.isTaskbarPresentInApps && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- return launcher.getColor(R.color.taskbar_background);
- }
return Color.TRANSPARENT;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 233ed46..d2f9294 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -26,7 +26,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.util.LayoutUtils;
@@ -104,13 +103,8 @@
}
@Override
- public boolean isTaskbarStashed(Launcher launcher) {
- return !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
- }
-
- @Override
public boolean isTaskbarAlignedWithHotseat(Launcher launcher) {
- return !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
+ return false;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 5eeeb36..a02f3de 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
+import static com.android.launcher3.QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION;
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getWorkspaceSpringScaleAnimator;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
@@ -119,6 +120,12 @@
long scrollDuration = Math.min(MAX_PAGE_SCROLL_DURATION,
numPagesToScroll * PER_PAGE_SCROLL_DURATION);
config.duration = Math.max(config.duration, scrollDuration);
+
+ // Sync scroll so that it ends before or at the same time as the taskbar animation.
+ if (DisplayController.isTransientTaskbar(mActivity)
+ && mActivity.getDeviceProfile().isTaskbarPresent) {
+ config.duration = Math.min(config.duration, TASKBAR_TO_HOME_DURATION);
+ }
overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration));
} else {
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
index 8babd34..3ae221b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
@@ -53,4 +53,9 @@
return SplitAnimationTimings.ABORT_DURATION;
}
}
+
+ @Override
+ public boolean shouldPreserveDataStateOnReapply() {
+ return true;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 1122e00..e9385d9 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -678,7 +678,7 @@
@Override
public void onMotionPauseDetected() {
mHasMotionEverBeenPaused = true;
- maybeUpdateRecentsAttachedState(true/* animate */, true/* moveFocusedTask */);
+ maybeUpdateRecentsAttachedState(true/* animate */, true/* moveRunningTask */);
Optional.ofNullable(mActivityInterface.getTaskbarController())
.ifPresent(TaskbarUIController::startTranslationSpring);
performHapticFeedback();
@@ -696,7 +696,7 @@
}
private void maybeUpdateRecentsAttachedState(boolean animate) {
- maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */);
+ maybeUpdateRecentsAttachedState(animate, false /* moveRunningTask */);
}
/**
@@ -706,9 +706,9 @@
*
* Note this method has no effect unless the navigation mode is NO_BUTTON.
* @param animate whether to animate when attaching RecentsView
- * @param moveFocusedTask whether to move focused task to front when attaching
+ * @param moveRunningTask whether to move running task to front when attaching
*/
- private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveFocusedTask) {
+ private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) {
if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
return;
}
@@ -727,11 +727,11 @@
} else {
recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask;
}
- if (moveFocusedTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
+ if (moveRunningTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
&& recentsAttachedToAppWindow) {
- // Only move focused task if RecentsView has never been attached before, to avoid
+ // Only move running task if RecentsView has never been attached before, to avoid
// TaskView jumping to new position as we move the tasks.
- mRecentsView.moveFocusedTaskToFront();
+ mRecentsView.moveRunningTaskToFront();
}
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
@@ -878,7 +878,7 @@
if (DesktopTaskView.DESKTOP_MODE_SUPPORTED && targets.hasDesktopTasks()) {
mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets);
} else {
- mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(mContext, targets);
+ mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(targets);
}
mRecentsAnimationController = controller;
mRecentsAnimationTargets = targets;
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 998439e..3e565b3 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -231,17 +231,20 @@
/**
* Calculates the taskView size for the provided device configuration.
*/
- public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
- Resources res = context.getResources();
- float maxScale = res.getFloat(R.dimen.overview_max_scale);
+ public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
+ PagedOrientationHandler orientedState) {
if (dp.isTablet) {
- Rect gridRect = new Rect();
- calculateGridSize(dp, gridRect);
-
- calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
+ if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ calculateGridTaskSize(context, dp, outRect, orientedState);
+ } else {
+ calculateFocusTaskSize(context, dp, outRect);
+ }
} else {
+ Resources res = context.getResources();
+ float maxScale = res.getFloat(R.dimen.overview_max_scale);
int taskMargin = dp.overviewTaskMarginPx;
- calculateTaskSizeInternal(context, dp,
+ calculateTaskSizeInternal(
+ dp,
dp.overviewTaskThumbnailTopMarginPx,
dp.getOverviewActionsClaimedSpace(),
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
@@ -251,7 +254,15 @@
}
}
- private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
+ private void calculateFocusTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+ Resources res = context.getResources();
+ float maxScale = res.getFloat(R.dimen.overview_max_scale);
+ Rect gridRect = new Rect();
+ calculateGridSize(dp, gridRect);
+ calculateTaskSizeInternal(dp, gridRect, maxScale, Gravity.CENTER, outRect);
+ }
+
+ private void calculateTaskSizeInternal(DeviceProfile dp, int claimedSpaceAbove,
int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
Rect outRect) {
Rect insets = dp.getInsets();
@@ -264,10 +275,10 @@
minimumHorizontalPadding,
claimedSpaceBelow);
- calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
+ calculateTaskSizeInternal(dp, potentialTaskRect, maxScale, gravity, outRect);
}
- private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
+ private void calculateTaskSizeInternal(DeviceProfile dp,
Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
PointF taskDimension = getTaskDimension(dp);
@@ -318,12 +329,15 @@
public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect,
PagedOrientationHandler orientedState) {
Resources res = context.getResources();
- Rect taskRect = new Rect();
- calculateTaskSize(context, dp, taskRect);
+ Rect potentialTaskRect = new Rect();
+ if (FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ calculateGridSize(dp, potentialTaskRect);
+ } else {
+ calculateFocusTaskSize(context, dp, potentialTaskRect);
+ }
- float rowHeight =
- (taskRect.height() + dp.overviewTaskThumbnailTopMarginPx - dp.overviewRowSpacing)
- / 2f;
+ float rowHeight = (potentialTaskRect.height() + dp.overviewTaskThumbnailTopMarginPx
+ - dp.overviewRowSpacing) / 2f;
PointF taskDimension = getTaskDimension(dp);
float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y;
@@ -332,14 +346,22 @@
int gravity = Gravity.TOP;
gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
- Gravity.apply(gravity, outWidth, outHeight, taskRect, outRect);
+ Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
+ }
+
+ /**
+ * Calculates the task size for the desktop task
+ */
+ public final void calculateDesktopTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+ calculateFocusTaskSize(context, dp, outRect);
}
/**
* Calculates the modal taskView size for the provided device configuration
*/
- public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
- calculateTaskSize(context, dp, outRect);
+ public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect,
+ PagedOrientationHandler orientedState) {
+ calculateTaskSize(context, dp, outRect, orientedState);
boolean isGridOnlyOverview = dp.isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get();
int claimedSpaceBelow = isGridOnlyOverview
? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarSize
@@ -351,7 +373,7 @@
Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2);
}
calculateTaskSizeInternal(
- context, dp,
+ dp,
dp.overviewTaskMarginPx,
claimedSpaceBelow,
minimumHorizontalPadding,
diff --git a/quickstep/src/com/android/quickstep/BootAwarePreloader.kt b/quickstep/src/com/android/quickstep/BootAwarePreloader.kt
new file mode 100644
index 0000000..35404a9
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/BootAwarePreloader.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep
+
+import android.content.Context
+import android.util.Log
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.isBootAwareStartupDataEnabled
+import com.android.launcher3.util.LockedUserState
+
+/**
+ * Loads expensive objects in memory before the user is unlocked. This decreases experienced latency
+ * when starting the launcher for the first time after a reboot.
+ */
+object BootAwarePreloader {
+ private const val TAG = "BootAwarePreloader"
+
+ @JvmStatic
+ fun start(context: Context) {
+ val lp = LauncherPrefs.get(context)
+ when {
+ LockedUserState.get(context).isUserUnlocked || !isBootAwareStartupDataEnabled -> {
+ /* No-Op */
+ }
+ lp.isStartupDataMigrated -> {
+ Log.d(TAG, "preloading start up data")
+ LauncherAppState.INSTANCE.get(context)
+ }
+ else -> {
+ Log.d(TAG, "queuing start up data migration to boot aware prefs")
+ LockedUserState.get(context).runOnUserUnlocked {
+ lp.migrateStartupDataToDeviceProtectedStorage()
+ }
+ }
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index ae9fb0b..8bb189a 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -61,7 +61,7 @@
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
PagedOrientationHandler orientationHandler) {
- calculateTaskSize(context, dp, outRect);
+ calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout() && DisplayController.getNavigationMode(context) != NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
} else {
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 7f2886c..ea9f032 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -73,7 +72,7 @@
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
PagedOrientationHandler orientationHandler) {
- calculateTaskSize(context, dp, outRect);
+ calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout()
&& DisplayController.getNavigationMode(context) != NavigationMode.NO_BUTTON) {
return dp.isSeascape() ? outRect.left : (dp.widthPx - outRect.right);
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index ac5b2f2..5b85249 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -283,7 +283,7 @@
RecentsView<?, ?> visibleRecentsView = activityInterface.getVisibleRecentsView();
if (visibleRecentsView != null) {
- visibleRecentsView.moveFocusedTaskToFront();
+ visibleRecentsView.moveRunningTaskToFront();
}
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
cmd.mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(gestureState);
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index 589459f..a8f3c3a 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -37,6 +37,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.R;
import com.android.launcher3.tracing.OverviewComponentObserverProto;
import com.android.launcher3.tracing.TouchInteractionServiceProto;
import com.android.launcher3.util.SimpleBroadcastReceiver;
@@ -65,6 +66,7 @@
private final Intent mMyHomeIntent;
private final Intent mFallbackIntent;
private final SparseIntArray mConfigChangesMap = new SparseIntArray();
+ private final String mSetupWizardPkg;
private Consumer<Boolean> mOverviewChangeListener = b -> { };
@@ -86,6 +88,7 @@
new ComponentName(context.getPackageName(), info.activityInfo.name);
mMyHomeIntent.setComponent(myHomeComponent);
mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges);
+ mSetupWizardPkg = context.getString(R.string.setup_wizard_pkg);
ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class);
mFallbackIntent = new Intent(Intent.ACTION_MAIN)
@@ -127,6 +130,12 @@
private void updateOverviewTargets() {
ComponentName defaultHome = PackageManagerWrapper.getInstance()
.getHomeActivities(new ArrayList<>());
+ if (defaultHome != null && defaultHome.getPackageName().equals(mSetupWizardPkg)) {
+ // Treat setup wizard as null default home, because there is a period between setup and
+ // launcher being default home where it is briefly null. Otherwise, it would appear as
+ // if overview targets are changing twice, giving the listener an incorrect signal.
+ defaultHome = null;
+ }
mIsHomeDisabled = mDeviceState.isHomeDisabled();
mIsDefaultHome = Objects.equals(mMyHomeIntent.getComponent(), defaultHome);
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 54e4a0d..5391f4d 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -59,7 +59,7 @@
}
Rect focusedTaskRect = new Rect();
LauncherActivityInterface.INSTANCE.calculateTaskSize(mContext, mDeviceProfile,
- focusedTaskRect);
+ focusedTaskRect, PagedOrientationHandler.PORTRAIT);
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.height());
return response;
}
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 9b00dcf..f30d3f1 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -89,7 +89,7 @@
* Length of targets.apps should match that of {@link #mRemoteTargetHandles}.
*
* If split screen may be active when this is called, you might want to use
- * {@link #assignTargetsForSplitScreen(Context, RemoteAnimationTargets)}
+ * {@link #assignTargetsForSplitScreen(RemoteAnimationTargets)}
*/
public RemoteTargetHandle[] assignTargets(RemoteAnimationTargets targets) {
for (int i = 0; i < mRemoteTargetHandles.length; i++) {
@@ -102,43 +102,45 @@
}
/**
- * Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this matches the
- * apps in targets.apps to that of the _active_ split screened tasks.
- * See {@link #assignTargetsForSplitScreen(RemoteAnimationTargets, int[])}
+ * Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this assigns the
+ * apps in {@code targets.apps} to the {@link #mRemoteTargetHandles} with index 0 will being
+ * the left/top task, index 1 right/bottom.
*/
- public RemoteTargetHandle[] assignTargetsForSplitScreen(
- Context context, RemoteAnimationTargets targets) {
- int[] splitIds = TopTaskTracker.INSTANCE.get(context).getRunningSplitTaskIds();
- return assignTargetsForSplitScreen(targets, splitIds);
- }
-
- /**
- * Assigns the provided splitIDs to the {@link #mRemoteTargetHandles}, with index 0 will being
- * the left/top task, index 1 right/bottom
- */
- public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets,
- int[] splitIds) {
- RemoteAnimationTarget topLeftTarget; // only one set if single/fullscreen task
- RemoteAnimationTarget bottomRightTarget;
+ public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
if (mRemoteTargetHandles.length == 1) {
// If we're not in split screen, the splitIds count doesn't really matter since we
// should always hit this case.
mRemoteTargetHandles[0].mTransformParams.setTargetSet(targets);
if (targets.apps.length > 0) {
// Unclear why/when target.apps length == 0, but it sure does happen :(
- topLeftTarget = targets.apps[0];
- mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(topLeftTarget, null);
+ mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(targets.apps[0], null);
}
} else {
- // split screen
- topLeftTarget = targets.findTask(splitIds[0]);
- bottomRightTarget = targets.findTask(splitIds[1]);
+ RemoteAnimationTarget topLeftTarget = targets.apps[0];
+
+ // Fetch the adjacent target for split screen.
+ RemoteAnimationTarget bottomRightTarget = null;
+ for (int i = 1; i < targets.apps.length; i++) {
+ final RemoteAnimationTarget target = targets.apps[i];
+ Rect topLeftBounds = getStartBounds(topLeftTarget);
+ Rect bounds = getStartBounds(target);
+ if (topLeftBounds.left > bounds.right || topLeftBounds.top > bounds.bottom) {
+ bottomRightTarget = topLeftTarget;
+ topLeftTarget = target;
+ break;
+ } else if (topLeftBounds.right < bounds.left || topLeftBounds.bottom < bounds.top) {
+ bottomRightTarget = target;
+ break;
+ }
+ }
// remoteTargetHandle[0] denotes topLeft task, so we pass in the bottomRight to exclude,
// vice versa
mSplitBounds = new SplitBounds(
getStartBounds(topLeftTarget),
- getStartBounds(bottomRightTarget), splitIds[0], splitIds[1]);
+ getStartBounds(bottomRightTarget),
+ topLeftTarget.taskId,
+ bottomRightTarget.taskId);
mRemoteTargetHandles[0].mTransformParams.setTargetSet(
createRemoteAnimationTargetsForTarget(targets, bottomRightTarget));
mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(topLeftTarget,
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 72330ef..6e47ff4 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -81,7 +81,8 @@
boolean isTablet = activity.getDeviceProfile().isTablet;
boolean isGridOnlyOverview = isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get();
- // Add overview actions to the menu when in in-place rotate landscape mode.
+ // Add overview actions to the menu when in in-place rotate landscape mode, or in
+ // grid-only overview.
if ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview) {
// Add screenshot action to task menu.
List<SystemShortcut> screenshotShortcuts = TaskShortcutFactory.SCREENSHOT
@@ -90,8 +91,9 @@
shortcuts.addAll(screenshotShortcuts);
}
- // Add modal action only if display orientation is the same as the device orientation.
- if (orientedState.getDisplayRotation() == ROTATION_0) {
+ // 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(activity, taskContainer);
if (modalShortcuts != null) {
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 1a72e3f..da97df6 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -190,7 +190,7 @@
if (forDesktop) {
remoteTargetHandles = gluer.assignTargetsForDesktop(targets);
} else if (v.containsMultipleTasks()) {
- remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, v.getTaskIds());
+ remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets);
} else {
remoteTargetHandles = gluer.assignTargets(targets);
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 61caef2..4680608 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -86,6 +86,7 @@
import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.tracing.LauncherTraceProto;
import com.android.launcher3.tracing.TouchInteractionServiceProto;
+import com.android.launcher3.uioverrides.flags.FlagsFactory;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.OnboardingPrefs;
@@ -409,6 +410,7 @@
mDeviceState = new RecentsAnimationDeviceState(this, true);
mTaskbarManager = new TaskbarManager(this);
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
+ BootAwarePreloader.start(this);
// Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
@@ -1130,6 +1132,10 @@
return;
}
+ // TODO(b/258022658): Remove temporary logging.
+ Log.i(TAG, "preloadOverview: forSUWAllSet=" + forSUWAllSet
+ + ", isHomeAndOverviewSame=" + mOverviewComponentObserver.isHomeAndOverviewSame());
+
mTaskAnimationManager.preloadRecentsAnimation(overviewIntent);
}
@@ -1175,7 +1181,7 @@
}
} else {
// Dump everything
- FeatureFlags.dump(pw);
+ FlagsFactory.dump(pw);
if (mDeviceState.isUserUnlocked()) {
PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 062e50e..11b1ab8 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -130,15 +130,9 @@
mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset(
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mActivity.getDeviceProfile());
+ setter.setFloat(mRecentsView, taskViewsFloat.first, isSplitSelectionState(state)
+ ? mRecentsView.getSplitSelectTranslation() : 0, LINEAR);
setter.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
- if (isSplitSelectionState(state)) {
- mRecentsView.applySplitPrimaryScrollOffset();
- setter.setFloat(mRecentsView, taskViewsFloat.first,
- mRecentsView.getSplitSelectTranslation(), LINEAR);
- } else {
- mRecentsView.resetSplitPrimaryScrollOffset();
- setter.setFloat(mRecentsView, taskViewsFloat.first, 0, LINEAR);
- }
}
/**
diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
index ac0c17d..bd0ce34 100644
--- a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
+++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
@@ -15,17 +15,30 @@
*/
package com.android.quickstep.interaction;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
+
import android.content.Context;
import android.graphics.Insets;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.View;
import android.view.WindowInsets;
import android.widget.RelativeLayout;
+import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
/** Root layout that TutorialFragment uses to intercept motion events. */
public class RootSandboxLayout extends RelativeLayout {
+
+ private View mFeedbackView;
+ private View mTutorialStepView;
+ private View mSkipButton;
+ private View mDoneButton;
+
public RootSandboxLayout(Context context) {
super(context);
}
@@ -52,4 +65,51 @@
return getHeight() + insets.top + insets.bottom;
}
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
+ return;
+ }
+ mFeedbackView = findViewById(R.id.gesture_tutorial_fragment_feedback_view);
+ mTutorialStepView =
+ mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_tutorial_step);
+ mSkipButton = mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_close_button);
+ mDoneButton = mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_action_button);
+
+ mFeedbackView.addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ if (mSkipButton.getVisibility() != VISIBLE
+ && mDoneButton.getVisibility() != VISIBLE) {
+ return;
+ }
+ // Either the skip or the done button is ever shown at once, never both.
+ boolean showingSkipButton = mSkipButton.getVisibility() == VISIBLE;
+ boolean isRTL = Utilities.isRtl(getContext().getResources());
+ updateTutorialStepViewTranslation(
+ showingSkipButton ? mSkipButton : mDoneButton,
+ // Translate the step indicator away from whichever button is being
+ // shown. The skip button in on the left in LTR or on the right in RTL.
+ // The done button is on the right in LTR or left in RTL.
+ (showingSkipButton && !isRTL) || (!showingSkipButton && isRTL));
+ });
+ }
+
+ private void updateTutorialStepViewTranslation(
+ @NonNull View anchorView, boolean translateToRight) {
+ mTutorialStepView.setTranslationX(translateToRight
+ ? Math.min(
+ // Translate to the right if the views are overlapping on large fonts and
+ // display sizes.
+ Math.max(0, anchorView.getRight() - mTutorialStepView.getLeft()),
+ // Do not translate beyond the bounds of the container view.
+ mFeedbackView.getWidth() - mTutorialStepView.getRight())
+ : Math.max(
+ // Translate to the left if the views are overlapping on large fonts and
+ // display sizes.
+ Math.min(0, anchorView.getLeft() - mTutorialStepView.getRight()),
+ // Do not translate beyond the bounds of the container view.
+ -mTutorialStepView.getLeft()));
+ }
}
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 0a155cb..4690d94 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -139,7 +139,7 @@
if (IS_VERBOSE) {
Log.d(TAG, String.format("\nwriteSnapshot(%d):\n%s", instanceId.getId(), info));
}
- if (!Utilities.ATLEAST_R || Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (!Utilities.ATLEAST_R || Utilities.isRunningInTestHarness()) {
return;
}
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_SNAPSHOT,
@@ -438,7 +438,7 @@
}
// TODO: remove this when b/231648228 is fixed.
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
return;
}
int cardinality = mCardinality.orElseGet(() -> getCardinality(atomInfo));
@@ -636,7 +636,7 @@
}
private static int getCardinality(LauncherAtom.ItemInfo info) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
return 0;
}
switch (info.getContainerInfo().getContainerCase()) {
@@ -758,7 +758,7 @@
}
private static int getHierarchy(LauncherAtom.ItemInfo info) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
return 0;
}
if (info.getContainerInfo().getContainerCase() == FOLDER) {
@@ -801,7 +801,7 @@
}
private static int getSearchAttributes(LauncherAtom.ItemInfo info) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
return 0;
}
ContainerInfo containerInfo = info.getContainerInfo();
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
index 7c83833..baca76c 100644
--- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -158,7 +158,8 @@
Rect startRect = new Rect();
PagedOrientationHandler orientationHandler = params.recentsOrientedState
.getOrientationHandler();
- LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect);
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect,
+ orientationHandler);
long distanceToCover = startRect.bottom;
PendingAnimation resistAnim = params.resistAnim != null
? params.resistAnim
diff --git a/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java b/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java
index effdfdd..f6b2441 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherViewsMoveFromCenterTranslationApplier.java
@@ -15,12 +15,13 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_MOVE_FROM_CENTER_ANIM;
+
import android.annotation.NonNull;
import android.view.View;
-import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.widget.NavigableAppWidgetHostView;
+import com.android.launcher3.Reorderable;
+import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.TranslationApplier;
/**
@@ -31,12 +32,9 @@
@Override
public void apply(@NonNull View view, float x, float y) {
- if (view instanceof NavigableAppWidgetHostView) {
- ((NavigableAppWidgetHostView) view).setTranslationForMoveFromCenterAnimation(x, y);
- } else if (view instanceof BubbleTextView) {
- ((BubbleTextView) view).setTranslationForMoveFromCenterAnimation(x, y);
- } else if (view instanceof FolderIcon) {
- ((FolderIcon) view).setTranslationForMoveFromCenterAnimation(x, y);
+ if (view instanceof Reorderable) {
+ MultiTranslateDelegate mtd = ((Reorderable) view).getTranslateDelegate();
+ mtd.setTranslation(INDEX_MOVE_FROM_CENTER_ANIM, x, y);
} else {
view.setTranslationX(x);
view.setTranslationY(y);
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index f7136a5..79656c2 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -43,7 +43,8 @@
PagedOrientationHandler orientationHandler) {
// Track the bottom of the window.
Rect taskSize = new Rect();
- LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize);
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize,
+ orientationHandler);
return orientationHandler.getDistanceToBottomOfRect(dp, taskSize);
}
diff --git a/quickstep/src/com/android/quickstep/util/LogUtils.kt b/quickstep/src/com/android/quickstep/util/LogUtils.kt
index 300c4a1..23a41f6 100644
--- a/quickstep/src/com/android/quickstep/util/LogUtils.kt
+++ b/quickstep/src/com/android/quickstep/util/LogUtils.kt
@@ -22,7 +22,7 @@
object LogUtils {
/**
* @return a [Pair] of two InstanceIds but with different types, one that can be used by
- * framework (if needing to pass through an intent or such) and one used in Launcher
+ * framework (if needing to pass through an intent or such) and one used in Launcher
*/
@JvmStatic
fun getShellShareableInstanceId(): Pair<com.android.internal.logging.InstanceId, InstanceId> {
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 69ed2f8..4bc41bc 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -129,7 +129,7 @@
* @param pointerIndex Index for the pointer being tracked in the motion event
*/
public void addPosition(MotionEvent ev, int pointerIndex) {
- long timeoutMs = Utilities.IS_RUNNING_IN_TEST_HARNESS
+ long timeoutMs = Utilities.isRunningInTestHarness()
? TEST_HARNESS_TRIGGER_TIMEOUT
: mMakePauseHarderToTrigger
? HARDER_TRIGGER_TIMEOUT
@@ -195,7 +195,7 @@
if (mIsPaused != isPaused) {
mIsPaused = isPaused;
String logString = "onMotionPauseChanged, paused=" + mIsPaused + " reason=" + reason;
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
Log.d(TAG, logString);
}
ActiveGestureLog.INSTANCE.addLog(logString);
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index e928b27..cf07e6e 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -64,7 +64,7 @@
});
}
- if (!Utilities.IS_RUNNING_IN_TEST_HARNESS
+ if (!Utilities.isRunningInTestHarness()
&& !hasReachedMaxCount(HOTSEAT_DISCOVERY_TIP_COUNT)) {
stateManager.addStateListener(new StateListener<LauncherState>() {
boolean mFromAllApps = false;
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index d1100c7..5214f7c 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -29,7 +29,6 @@
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.PendingIntent;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -58,6 +57,7 @@
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.RecentsModel;
@@ -162,7 +162,7 @@
* Used in various task-switching or splitscreen operations when we need to check if there is a
* currently running Task of a certain type and use the most recent one.
*/
- public void findLastActiveTaskAndRunCallback(ComponentName componentName,
+ public void findLastActiveTaskAndRunCallback(ComponentKey componentKey,
Consumer<Task> callback) {
mRecentTasksModel.getTasks(taskGroups -> {
Task lastActiveTask = null;
@@ -170,12 +170,12 @@
for (int i = taskGroups.size() - 1; i >= 0; i--) {
GroupTask groupTask = taskGroups.get(i);
Task task1 = groupTask.task1;
- if (isInstanceOfComponent(task1, componentName)) {
+ if (isInstanceOfComponent(task1, componentKey)) {
lastActiveTask = task1;
break;
}
Task task2 = groupTask.task2;
- if (isInstanceOfComponent(task2, componentName)) {
+ if (isInstanceOfComponent(task2, componentKey)) {
lastActiveTask = task2;
break;
}
@@ -189,13 +189,14 @@
* Checks if a given Task is the most recently-active Task of type componentName. Used for
* selecting already-running Tasks for splitscreen.
*/
- public boolean isInstanceOfComponent(@Nullable Task task, ComponentName componentName) {
+ public boolean isInstanceOfComponent(@Nullable Task task, ComponentKey componentKey) {
// Exclude the task that is already staged
if (task == null || task.key.id == mInitialTaskId) {
return false;
}
- return task.key.baseIntent.getComponent().equals(componentName);
+ return task.key.baseIntent.getComponent().equals(componentKey.componentName)
+ && task.key.userId == componentKey.user.getIdentifier();
}
/**
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 69f9ce3..0b83eaf 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -157,7 +157,8 @@
mSizeStrategy.calculateGridTaskSize(mContext, mDp, mTaskRect,
mOrientationState.getOrientationHandler());
} else {
- mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect);
+ mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect,
+ mOrientationState.getOrientationHandler());
}
Rect fullTaskSize;
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index d098ffc..6813857 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -67,7 +67,6 @@
private float mGridTranslationPrimary;
private float mGridScrollOffset;
private float mScrollOffsetPrimary;
- private float mSplitSelectScrollOffsetPrimary;
private int mSidePadding;
@@ -176,10 +175,6 @@
mScrollOffsetPrimary = scrollOffsetPrimary;
}
- public void setSplitSelectScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
- mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
- }
-
public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
float scrollAdjustment = 0;
if (fullscreenEnabled) {
@@ -189,7 +184,6 @@
scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset;
}
scrollAdjustment += mScrollOffsetPrimary;
- scrollAdjustment += mSplitSelectScrollOffsetPrimary;
return scrollAdjustment;
}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 89177b6..14898b1 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -381,6 +381,7 @@
}
setOverlayEnabled(false);
onTaskListVisibilityChanged(false);
+ setVisibility(VISIBLE);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index f578b87..409504b 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -56,7 +56,8 @@
HIDDEN_NO_RECENTS,
HIDDEN_SPLIT_SCREEN,
HIDDEN_SPLIT_SELECT_ACTIVE,
- HIDDEN_ACTIONS_IN_MENU
+ HIDDEN_ACTIONS_IN_MENU,
+ HIDDEN_DESKTOP
})
@Retention(RetentionPolicy.SOURCE)
public @interface ActionsHiddenFlags { }
@@ -67,6 +68,7 @@
public static final int HIDDEN_SPLIT_SCREEN = 1 << 3;
public static final int HIDDEN_SPLIT_SELECT_ACTIVE = 1 << 4;
public static final int HIDDEN_ACTIONS_IN_MENU = 1 << 5;
+ public static final int HIDDEN_DESKTOP = 1 << 6;
@IntDef(flag = true, value = {
DISABLED_SCROLLING,
@@ -259,26 +261,8 @@
* Offsets OverviewActionsView horizontal position based on 3 button nav container in taskbar.
*/
private void updatePadding() {
- if (mDp == null) {
- return;
- }
- boolean largeScreenLandscape = mDp.isTablet && !mDp.isTwoPanels && mDp.isLandscape;
- // If in 3-button mode, shift action buttons to accommodate 3-button layout.
- // (Special exception for landscape tablets, where there is enough room and we don't need to
- // shift the action buttons.)
- if (mDp.areNavButtonsInline && !largeScreenLandscape
- // If taskbar is in overview, overview action has dedicated space above nav buttons
- && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- // Add extra horizontal spacing
- int additionalPadding = mDp.hotseatBarEndOffset;
- if (isLayoutRtl()) {
- setPadding(mInsets.left + additionalPadding, 0, mInsets.right, 0);
- } else {
- setPadding(mInsets.left, 0, mInsets.right + additionalPadding, 0);
- }
- } else {
- setPadding(mInsets.left, 0, mInsets.right, 0);
- }
+ // If taskbar is in overview, overview action has dedicated space above nav buttons
+ setPadding(mInsets.left, 0, mInsets.right, 0);
}
/** Updates vertical margins for different navigation mode or configuration changes. */
@@ -298,11 +282,6 @@
return 0;
}
- if (!mDp.isGestureMode && mDp.isTaskbarPresent
- && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- return mDp.getOverviewActionsClaimedSpaceBelow();
- }
-
if (mDp.isTablet && FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW.get()) {
return mDp.stashedTaskbarSize;
}
@@ -322,7 +301,7 @@
requestLayout();
- mSplitButton.setCompoundDrawablesWithIntrinsicBounds(
+ mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
(dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical),
0, 0, 0);
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index e529b04..ac59403 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -44,7 +44,6 @@
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW;
import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCH_FROM_STAGED_APP;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
@@ -53,8 +52,6 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
@@ -62,6 +59,7 @@
import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
import static com.android.quickstep.views.OverviewActionsView.FLAG_SINGLE_TASK;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
@@ -79,7 +77,6 @@
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.WindowConfiguration;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
@@ -150,6 +147,8 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.testing.TestLogging;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DynamicResource;
@@ -453,6 +452,7 @@
protected final Rect mLastComputedTaskSize = new Rect();
protected final Rect mLastComputedGridSize = new Rect();
protected final Rect mLastComputedGridTaskSize = new Rect();
+ protected final Rect mLastComputedDesktopTaskSize = new Rect();
private TaskView mSelectedTask = null;
// How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
@Nullable
@@ -517,6 +517,7 @@
private float mTaskThumbnailSplashAlpha = 0;
private boolean mShowAsGridLastOnLayout = false;
private final IntSet mTopRowIdSet = new IntSet();
+ private int mClearAllShortTotalWidthTranslation = 0;
// The GestureEndTarget that is still in progress.
@Nullable
@@ -707,6 +708,12 @@
private ObjectAnimator mActionsViewAlphaAnimator;
private float mActionsViewAlphaAnimatorFinalValue;
+ /**
+ * Keeps track of the desktop task. Optional and only present when the feature flag is enabled.
+ */
+ @Nullable
+ private DesktopTaskView mDesktopTaskView;
+
private MultiWindowModeChangedListener mMultiWindowModeChangedListener =
new MultiWindowModeChangedListener() {
@Override
@@ -1233,21 +1240,9 @@
return clearAllScroll + (mIsRtl ? distance : -distance);
}
- private int getSnapToFocusedTaskScrollDiff(boolean isClearAllHidden) {
- int screenStart = mOrientationHandler.getPrimaryScroll(this);
- int targetScroll = getScrollForPage(indexOfChild(getFocusedTaskView()));
- if (!isClearAllHidden) {
- int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
- int taskGridHorizontalDiff = mLastComputedTaskSize.right - mLastComputedGridSize.right;
- int clearAllFocusScrollDiff = taskGridHorizontalDiff - clearAllWidth;
- targetScroll += mIsRtl ? clearAllFocusScrollDiff : -clearAllFocusScrollDiff;
- }
- return screenStart - targetScroll;
- }
-
private boolean isTaskViewWithinBounds(TaskView tv, int start, int end) {
int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment(
- showAsFullscreen(), showAsGrid());
+ showAsGrid());
int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment(
showAsFullscreen()));
int taskEnd = taskStart + taskSize;
@@ -1257,7 +1252,7 @@
private boolean isTaskViewFullyWithinBounds(TaskView tv, int start, int end) {
int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment(
- showAsFullscreen(), showAsGrid());
+ showAsGrid());
int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment(
showAsFullscreen()));
int taskEnd = taskStart + taskSize;
@@ -1493,20 +1488,20 @@
}
/**
- * Moves the focused task to the front of the carousel in tablets, to minimize animation
- * required to focus the task in grid.
+ * Moves the running task to the front of the carousel in tablets, to minimize animation
+ * required to move the running task in grid.
*/
- public void moveFocusedTaskToFront() {
+ public void moveRunningTaskToFront() {
if (!mActivity.getDeviceProfile().isTablet) {
return;
}
- TaskView focusedTaskView = getFocusedTaskView();
- if (focusedTaskView == null) {
+ TaskView runningTaskView = getRunningTaskView();
+ if (runningTaskView == null) {
return;
}
- if (indexOfChild(focusedTaskView) != mCurrentPage) {
+ if (indexOfChild(runningTaskView) != mCurrentPage) {
return;
}
@@ -1518,20 +1513,20 @@
int currentPageScroll = getScrollForPage(mCurrentPage);
mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
- mMovingTaskView = focusedTaskView;
- removeView(focusedTaskView);
+ mMovingTaskView = runningTaskView;
+ removeView(runningTaskView);
mMovingTaskView = null;
- focusedTaskView.resetPersistentViewTransforms();
+ runningTaskView.resetPersistentViewTransforms();
int frontTaskIndex = 0;
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && !focusedTaskView.isDesktopTask()) {
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && !runningTaskView.isDesktopTask()) {
// If desktop mode is enabled, desktop task view is pinned at first position.
- // Move focused task to position 1
+ // Move running task to position 1
frontTaskIndex = 1;
}
- addView(focusedTaskView, frontTaskIndex);
+ addView(runningTaskView, frontTaskIndex);
setCurrentPage(frontTaskIndex);
- updateGridProperties();
+ updateTaskSize();
}
@Override
@@ -1564,7 +1559,7 @@
return;
}
- int currentTaskId = -1;
+ int currentTaskId = INVALID_TASK_ID;
TaskView currentTaskView = getTaskViewAt(mCurrentPage);
if (currentTaskView != null && currentTaskView.getTask() != null) {
currentTaskId = currentTaskView.getTask().key.id;
@@ -1574,7 +1569,8 @@
unloadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
TaskView ignoreResetTaskView =
- mIgnoreResetTaskId == -1 ? null : getTaskViewByTaskId(mIgnoreResetTaskId);
+ mIgnoreResetTaskId == INVALID_TASK_ID
+ ? null : getTaskViewByTaskId(mIgnoreResetTaskId);
// Save running task ID if it exists before rebinding all taskViews, otherwise the task from
// the runningTaskView currently bound could get assigned to another TaskView
@@ -1598,6 +1594,8 @@
// update the map of instance counts
mFilterState.updateInstanceCountMap(taskGroups);
+ // Clear out desktop view if it is set
+ mDesktopTaskView = null;
DesktopTask desktopTask = null;
// Add views as children based on whether it's grouped or single task. Looping through
@@ -1656,12 +1654,13 @@
if (!taskGroups.isEmpty()) {
addView(mClearAllButton);
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
- TaskView taskView = getTaskViewFromPool(TaskView.Type.DESKTOP);
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED
+ && !getSplitSelectController().isSplitSelectActive()) {
+ mDesktopTaskView = (DesktopTaskView) getTaskViewFromPool(TaskView.Type.DESKTOP);
// Always add a desktop task to the first position. Even if it is empty
- addView(taskView, 0);
+ addView(mDesktopTaskView, 0);
ArrayList<Task> tasks = desktopTask != null ? desktopTask.tasks : new ArrayList<>();
- ((DesktopTaskView) taskView).bind(tasks, mOrientationState);
+ mDesktopTaskView.bind(tasks, mOrientationState);
}
}
@@ -1677,20 +1676,20 @@
newFocusedTaskView = getTaskViewAt(1);
}
}
- mFocusedTaskViewId = newFocusedTaskView != null ?
- newFocusedTaskView.getTaskViewId() : -1;
+ mFocusedTaskViewId = newFocusedTaskView != null && !ENABLE_GRID_ONLY_OVERVIEW.get()
+ ? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID;
updateTaskSize();
updateChildTaskOrientations();
TaskView newRunningTaskView = null;
- if (runningTaskId != -1) {
+ if (runningTaskId != INVALID_TASK_ID) {
// Update mRunningTaskViewId to be the new TaskView that was assigned by binding
// the full list of tasks to taskViews
newRunningTaskView = getTaskViewByTaskId(runningTaskId);
if (newRunningTaskView != null) {
mRunningTaskViewId = newRunningTaskView.getTaskViewId();
} else {
- mRunningTaskViewId = -1;
+ mRunningTaskViewId = INVALID_TASK_ID;
}
}
@@ -1698,7 +1697,7 @@
if (mNextPage != INVALID_PAGE) {
// Restore mCurrentPage but don't call setCurrentPage() as that clobbers the scroll.
mCurrentPage = previousCurrentPage;
- if (currentTaskId != -1) {
+ if (currentTaskId != INVALID_TASK_ID) {
currentTaskView = getTaskViewByTaskId(currentTaskId);
if (currentTaskView != null) {
targetPage = indexOfChild(currentTaskView);
@@ -1706,7 +1705,7 @@
}
} else {
// Set the current page to the running task, but not if settling on new task.
- if (runningTaskId != -1) {
+ if (runningTaskId != INVALID_TASK_ID) {
targetPage = indexOfChild(newRunningTaskView);
} else if (getTaskViewCount() > 0) {
TaskView taskView = requireTaskViewAt(0);
@@ -1721,7 +1720,7 @@
int finalTargetPage = targetPage;
runOnPageScrollsInitialized(() -> {
// TODO(b/246283207): Remove logging once root cause of flake detected.
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
Log.d("b/246283207", "RecentsView#applyLoadPlan() -> "
+ "previousCurrentPage: " + previousCurrentPage
+ ", targetPage: " + finalTargetPage
@@ -1732,12 +1731,12 @@
});
}
- if (mIgnoreResetTaskId != -1 &&
+ if (mIgnoreResetTaskId != INVALID_TASK_ID &&
getTaskViewByTaskId(mIgnoreResetTaskId) != ignoreResetTaskView) {
// If the taskView mapping is changing, do not preserve the visuals. Since we are
// mostly preserving the first task, and new taskViews are added to the end, it should
// generally map to the same task.
- mIgnoreResetTaskId = -1;
+ mIgnoreResetTaskId = INVALID_TASK_ID;
}
resetTaskVisuals();
onTaskStackUpdated();
@@ -1793,7 +1792,7 @@
* Returns the number of tasks in the bottom row of the overview grid.
*/
public int getBottomRowTaskCountForTablet() {
- return getTaskViewCount() - mTopRowIdSet.size() - 1;
+ return getTaskViewCount() - mTopRowIdSet.size() - (ENABLE_GRID_ONLY_OVERVIEW.get() ? 0 : 1);
}
protected void onTaskStackUpdated() {
@@ -1953,6 +1952,10 @@
mLastComputedGridSize);
mSizeStrategy.calculateGridTaskSize(mActivity, mActivity.getDeviceProfile(),
mLastComputedGridTaskSize, mOrientationHandler);
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ mSizeStrategy.calculateDesktopTaskSize(mActivity, mActivity.getDeviceProfile(),
+ mLastComputedDesktopTaskSize);
+ }
mTaskGridVerticalDiff = mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
mTopBottomRowHeightDiff =
@@ -1999,7 +2002,8 @@
}
public void getTaskSize(Rect outRect) {
- mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
+ mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
+ mOrientationHandler);
mLastComputedTaskSize.set(outRect);
}
@@ -2042,9 +2046,15 @@
return mLastComputedGridTaskSize;
}
+ /** Gets the last computed desktop task size */
+ public Rect getLastComputedDesktopTaskSize() {
+ return mLastComputedDesktopTaskSize;
+ }
+
/** Gets the task size for modal state. */
public void getModalTaskSize(Rect outRect) {
- mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
+ mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
+ mOrientationHandler);
}
@Override
@@ -2477,8 +2487,7 @@
for (TaskViewSimulator tvs : taskViewSimulators) {
if (animatorSet == null) {
setGridProgress(1);
- tvs.taskPrimaryTranslation.value =
- runningTaskPrimaryGridTranslation;
+ tvs.taskPrimaryTranslation.value = runningTaskPrimaryGridTranslation;
} else {
animatorSet.play(ObjectAnimator.ofFloat(this, RECENTS_GRID_PROGRESS, 1));
animatorSet.play(tvs.taskPrimaryTranslation.animateToValue(
@@ -2587,7 +2596,7 @@
boolean runningTaskTileHidden = mRunningTaskTileHidden;
setCurrentTask(runningTaskViewId);
- mFocusedTaskViewId = runningTaskViewId;
+ mFocusedTaskViewId = ENABLE_GRID_ONLY_OVERVIEW.get() ? INVALID_TASK_ID : runningTaskViewId;
runOnPageScrollsInitialized(() -> setCurrentPage(getRunningTaskIndex()));
setRunningTaskViewShowScreenshot(false);
setRunningTaskHidden(runningTaskTileHidden);
@@ -2720,7 +2729,8 @@
return;
}
- int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
int topRowWidth = 0;
int bottomRowWidth = 0;
@@ -2775,10 +2785,17 @@
} else if (taskView.isDesktopTask()) {
// Desktop task was not focused. Pin it to the right of focused
desktopTaskIndex = i;
- gridTranslations[i] += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
+ if (taskView.getVisibility() == View.GONE) {
+ // Desktop task view is hidden, skip it from grid calculations
+ continue;
+ }
+ if (!ENABLE_GRID_ONLY_OVERVIEW.get()) {
+ // Only apply x-translation when using legacy overview grid
+ gridTranslations[i] += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
+ }
// Center view vertically in case it's from different orientation.
- taskView.setGridTranslationY((mLastComputedTaskSize.height() + taskTopMargin
+ taskView.setGridTranslationY((mLastComputedDesktopTaskSize.height() + taskTopMargin
- taskView.getLayoutParams().height) / 2f);
} else {
if (i > focusedTaskIndex) {
@@ -2862,7 +2879,7 @@
float snappedTaskGridTranslationX = 0;
if (snappedTaskView != null) {
snappedTaskNonGridScrollAdjustment = snappedTaskView.getScrollAdjustment(
- /*fullscreenEnabled=*/true, /*gridEnabled=*/false);
+ /*gridEnabled=*/false);
snappedTaskGridTranslationX = gridTranslations[snappedPage];
}
@@ -2887,18 +2904,28 @@
// If the total width is shorter than one grid's width, move ClearAllButton further away
// accordingly. Update longRowWidth if ClearAllButton has been moved.
- float clearAllShortTotalCompensation = 0;
+ float clearAllShortTotalWidthTranslation = 0;
int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
if (longRowWidth < mLastComputedGridSize.width()) {
- float shortTotalCompensation = mLastComputedGridSize.width() - longRowWidth;
- clearAllShortTotalCompensation =
- mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
- longRowWidth = mLastComputedGridSize.width();
+ mClearAllShortTotalWidthTranslation =
+ (mIsRtl
+ ? mLastComputedTaskSize.right
+ : deviceProfile.widthPx - mLastComputedTaskSize.left)
+ - longRowWidth - deviceProfile.overviewGridSideMargin;
+ clearAllShortTotalWidthTranslation = mIsRtl
+ ? -mClearAllShortTotalWidthTranslation : mClearAllShortTotalWidthTranslation;
+ if (snappedTaskRowWidth == longRowWidth) {
+ // Updated snappedTaskRowWidth as well if it's same as longRowWidth.
+ snappedTaskRowWidth += mClearAllShortTotalWidthTranslation;
+ }
+ longRowWidth += mClearAllShortTotalWidthTranslation;
+ } else {
+ mClearAllShortTotalWidthTranslation = 0;
}
float clearAllTotalTranslationX =
clearAllAccumulatedTranslation + clearAllShorterRowCompensation
- + clearAllShortTotalCompensation + snappedTaskNonGridScrollAdjustment;
+ + clearAllShortTotalWidthTranslation + snappedTaskNonGridScrollAdjustment;
if (focusedTaskIndex < taskCount) {
// Shift by focused task's width and spacing if a task is focused.
clearAllTotalTranslationX +=
@@ -2908,11 +2935,15 @@
// Make sure there are enough space between snapped page and ClearAllButton, for the case
// of swiping up after quick switch.
if (snappedTaskView != null) {
- int distanceFromClearAll = longRowWidth - snappedTaskRowWidth + mPageSpacing;
+ int distanceFromClearAll = longRowWidth - snappedTaskRowWidth;
// ClearAllButton should be off screen when snapped task is in its snapped position.
int minimumDistance =
- mTaskWidth - snappedTaskView.getLayoutParams().width
- + (mLastComputedGridSize.width() - mTaskWidth) / 2;
+ (mIsRtl
+ ? mLastComputedTaskSize.left
+ : deviceProfile.widthPx - mLastComputedTaskSize.right)
+ - deviceProfile.overviewGridSideMargin - mPageSpacing
+ + (mTaskWidth - snappedTaskView.getLayoutParams().width)
+ - mClearAllShortTotalWidthTranslation;
if (distanceFromClearAll < minimumDistance) {
int distanceDifference = minimumDistance - distanceFromClearAll;
snappedTaskGridTranslationX += mIsRtl ? distanceDifference : -distanceDifference;
@@ -3195,6 +3226,7 @@
// Grid specific properties.
boolean isFocusedTaskDismissed = false;
+ boolean isStagingFocusedTask = false;
TaskView nextFocusedTaskView = null;
boolean nextFocusedTaskFromTop = false;
float dismissedTaskWidth = 0;
@@ -3209,26 +3241,30 @@
if (showAsGrid) {
dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
- if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
- nextFocusedTaskFromTop =
- mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
- // Pick the next focused task from the preferred row.
- for (int i = 0; i < taskCount; i++) {
- TaskView taskView = requireTaskViewAt(i);
- if (taskView == dismissedTaskView) {
- continue;
+ if (isFocusedTaskDismissed) {
+ if (isSplitSelectionActive()) {
+ isStagingFocusedTask = true;
+ } else {
+ nextFocusedTaskFromTop =
+ mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
+ // Pick the next focused task from the preferred row.
+ for (int i = 0; i < taskCount; i++) {
+ TaskView taskView = requireTaskViewAt(i);
+ if (taskView == dismissedTaskView) {
+ continue;
+ }
+ boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
+ if ((nextFocusedTaskFromTop && isTopRow
+ || (!nextFocusedTaskFromTop && !isTopRow))) {
+ nextFocusedTaskView = taskView;
+ break;
+ }
}
- boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
- if ((nextFocusedTaskFromTop && isTopRow
- || (!nextFocusedTaskFromTop && !isTopRow))) {
- nextFocusedTaskView = taskView;
- break;
+ if (nextFocusedTaskView != null) {
+ nextFocusedTaskWidth =
+ nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
}
}
- if (nextFocusedTaskView != null) {
- nextFocusedTaskWidth =
- nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
- }
}
} else {
getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
@@ -3245,8 +3281,6 @@
boolean snapToLastTask = false;
boolean isLandscapeSplit =
mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
- boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
- boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
int currentPageScroll = getScrollForPage(mCurrentPage);
int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
@@ -3258,42 +3292,69 @@
float longGridRowWidthDiff = 0;
int topGridRowSize = mTopRowIdSet.size();
- int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
+ int bottomGridRowSize = taskCount - mTopRowIdSet.size()
+ - (ENABLE_GRID_ONLY_OVERVIEW.get() ? 0 : 1);
boolean topRowLonger = topGridRowSize > bottomGridRowSize;
boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
+ if (dismissedTaskFromTop || (isFocusedTaskDismissed && nextFocusedTaskFromTop)) {
+ topGridRowSize--;
+ }
+ if (dismissedTaskFromBottom || (isFocusedTaskDismissed && !nextFocusedTaskFromTop)) {
+ bottomGridRowSize--;
+ }
+ int longRowWidth = Math.max(topGridRowSize, bottomGridRowSize)
+ * (mLastComputedGridTaskSize.width() + mPageSpacing);
+ if (!ENABLE_GRID_ONLY_OVERVIEW.get() && !isStagingFocusedTask) {
+ longRowWidth += mLastComputedTaskSize.width() + mPageSpacing;
+ }
+
float gapWidth = 0;
if ((topRowLonger && dismissedTaskFromTop)
|| (bottomRowLonger && dismissedTaskFromBottom)) {
gapWidth = dismissedTaskWidth;
- } else if ((topRowLonger && nextFocusedTaskFromTop)
- || (bottomRowLonger && !nextFocusedTaskFromTop)) {
+ } else if (nextFocusedTaskView != null
+ && ((topRowLonger && nextFocusedTaskFromTop)
+ || (bottomRowLonger && !nextFocusedTaskFromTop))) {
gapWidth = nextFocusedTaskWidth;
}
if (gapWidth > 0) {
- if (taskCount > 2) {
- // Compensate the removed gap.
- longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
- if (isClearAllHidden) {
- // If ClearAllButton isn't fully shown, snap to the last task.
- snapToLastTask = true;
+ if (mClearAllShortTotalWidthTranslation == 0) {
+ // Compensate the removed gap if we don't already have shortTotalCompensation,
+ // and adjust accordingly to the new shortTotalCompensation after dismiss.
+ int newClearAllShortTotalWidthTranslation = 0;
+ if (longRowWidth < mLastComputedGridSize.width()) {
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+ newClearAllShortTotalWidthTranslation =
+ (mIsRtl
+ ? mLastComputedTaskSize.right
+ : deviceProfile.widthPx - mLastComputedTaskSize.left)
+ - longRowWidth - deviceProfile.overviewGridSideMargin;
}
- } else {
- // If only focused task will be left, snap to focused task instead.
- longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
+ float gapCompensation = gapWidth - newClearAllShortTotalWidthTranslation;
+ longGridRowWidthDiff += mIsRtl ? -gapCompensation : gapCompensation;
+ }
+ if (isClearAllHidden) {
+ // If ClearAllButton isn't fully shown, snap to the last task.
+ snapToLastTask = true;
}
}
- if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
- // ClearAllButton will not be available in split select, snap to last task instead.
- snapToLastTask = true;
+ if (isLandscapeSplit && !isStagingFocusedTask) {
+ // LastTask's scroll is the minimum scroll in split select, if current scroll is
+ // beyond that, we'll need to snap to last task instead.
+ TaskView lastTask = getLastGridTaskView();
+ if (lastTask != null) {
+ int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
+ int lastTaskScroll = getScrollForPage(indexOfChild(lastTask));
+ if ((mIsRtl && primaryScroll < lastTaskScroll)
+ || (!mIsRtl && primaryScroll > lastTaskScroll)) {
+ snapToLastTask = true;
+ }
+ }
}
if (snapToLastTask) {
longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
- if (isSplitPlaceholderLastInGrid) {
- // Shift all the tasks to make space for split placeholder.
- longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
- }
} else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
// Use last task as reference point for scroll diff and snapping calculation as it's
// the only invariant point in landscape split screen.
@@ -3451,8 +3512,6 @@
// dismissed index or next focused index. Offset successive task dismissal
// durations for a staggered effect.
distanceFromDismissedTask++;
- boolean isStagingFocusedTask =
- isFocusedTaskDismissed && nextFocusedTaskView == null;
int staggerColumn = isStagingFocusedTask
? (int) Math.ceil(distanceFromDismissedTask / 2f)
: distanceFromDismissedTask;
@@ -3508,11 +3567,6 @@
int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
primaryTranslation +=
mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
- if (isSplitPlaceholderFirstInGrid) {
- // Moves less if split placeholder is at the start.
- primaryTranslation +=
- mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
- }
}
anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(),
@@ -3641,14 +3695,6 @@
RecentsView.this);
int currentPageScroll = getScrollForPage(mCurrentPage);
mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
- // Compensate for coordinate shift by split placeholder.
- if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
- mCurrentPageScrollDiff +=
- mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
- } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
- mCurrentPageScrollDiff +=
- mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
- }
}
}
} else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
@@ -3662,14 +3708,15 @@
removeViewInLayout(mClearAllButton);
if (isHomeTaskDismissed) {
updateEmptyMessage();
- } else if (!(ENABLE_TASKBAR_IN_OVERVIEW.get() &&
- mSplitSelectStateController.isSplitSelectActive())) {
+ } else if (!mSplitSelectStateController.isSplitSelectActive()) {
startHome();
}
} else {
// Update focus task and its size.
if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
- mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
+ mFocusedTaskViewId = ENABLE_GRID_ONLY_OVERVIEW.get()
+ ? INVALID_TASK_ID
+ : finalNextFocusedTaskView.getTaskViewId();
mTopRowIdSet.remove(mFocusedTaskViewId);
finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
}
@@ -3688,8 +3735,7 @@
int screenStart = mOrientationHandler.getPrimaryScroll(
RecentsView.this);
int taskStart = mOrientationHandler.getChildStart(taskView)
- + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
- false, /*gridEnabled=*/ true);
+ + (int) taskView.getOffsetAdjustment(/*gridEnabled=*/ true);
// Rebalance only if there is a maximum gap between the task and the
// screen's edge; this ensures that rebalanced tasks are outside the
@@ -3765,8 +3811,11 @@
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
mActionsView.updateSplitButtonHiddenFlags(FLAG_IS_NOT_TABLET,
!mActivity.getDeviceProfile().isTablet);
- mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK,
- !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get() && getTaskViewCount() <= 1);
+ mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK, /*enable=*/ false);
+ if (DESKTOP_MODE_SUPPORTED) {
+ boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
+ mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
+ }
}
/**
@@ -3848,14 +3897,6 @@
REMOVE_TASK_WAIT_FOR_APP_STOP_MS);
}
- /**
- * Returns {@code true} if one of the task thumbnails would intersect/overlap with the
- * {@link #mFirstFloatingTaskView}.
- */
- public boolean shouldShiftThumbnailsForSplitSelect() {
- return !mActivity.getDeviceProfile().isTablet || !mActivity.getDeviceProfile().isLandscape;
- }
-
protected void onDismissAnimationEnds() {
AccessibilityManagerCompat.sendDismissAnimationEndsEventToTest(getContext());
}
@@ -4414,65 +4455,6 @@
}
/**
- * Apply scroll offset to children of RecentsView when entering split select.
- */
- public void applySplitPrimaryScrollOffset() {
- float taskSplitScrollOffsetPrimary = 0f;
- float clearAllSplitScrollOffsetPrimar = 0f;
- if (isSplitPlaceholderFirstInGrid()) {
- taskSplitScrollOffsetPrimary = mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
- } else if (isSplitPlaceholderLastInGrid()) {
- clearAllSplitScrollOffsetPrimar =
- mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
- }
-
- for (int i = 0; i < getTaskViewCount(); i++) {
- requireTaskViewAt(i).setSplitScrollOffsetPrimary(taskSplitScrollOffsetPrimary);
- }
- mClearAllButton.setSplitSelectScrollOffsetPrimary(clearAllSplitScrollOffsetPrimar);
- }
-
- /**
- * Returns if split placeholder is at the beginning of RecentsView. Always returns {@code false}
- * if RecentsView is in portrait or RecentsView isn't shown as grid.
- */
- private boolean isSplitPlaceholderFirstInGrid() {
- if (!mActivity.getDeviceProfile().isLandscape || !showAsGrid()
- || !isSplitSelectionActive()) {
- return false;
- }
- @StagePosition int position = mSplitSelectStateController.getActiveSplitStagePosition();
- return mIsRtl
- ? position == STAGE_POSITION_BOTTOM_OR_RIGHT
- : position == STAGE_POSITION_TOP_OR_LEFT;
- }
-
- /**
- * Returns if split placeholder is at the end of RecentsView. Always returns {@code false} if
- * RecentsView is in portrait or RecentsView isn't shown as grid.
- */
- private boolean isSplitPlaceholderLastInGrid() {
- if (!mActivity.getDeviceProfile().isLandscape || !showAsGrid()
- || !isSplitSelectionActive()) {
- return false;
- }
- @StagePosition int position = mSplitSelectStateController.getActiveSplitStagePosition();
- return mIsRtl
- ? position == STAGE_POSITION_TOP_OR_LEFT
- : position == STAGE_POSITION_BOTTOM_OR_RIGHT;
- }
-
- /**
- * Reset scroll offset on children of RecentsView when exiting split select.
- */
- public void resetSplitPrimaryScrollOffset() {
- for (int i = 0; i < getTaskViewCount(); i++) {
- requireTaskViewAt(i).setSplitScrollOffsetPrimary(0);
- }
- mClearAllButton.setSplitSelectScrollOffsetPrimary(0);
- }
-
- /**
* Resets the visuals when exit modal state.
*/
public void resetModalVisuals() {
@@ -4500,6 +4482,9 @@
mSplitSelectStateController.setAnimateCurrentTaskDismissal(
true /*animateCurrentTaskDismissal*/);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ updateDesktopTaskVisibility(false /* visible */);
+ }
}
/**
@@ -4508,6 +4493,7 @@
* Attempts to initiate split with an existing taskView, if one exists
*/
public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
+ TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "enterSplitSelect");
mSplitSelectSource = splitSelectSource;
mSplitHiddenTaskView = getTaskViewByTaskId(splitSelectSource.alreadyRunningTaskId);
mSplitHiddenTaskViewIndex = indexOfChild(mSplitHiddenTaskView);
@@ -4516,6 +4502,15 @@
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ updateDesktopTaskVisibility(false /* visible */);
+ }
+ }
+
+ private void updateDesktopTaskVisibility(boolean visible) {
+ if (mDesktopTaskView != null) {
+ mDesktopTaskView.setVisibility(visible ? VISIBLE : GONE);
+ }
}
/**
@@ -4624,7 +4619,6 @@
return true;
}
- /** TODO(b/181707736) More gracefully handle exiting split selection state */
@SuppressLint("WrongCall")
protected void resetFromSplitSelectionState() {
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
@@ -4667,6 +4661,9 @@
mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE);
mSplitHiddenTaskView = null;
}
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ updateDesktopTaskVisibility(true /* visible */);
+ }
}
private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
@@ -4680,14 +4677,29 @@
* Note that the translation can be its primary or secondary dimension.
*/
public float getSplitSelectTranslation() {
- int splitPosition = getSplitSelectController().getActiveSplitStagePosition();
- if (!shouldShiftThumbnailsForSplitSelect()) {
- return 0f;
- }
+ DeviceProfile deviceProfile = mActivity.getDeviceProfile();
PagedOrientationHandler orientationHandler = getPagedOrientationHandler();
+ int splitPosition = getSplitSelectController().getActiveSplitStagePosition();
+ int splitPlaceholderSize =
+ mActivity.getResources().getDimensionPixelSize(R.dimen.split_placeholder_size);
int direction = orientationHandler.getSplitTranslationDirectionFactor(
- splitPosition, mActivity.getDeviceProfile());
- return mActivity.getResources().getDimension(R.dimen.split_placeholder_size) * direction;
+ splitPosition, deviceProfile);
+
+ if (deviceProfile.isTablet && deviceProfile.isLandscape) {
+ // Only shift TaskViews if there is not enough space on the side of
+ // mLastComputedTaskSize to minimize motion.
+ int sideSpace = mIsRtl
+ ? deviceProfile.widthPx - mLastComputedTaskSize.right
+ : mLastComputedTaskSize.left;
+ int extraSpace = splitPlaceholderSize + mPageSpacing - sideSpace;
+ if (extraSpace <= 0f) {
+ return 0f;
+ }
+
+ return extraSpace * direction;
+ }
+
+ return splitPlaceholderSize * direction;
}
protected void onRotateInSplitSelectionState() {
@@ -4709,8 +4721,6 @@
if (mSplitInstructionsView != null) {
mSplitInstructionsView.ensureProperRotation();
}
-
- applySplitPrimaryScrollOffset();
}
private void updateDeadZoneRects() {
@@ -5025,8 +5035,7 @@
mRemoteTargetHandles = gluer.assignTargetsForDesktop(recentsAnimationTargets);
} else {
gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
- mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(
- getContext(), recentsAnimationTargets);
+ mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
}
mSplitBoundsConfig = gluer.getSplitBounds();
// Add release check to the targets from the RemoteTargetGluer and not the targets
@@ -5201,11 +5210,21 @@
}
private int getLastViewIndex() {
- return mDisallowScrollToClearAll
- ? mShowAsGridLastOnLayout
- ? indexOfChild(getLastGridTaskView())
- : getTaskViewCount() - 1
- : indexOfChild(mClearAllButton);
+ if (!mDisallowScrollToClearAll) {
+ return indexOfChild(mClearAllButton);
+ }
+
+ if (!mShowAsGridLastOnLayout) {
+ return getTaskViewCount() - 1;
+ }
+
+ TaskView lastGridTaskView = getLastGridTaskView();
+ if (lastGridTaskView != null) {
+ return indexOfChild(lastGridTaskView);
+ }
+
+ // Returns focus task if there are no grid tasks.
+ return indexOfChild(getFocusedTaskView());
}
/**
@@ -5246,11 +5265,11 @@
}
final int taskCount = getTaskViewCount();
+ int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
- float scrollDiff = taskView.getScrollAdjustment(showAsFullscreen, showAsGrid);
+ float scrollDiff = taskView.getScrollAdjustment(showAsGrid);
int pageScroll = newPageScrolls[i] + (int) scrollDiff;
- int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
if ((mIsRtl && pageScroll < lastTaskScroll)
|| (!mIsRtl && pageScroll > lastTaskScroll)) {
pageScroll = lastTaskScroll;
@@ -5274,8 +5293,7 @@
int childOffset = super.getChildOffset(index);
View child = getChildAt(index);
if (child instanceof TaskView) {
- childOffset += ((TaskView) child).getOffsetAdjustment(showAsFullscreen(),
- showAsGrid());
+ childOffset += ((TaskView) child).getOffsetAdjustment(showAsGrid());
} else if (child instanceof ClearAllButton) {
childOffset += ((ClearAllButton) child).getOffsetAdjustment(mOverviewFullscreenEnabled,
showAsGrid());
@@ -5383,17 +5401,19 @@
int gridTaskSizeAndSpacing = mLastComputedGridTaskSize.width() + mPageSpacing;
int positionDiff = gridTaskSizeAndSpacing * (lastGridTaskViewPosition - taskViewPosition);
- int lastTaskEnd = (mIsRtl
- ? mLastComputedGridSize.left
- : mLastComputedGridSize.right)
- + (mIsRtl ? mPageSpacing : -mPageSpacing);
- int taskEnd = lastTaskEnd + (mIsRtl ? positionDiff : -positionDiff);
+ int taskEnd = getLastTaskEnd() + (mIsRtl ? positionDiff : -positionDiff);
int normalTaskEnd = mIsRtl
? mLastComputedGridTaskSize.left
: mLastComputedGridTaskSize.right;
return taskEnd - normalTaskEnd;
}
+ private int getLastTaskEnd() {
+ return mIsRtl
+ ? mLastComputedGridSize.left + mPageSpacing + mClearAllShortTotalWidthTranslation
+ : mLastComputedGridSize.right - mPageSpacing - mClearAllShortTotalWidthTranslation;
+ }
+
private int getPositionInRow(
TaskView taskView, IntArray topRowIdArray, IntArray bottomRowIdArray) {
int position = topRowIdArray.indexOf(taskView.getTaskViewId());
@@ -5693,14 +5713,10 @@
taskView = getTaskViewAt(--targetPage);
}
// Target a scroll where targetPage is on left of screen but still fully visible.
- int lastTaskEnd = (mIsRtl
- ? mLastComputedGridSize.left
- : mLastComputedGridSize.right)
- + (mIsRtl ? mPageSpacing : -mPageSpacing);
int normalTaskEnd = mIsRtl
? mLastComputedGridTaskSize.left
: mLastComputedGridTaskSize.right;
- int targetScroll = getScrollForPage(targetPage) + normalTaskEnd - lastTaskEnd;
+ int targetScroll = getScrollForPage(targetPage) + normalTaskEnd - getLastTaskEnd();
// Find a page that is close to targetScroll while not over it.
while (targetPage - 1 >= 0
&& (mIsRtl
diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
index b0b111d..0d9e412 100644
--- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
@@ -16,8 +16,6 @@
package com.android.quickstep.views;
-import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
-
import android.content.Context;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -27,11 +25,8 @@
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.util.DisplayController;
/**
* A rounded rectangular component containing a single TextView.
@@ -103,36 +98,10 @@
this,
mLauncher.getDeviceProfile(),
getMeasuredHeight(),
- getMeasuredWidth(),
- getThreeButtonNavShift()
+ getMeasuredWidth()
);
}
- // In some cases, when user is using 3-button nav, there isn't enough room for both the
- // 3-button nav and a centered SplitInstructionsView. This function will return an int that will
- // be used to shift the SplitInstructionsView over a bit so that everything looks well-spaced.
- // In many cases, this will return 0, since we don't need to shift it away from the center.
- int getThreeButtonNavShift() {
- DeviceProfile dp = mLauncher.getDeviceProfile();
- if ((DisplayController.getNavigationMode(getContext()) == THREE_BUTTONS)
- && ((dp.isTwoPanels) || (dp.isTablet && !dp.isLandscape))
- // If taskbar is in overview, overview action has dedicated space above nav buttons
- && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- int navButtonWidth = getResources().getDimensionPixelSize(
- R.dimen.taskbar_nav_buttons_size);
- int extraMargin = getResources().getDimensionPixelSize(
- R.dimen.taskbar_split_instructions_margin);
- // Explanation: The 3-button nav for non-phones sits on one side of the screen, taking
- // up 3 buttons + a side margin worth of space. Our splitInstructionsView starts in the
- // center of the screen and we want to center it in the remaining space, therefore we
- // want to shift it over by half the 3-button layout's width.
- // If the user is using an RtL layout, we shift it the opposite way.
- return -((3 * navButtonWidth + extraMargin) / 2) * (isLayoutRtl() ? -1 : 1);
- } else {
- return 0;
- }
- }
-
public AppCompatTextView getTextView() {
return mTextView;
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index fb85605..ab72f2d 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -375,7 +375,6 @@
// Used when in SplitScreenSelectState
private float mSplitSelectTranslationY;
private float mSplitSelectTranslationX;
- private float mSplitSelectScrollOffsetPrimary;
@Nullable
private ObjectAnimator mIconAndDimAnimator;
@@ -1297,10 +1296,6 @@
applyTranslationY();
}
- public void setSplitScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
- mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
- }
-
private void setDismissTranslationX(float x) {
mDismissTranslationX = x;
applyTranslationX();
@@ -1364,19 +1359,18 @@
applyTranslationX();
}
- public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
+ public float getScrollAdjustment(boolean gridEnabled) {
float scrollAdjustment = 0;
if (gridEnabled) {
scrollAdjustment += mGridTranslationX;
} else {
scrollAdjustment += getPrimaryNonGridTranslationProperty().get(this);
}
- scrollAdjustment += mSplitSelectScrollOffsetPrimary;
return scrollAdjustment;
}
- public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
- return getScrollAdjustment(fullscreenEnabled, gridEnabled);
+ public float getOffsetAdjustment(boolean gridEnabled) {
+ return getScrollAdjustment(gridEnabled);
}
public float getSizeAdjustment(boolean fullscreenEnabled) {
@@ -1625,7 +1619,12 @@
int boxWidth;
int boxHeight;
boolean isFocusedTask = isFocusedTask();
- if (isFocusedTask || isDesktopTask()) {
+ if (isDesktopTask()) {
+ Rect lastComputedDesktopTaskSize =
+ getRecentsView().getLastComputedDesktopTaskSize();
+ boxWidth = lastComputedDesktopTaskSize.width();
+ boxHeight = lastComputedDesktopTaskSize.height();
+ } else if (isFocusedTask) {
// Task will be focused and should use focused task size. Use focusTaskRatio
// that is associated with the original orientation of the focused task.
boxWidth = taskWidth;
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt
index 5a53d38..8c13fe3 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/FallbackTaskbarUIControllerTest.kt
@@ -28,7 +28,6 @@
import org.mockito.Mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations.initMocks
import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidJUnit4::class)
@@ -37,10 +36,8 @@
lateinit var fallbackTaskbarUIController: FallbackTaskbarUIController
lateinit var stateListener: StateManager.StateListener<RecentsState>
- @Mock
- lateinit var recentsActivity: RecentsActivity
- @Mock
- lateinit var stateManager: StateManager<RecentsState>
+ @Mock lateinit var recentsActivity: RecentsActivity
+ @Mock lateinit var stateManager: StateManager<RecentsState>
@Before
override fun setup() {
@@ -80,4 +77,4 @@
// verify split selection enabled
verify(taskbarPopupController, times(1)).setAllowInitialSplitSelection(false)
}
-}
\ No newline at end of file
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
new file mode 100644
index 0000000..f10b917
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import android.content.Intent;
+
+import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.rule.TestStabilityRule;
+import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
+
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TaplTestsSplitscreen extends AbstractQuickStepTest {
+ private static final String CALCULATOR_APP_NAME = "Calculator";
+ private static final String CALCULATOR_APP_PACKAGE =
+ resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ TaplTestsLauncher3.initialize(this);
+
+ mLauncher.getWorkspace()
+ .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
+ .switchToAllApps()
+ .getAppIcon(CALCULATOR_APP_NAME)
+ .dragToHotseat(0);
+
+ startAppFast(CALCULATOR_APP_PACKAGE);
+ mLauncher.enableBlockTimeout(true);
+ mLauncher.showTaskbarIfHidden();
+ }
+
+ @After
+ public void tearDown() {
+ mLauncher.enableBlockTimeout(false);
+ }
+
+ @Test
+ // TODO (b/270201357): When this test is proven stable, remove this TestStabilityRule and
+ // introduce into presubmit as well.
+ @TestStabilityRule.Stability(
+ flavors = TestStabilityRule.LOCAL | TestStabilityRule.PLATFORM_POSTSUBMIT)
+ @PortraitLandscape
+ @TaskbarModeSwitch
+ public void testSplitAppFromHomeWithItself() throws Exception {
+ Assume.assumeTrue(mLauncher.isTablet());
+
+ mLauncher.goHome()
+ .switchToAllApps()
+ .getAppIcon(CALCULATOR_APP_NAME)
+ .openMenu()
+ .getSplitScreenMenuItem()
+ .click();
+
+ mLauncher.getLaunchedAppState()
+ .getTaskbar()
+ .getAppIcon(CALCULATOR_APP_NAME)
+ .launchIntoSplitScreen();
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index aed26d3..735c5e6 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -92,6 +92,7 @@
@TaskbarModeSwitch(mode = TRANSIENT)
public void testTransientLaunchApp() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().assertTaskbarHidden();
}
@Test
@@ -140,6 +141,7 @@
public void testTransientLaunchAppInSplitscreen() throws Exception {
getTaskbar().getAppIcon(TEST_APP_NAME).dragToSplitscreen(
TEST_APP_PACKAGE, CALCULATOR_APP_PACKAGE);
+ mLauncher.getLaunchedAppState().assertTaskbarHidden();
}
@Test
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 9db0368..512df8e 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -23,17 +23,21 @@
import android.content.Intent
import android.graphics.Rect
import android.os.Handler
+import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.LauncherState
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.statehandlers.DepthController
import com.android.launcher3.statemanager.StateManager
+import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.withArgCaptor
import com.android.quickstep.RecentsModel
import com.android.quickstep.SystemUiProxy
import com.android.systemui.shared.recents.model.Task
+import java.util.ArrayList
+import java.util.function.Consumer
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
@@ -44,9 +48,6 @@
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import java.util.ArrayList
-import java.util.function.Consumer
-
@RunWith(AndroidJUnit4::class)
class SplitSelectStateControllerTest {
@@ -61,37 +62,55 @@
lateinit var splitSelectStateController: SplitSelectStateController
+ private val primaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId)
+ private val nonPrimaryUserHandle = UserHandle(ActivityManager.RunningTaskInfo().userId + 10)
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- splitSelectStateController = SplitSelectStateController(context, handler,
- stateManager, depthController, statsLogManager, systemUiProxy, recentsModel)
+ splitSelectStateController =
+ SplitSelectStateController(
+ context,
+ handler,
+ stateManager,
+ depthController,
+ statsLogManager,
+ systemUiProxy,
+ recentsModel
+ )
}
@Test
fun activeTasks_noMatchingTasks() {
- val groupTask1 = generateGroupTask(
+ val nonMatchingComponent = ComponentKey(ComponentName("no", "match"), primaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
ComponentName("pomegranate", "juice"),
- ComponentName("pumpkin", "pie"))
- val groupTask2 = generateGroupTask(
+ ComponentName("pumpkin", "pie")
+ )
+ val groupTask2 =
+ generateGroupTask(
ComponentName("hotdog", "juice"),
- ComponentName("personal", "computer"))
+ ComponentName("personal", "computer")
+ )
val tasks: ArrayList<GroupTask> = ArrayList()
tasks.add(groupTask1)
tasks.add(groupTask2)
// Assertions happen in the callback we get from what we pass into
// #findLastActiveTaskAndRunCallback
- val taskConsumer = Consumer<Task> {
- assertNull("No tasks should have matched", it /*task*/)
- }
+ val taskConsumer =
+ Consumer<Task> { assertNull("No tasks should have matched", it /*task*/) }
// Capture callback from recentsModel#getTasks()
- val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- ComponentName("no", "match"), taskConsumer)
- verify(recentsModel).getTasks(capture())
- }
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ nonMatchingComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
// Send our mocked tasks
consumer.accept(tasks)
@@ -101,32 +120,141 @@
fun activeTasks_singleMatchingTask() {
val matchingPackage = "hotdog"
val matchingClass = "juice"
- val groupTask1 = generateGroupTask(
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
ComponentName(matchingPackage, matchingClass),
- ComponentName("pomegranate", "juice"))
- val groupTask2 = generateGroupTask(
+ ComponentName("pomegranate", "juice")
+ )
+ val groupTask2 =
+ generateGroupTask(
ComponentName("pumpkin", "pie"),
- ComponentName("personal", "computer"))
+ ComponentName("personal", "computer")
+ )
val tasks: ArrayList<GroupTask> = ArrayList()
tasks.add(groupTask1)
tasks.add(groupTask2)
// Assertions happen in the callback we get from what we pass into
// #findLastActiveTaskAndRunCallback
- val taskConsumer = Consumer<Task> {
- assertEquals("ComponentName package mismatched",
- it.key.baseIntent.component.packageName, matchingPackage)
- assertEquals("ComponentName class mismatched",
- it.key.baseIntent.component.className, matchingClass)
- assertEquals(it, groupTask1.task1)
- }
+ val taskConsumer =
+ Consumer<Task> {
+ assertEquals(
+ "ComponentName package mismatched",
+ it.key.baseIntent.component.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it.key.baseIntent.component.className,
+ matchingClass
+ )
+ assertEquals(it, groupTask1.task1)
+ }
// Capture callback from recentsModel#getTasks()
- val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- ComponentName(matchingPackage, matchingClass), taskConsumer)
- verify(recentsModel).getTasks(capture())
- }
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ matchingComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_skipTaskWithDifferentUser() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val nonPrimaryUserComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), nonPrimaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName(matchingPackage, matchingClass),
+ ComponentName("pomegranate", "juice")
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pumpkin", "pie"),
+ ComponentName("personal", "computer")
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask1)
+ tasks.add(groupTask2)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTaskAndRunCallback
+ val taskConsumer =
+ Consumer<Task> { assertNull("No tasks should have matched", it /*task*/) }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ nonPrimaryUserComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
+
+ // Send our mocked tasks
+ consumer.accept(tasks)
+ }
+
+ @Test
+ fun activeTasks_findTaskAsNonPrimaryUser() {
+ val matchingPackage = "hotdog"
+ val matchingClass = "juice"
+ val nonPrimaryUserComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), nonPrimaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
+ ComponentName(matchingPackage, matchingClass),
+ nonPrimaryUserHandle,
+ ComponentName("pomegranate", "juice"),
+ nonPrimaryUserHandle
+ )
+ val groupTask2 =
+ generateGroupTask(
+ ComponentName("pumpkin", "pie"),
+ ComponentName("personal", "computer")
+ )
+ val tasks: ArrayList<GroupTask> = ArrayList()
+ tasks.add(groupTask1)
+ tasks.add(groupTask2)
+
+ // Assertions happen in the callback we get from what we pass into
+ // #findLastActiveTaskAndRunCallback
+ val taskConsumer =
+ Consumer<Task> {
+ assertEquals(
+ "ComponentName package mismatched",
+ it.key.baseIntent.component.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it.key.baseIntent.component.className,
+ matchingClass
+ )
+ assertEquals("userId mismatched", it.key.userId, nonPrimaryUserHandle.identifier)
+ assertEquals(it, groupTask1.task1)
+ }
+
+ // Capture callback from recentsModel#getTasks()
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ nonPrimaryUserComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
// Send our mocked tasks
consumer.accept(tasks)
@@ -136,32 +264,48 @@
fun activeTasks_multipleMatchMostRecentTask() {
val matchingPackage = "hotdog"
val matchingClass = "juice"
- val groupTask1 = generateGroupTask(
+ val matchingComponent =
+ ComponentKey(ComponentName(matchingPackage, matchingClass), primaryUserHandle)
+ val groupTask1 =
+ generateGroupTask(
ComponentName(matchingPackage, matchingClass),
- ComponentName("pumpkin", "pie"))
- val groupTask2 = generateGroupTask(
+ ComponentName("pumpkin", "pie")
+ )
+ val groupTask2 =
+ generateGroupTask(
ComponentName("pomegranate", "juice"),
- ComponentName(matchingPackage, matchingClass))
+ ComponentName(matchingPackage, matchingClass)
+ )
val tasks: ArrayList<GroupTask> = ArrayList()
tasks.add(groupTask2)
tasks.add(groupTask1)
// Assertions happen in the callback we get from what we pass into
// #findLastActiveTaskAndRunCallback
- val taskConsumer = Consumer<Task> {
- assertEquals("ComponentName package mismatched",
- it.key.baseIntent.component.packageName, matchingPackage)
- assertEquals("ComponentName class mismatched",
- it.key.baseIntent.component.className, matchingClass)
- assertEquals(it, groupTask2.task2)
- }
+ val taskConsumer =
+ Consumer<Task> {
+ assertEquals(
+ "ComponentName package mismatched",
+ it.key.baseIntent.component.packageName,
+ matchingPackage
+ )
+ assertEquals(
+ "ComponentName class mismatched",
+ it.key.baseIntent.component.className,
+ matchingClass
+ )
+ assertEquals(it, groupTask2.task2)
+ }
// Capture callback from recentsModel#getTasks()
- val consumer = withArgCaptor<Consumer<ArrayList<GroupTask>>> {
- splitSelectStateController.findLastActiveTaskAndRunCallback(
- ComponentName(matchingPackage, matchingClass), taskConsumer)
- verify(recentsModel).getTasks(capture())
- }
+ val consumer =
+ withArgCaptor<Consumer<ArrayList<GroupTask>>> {
+ splitSelectStateController.findLastActiveTaskAndRunCallback(
+ matchingComponent,
+ taskConsumer
+ )
+ verify(recentsModel).getTasks(capture())
+ }
// Send our mocked tasks
consumer.accept(tasks)
@@ -169,29 +313,46 @@
@Test
fun setInitialApp_withTaskId() {
- splitSelectStateController.setInitialTaskSelect(null /*intent*/,
- -1 /*stagePosition*/, ItemInfo(), null /*splitEvent*/, 10 /*alreadyRunningTask*/)
+ splitSelectStateController.setInitialTaskSelect(
+ null /*intent*/,
+ -1 /*stagePosition*/,
+ ItemInfo(),
+ null /*splitEvent*/,
+ 10 /*alreadyRunningTask*/
+ )
assertTrue(splitSelectStateController.isSplitSelectActive)
}
@Test
fun setInitialApp_withIntent() {
- splitSelectStateController.setInitialTaskSelect(Intent() /*intent*/,
- -1 /*stagePosition*/, ItemInfo(), null /*splitEvent*/, -1 /*alreadyRunningTask*/)
+ splitSelectStateController.setInitialTaskSelect(
+ Intent() /*intent*/,
+ -1 /*stagePosition*/,
+ ItemInfo(),
+ null /*splitEvent*/,
+ -1 /*alreadyRunningTask*/
+ )
assertTrue(splitSelectStateController.isSplitSelectActive)
}
@Test
fun resetAfterInitial() {
- splitSelectStateController.setInitialTaskSelect(Intent() /*intent*/,
- -1 /*stagePosition*/, ItemInfo(), null /*splitEvent*/,
- -1)
+ splitSelectStateController.setInitialTaskSelect(
+ Intent() /*intent*/,
+ -1 /*stagePosition*/,
+ ItemInfo(),
+ null /*splitEvent*/,
+ -1
+ )
splitSelectStateController.resetState()
assertFalse(splitSelectStateController.isSplitSelectActive)
}
- private fun generateGroupTask(task1ComponentName: ComponentName,
- task2ComponentName: ComponentName): GroupTask {
+ // Generate GroupTask with default userId.
+ private fun generateGroupTask(
+ task1ComponentName: ComponentName,
+ task2ComponentName: ComponentName
+ ): GroupTask {
val task1 = Task()
var taskInfo = ActivityManager.RunningTaskInfo()
var intent = Intent()
@@ -205,8 +366,40 @@
intent.component = task2ComponentName
taskInfo.baseIntent = intent
task2.key = Task.TaskKey(taskInfo)
- return GroupTask(task1, task2, SplitConfigurationOptions.SplitBounds(
- Rect(), Rect(), -1, -1
- ))
+ return GroupTask(
+ task1,
+ task2,
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ )
}
-}
\ No newline at end of file
+
+ // Generate GroupTask with custom user handles.
+ private fun generateGroupTask(
+ task1ComponentName: ComponentName,
+ userHandle1: UserHandle,
+ task2ComponentName: ComponentName,
+ userHandle2: UserHandle
+ ): GroupTask {
+ val task1 = Task()
+ var taskInfo = ActivityManager.RunningTaskInfo()
+ // Apply custom userHandle1
+ taskInfo.userId = userHandle1.identifier
+ var intent = Intent()
+ intent.component = task1ComponentName
+ taskInfo.baseIntent = intent
+ task1.key = Task.TaskKey(taskInfo)
+ val task2 = Task()
+ taskInfo = ActivityManager.RunningTaskInfo()
+ // Apply custom userHandle2
+ taskInfo.userId = userHandle2.identifier
+ intent = Intent()
+ intent.component = task2ComponentName
+ taskInfo.baseIntent = intent
+ task2.key = Task.TaskKey(taskInfo)
+ return GroupTask(
+ task1,
+ task2,
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1)
+ )
+ }
+}
diff --git a/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml b/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml
new file mode 100644
index 0000000..6e740ae
--- /dev/null
+++ b/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M13.5,17C12.538,17 11.715,16.65 11.033,15.967C10.35,15.285 10,14.462 10,13.5C10,12.538 10.35,11.715 11.033,11.033C11.715,10.35 12.538,10 13.5,10C14.462,10 15.285,10.35 15.967,11.033C16.65,11.715 17,12.538 17,13.5C17,14.462 16.65,15.285 15.967,15.967C15.285,16.65 14.462,17 13.5,17Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M24,17C23.038,17 22.215,16.65 21.532,15.967C20.85,15.285 20.5,14.462 20.5,13.5C20.5,12.538 20.85,11.715 21.532,11.033C22.215,10.35 23.038,10 24,10C24.962,10 25.785,10.35 26.468,11.033C27.15,11.715 27.5,12.538 27.5,13.5C27.5,14.462 27.15,15.285 26.468,15.967C25.785,16.65 24.962,17 24,17Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M34.5,17C33.537,17 32.715,16.65 32.033,15.967C31.35,15.285 31,14.462 31,13.5C31,12.538 31.35,11.715 32.033,11.033C32.715,10.35 33.537,10 34.5,10C35.463,10 36.285,10.35 36.967,11.033C37.65,11.715 38,12.538 38,13.5C38,14.462 37.65,15.285 36.967,15.967C36.285,16.65 35.463,17 34.5,17Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M13.5,27.5C12.538,27.5 11.715,27.15 11.033,26.468C10.35,25.785 10,24.962 10,24C10,23.038 10.35,22.215 11.033,21.532C11.715,20.85 12.538,20.5 13.5,20.5C14.462,20.5 15.285,20.85 15.967,21.532C16.65,22.215 17,23.038 17,24C17,24.962 16.65,25.785 15.967,26.468C15.285,27.15 14.462,27.5 13.5,27.5Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M24,27.5C23.038,27.5 22.215,27.15 21.532,26.468C20.85,25.785 20.5,24.962 20.5,24C20.5,23.038 20.85,22.215 21.532,21.532C22.215,20.85 23.038,20.5 24,20.5C24.962,20.5 25.785,20.85 26.468,21.532C27.15,22.215 27.5,23.038 27.5,24C27.5,24.962 27.15,25.785 26.468,26.468C25.785,27.15 24.962,27.5 24,27.5Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M34.5,27.5C33.537,27.5 32.715,27.15 32.033,26.468C31.35,25.785 31,24.962 31,24C31,23.038 31.35,22.215 32.033,21.532C32.715,20.85 33.537,20.5 34.5,20.5C35.463,20.5 36.285,20.85 36.967,21.532C37.65,22.215 38,23.038 38,24C38,24.962 37.65,25.785 36.967,26.468C36.285,27.15 35.463,27.5 34.5,27.5Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M13.5,38C12.538,38 11.715,37.65 11.033,36.967C10.35,36.285 10,35.463 10,34.5C10,33.537 10.35,32.715 11.033,32.033C11.715,31.35 12.538,31 13.5,31C14.462,31 15.285,31.35 15.967,32.033C16.65,32.715 17,33.537 17,34.5C17,35.463 16.65,36.285 15.967,36.967C15.285,37.65 14.462,38 13.5,38Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M24,38C23.038,38 22.215,37.65 21.532,36.967C20.85,36.285 20.5,35.463 20.5,34.5C20.5,33.537 20.85,32.715 21.532,32.033C22.215,31.35 23.038,31 24,31C24.962,31 25.785,31.35 26.468,32.033C27.15,32.715 27.5,33.537 27.5,34.5C27.5,35.463 27.15,36.285 26.468,36.967C25.785,37.65 24.962,38 24,38Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M34.5,38C33.537,38 32.715,37.65 32.033,36.967C31.35,36.285 31,35.463 31,34.5C31,33.537 31.35,32.715 32.033,32.033C32.715,31.35 33.537,31 34.5,31C35.463,31 36.285,31.35 36.967,32.033C37.65,32.715 38,33.537 38,34.5C38,35.463 37.65,36.285 36.967,36.967C36.285,37.65 35.463,38 34.5,38Z"
+ android:fillColor="#40484B"/>
+</vector>
diff --git a/res/drawable/ic_all_apps_button.xml b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml
similarity index 100%
rename from res/drawable/ic_all_apps_button.xml
rename to res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml
diff --git a/res/drawable/ic_taskbar_all_apps_button.xml b/res/drawable/ic_taskbar_all_apps_button.xml
new file mode 100644
index 0000000..82fbbea
--- /dev/null
+++ b/res/drawable/ic_taskbar_all_apps_button.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="44dp"
+ android:height="44dp"
+ android:viewportWidth="44"
+ android:viewportHeight="44">
+ <path
+ android:pathData="M13,16C12.175,16 11.47,15.7 10.885,15.115C10.3,14.53 10,13.825 10,13C10,12.175 10.3,11.47 10.885,10.885C11.47,10.3 12.175,10 13,10C13.825,10 14.53,10.3 15.115,10.885C15.7,11.47 16,12.175 16,13C16,13.825 15.7,14.53 15.115,15.115C14.53,15.7 13.825,16 13,16Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M22,16C21.175,16 20.47,15.7 19.885,15.115C19.3,14.53 19,13.825 19,13C19,12.175 19.3,11.47 19.885,10.885C20.47,10.3 21.175,10 22,10C22.825,10 23.53,10.3 24.115,10.885C24.7,11.47 25,12.175 25,13C25,13.825 24.7,14.53 24.115,15.115C23.53,15.7 22.825,16 22,16Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M31,16C30.175,16 29.47,15.7 28.885,15.115C28.3,14.53 28,13.825 28,13C28,12.175 28.3,11.47 28.885,10.885C29.47,10.3 30.175,10 31,10C31.825,10 32.53,10.3 33.115,10.885C33.7,11.47 34,12.175 34,13C34,13.825 33.7,14.53 33.115,15.115C32.53,15.7 31.825,16 31,16Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M13,25C12.175,25 11.47,24.7 10.885,24.115C10.3,23.53 10,22.825 10,22C10,21.175 10.3,20.47 10.885,19.885C11.47,19.3 12.175,19 13,19C13.825,19 14.53,19.3 15.115,19.885C15.7,20.47 16,21.175 16,22C16,22.825 15.7,23.53 15.115,24.115C14.53,24.7 13.825,25 13,25Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M22,25C21.175,25 20.47,24.7 19.885,24.115C19.3,23.53 19,22.825 19,22C19,21.175 19.3,20.47 19.885,19.885C20.47,19.3 21.175,19 22,19C22.825,19 23.53,19.3 24.115,19.885C24.7,20.47 25,21.175 25,22C25,22.825 24.7,23.53 24.115,24.115C23.53,24.7 22.825,25 22,25Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M31,25C30.175,25 29.47,24.7 28.885,24.115C28.3,23.53 28,22.825 28,22C28,21.175 28.3,20.47 28.885,19.885C29.47,19.3 30.175,19 31,19C31.825,19 32.53,19.3 33.115,19.885C33.7,20.47 34,21.175 34,22C34,22.825 33.7,23.53 33.115,24.115C32.53,24.7 31.825,25 31,25Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M13,34C12.175,34 11.47,33.7 10.885,33.115C10.3,32.53 10,31.825 10,31C10,30.175 10.3,29.47 10.885,28.885C11.47,28.3 12.175,28 13,28C13.825,28 14.53,28.3 15.115,28.885C15.7,29.47 16,30.175 16,31C16,31.825 15.7,32.53 15.115,33.115C14.53,33.7 13.825,34 13,34Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M22,34C21.175,34 20.47,33.7 19.885,33.115C19.3,32.53 19,31.825 19,31C19,30.175 19.3,29.47 19.885,28.885C20.47,28.3 21.175,28 22,28C22.825,28 23.53,28.3 24.115,28.885C24.7,29.47 25,30.175 25,31C25,31.825 24.7,32.53 24.115,33.115C23.53,33.7 22.825,34 22,34Z"
+ android:fillColor="#40484B"/>
+ <path
+ android:pathData="M31,34C30.175,34 29.47,33.7 28.885,33.115C28.3,32.53 28,31.825 28,31C28,30.175 28.3,29.47 28.885,28.885C29.47,28.3 30.175,28 31,28C31.825,28 32.53,28.3 33.115,28.885C33.7,29.47 34,30.175 34,31C34,31.825 33.7,32.53 33.115,33.115C32.53,33.7 31.825,34 31,34Z"
+ android:fillColor="#40484B"/>
+</vector>
diff --git a/res/layout/widgets_full_sheet_paged_view.xml b/res/layout/widgets_full_sheet_paged_view.xml
index b02e3e3..455217f 100644
--- a/res/layout/widgets_full_sheet_paged_view.xml
+++ b/res/layout/widgets_full_sheet_paged_view.xml
@@ -23,19 +23,20 @@
android:clipToPadding="false"
android:layout_below="@id/collapse_handle"
android:descendantFocusability="afterDescendants"
- android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
launcher:pageIndicator="@+id/tabs" >
<com.android.launcher3.widget.picker.WidgetsRecyclerView
android:id="@+id/primary_widgets_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
android:clipToPadding="false" />
<com.android.launcher3.widget.picker.WidgetsRecyclerView
android:id="@+id/work_widgets_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
android:clipToPadding="false" />
</com.android.launcher3.widget.picker.WidgetPagedView>
@@ -47,6 +48,7 @@
android:layout_height="wrap_content"
android:layout_below="@id/collapse_handle"
android:paddingBottom="0dp"
+ android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:clipToOutline="true"
android:orientation="vertical">
@@ -57,7 +59,6 @@
android:gravity="center_horizontal"
android:textSize="24sp"
android:layout_marginTop="24dp"
- android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/widget_button_text"/>
@@ -68,7 +69,6 @@
android:elevation="0.1dp"
android:background="?android:attr/colorBackground"
android:paddingBottom="8dp"
- android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
launcher:layout_sticky="true">
<include layout="@layout/widgets_search_bar" />
</FrameLayout>
@@ -80,7 +80,6 @@
android:layout_marginTop="8dp"
android:background="@drawable/widgets_surface_background"
android:paddingVertical="@dimen/recommended_widgets_table_vertical_padding"
- android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:visibility="gone" />
<com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip
@@ -90,7 +89,6 @@
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingVertical="8dp"
- android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:background="?android:attr/colorBackground"
style="@style/TextHeadline"
launcher:layout_sticky="true">
diff --git a/res/layout/widgets_full_sheet_recyclerview.xml b/res/layout/widgets_full_sheet_recyclerview.xml
index 366d2d2..887f00c 100644
--- a/res/layout/widgets_full_sheet_recyclerview.xml
+++ b/res/layout/widgets_full_sheet_recyclerview.xml
@@ -20,7 +20,7 @@
android:layout_below="@id/collapse_handle"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
+ android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
android:clipToPadding="false" />
<!-- SearchAndRecommendationsView without the tab layout as well -->
@@ -30,7 +30,7 @@
android:layout_height="wrap_content"
android:layout_below="@id/collapse_handle"
android:paddingBottom="16dp"
- android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
+ android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:clipToOutline="true"
android:orientation="vertical">
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index ba6e547..82758bf 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -415,10 +415,6 @@
<dimen name="split_instructions_elevation">1dp</dimen>
<dimen name="split_instructions_horizontal_padding">24dp</dimen>
<dimen name="split_instructions_vertical_padding">12dp</dimen>
- <dimen name="split_instructions_bottom_margin_tablet_landscape">32dp</dimen>
- <dimen name="split_instructions_bottom_margin_tablet_portrait">44dp</dimen>
- <dimen name="split_instructions_bottom_margin_twopanels_landscape">33dp</dimen>
- <dimen name="split_instructions_bottom_margin_twopanels_portrait">51dp</dimen>
<dimen name="split_instructions_bottom_margin_phone_landscape">24dp</dimen>
<dimen name="split_instructions_bottom_margin_phone_portrait">60dp</dimen>
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 8a0c909..284ab9e 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -50,10 +50,4 @@
launcher:logIdOn="615"
launcher:logIdOff="616" />
- <androidx.preference.PreferenceScreen
- android:key="pref_developer_options"
- android:persistent="false"
- android:title="@string/developer_options_title"
- android:fragment="com.android.launcher3.settings.DeveloperOptionsFragment"/>
-
</androidx.preference.PreferenceScreen>
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 94b8cd8..bc4a5c3 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -827,6 +827,6 @@
private boolean hasSeenReconfigurableWidgetEducationTip() {
return mLauncher.getSharedPrefs()
.getBoolean(KEY_RECONFIGURABLE_WIDGET_EDUCATION_TIP_SEEN, false)
- || Utilities.IS_RUNNING_IN_TEST_HARNESS;
+ || Utilities.isRunningInTestHarness();
}
}
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 9e28608..3eb03ed 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -34,7 +34,6 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -71,6 +70,7 @@
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
+import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.views.ActivityContext;
@@ -100,17 +100,6 @@
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
- private final PointF mTranslationForReorderBounce = new PointF(0, 0);
- private final PointF mTranslationForReorderPreview = new PointF(0, 0);
-
- private float mTranslationXForTaskbarAlignmentAnimation = 0f;
- private float mTranslationYForTaskbarAlignmentAnimation = 0f;
-
- private float mTranslationXForTaskbarRevealAnimation = 0f;
- private float mTranslationYForTaskbarRevealAnimation = 0f;
-
- private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
-
private float mScaleForReorderBounce = 1f;
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
@@ -140,6 +129,7 @@
}
};
+ private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this);
private final ActivityContext mActivity;
private FastBitmapDrawable mIcon;
private boolean mCenterVertically;
@@ -958,122 +948,23 @@
mDisplay == DISPLAY_SEARCH_RESULT_SMALL;
}
- private void updateTranslation() {
- super.setTranslationX(mTranslationForReorderBounce.x
- + mTranslationForReorderPreview.x
- + mTranslationForMoveFromCenterAnimation.x
- + mTranslationXForTaskbarAlignmentAnimation
- + mTranslationXForTaskbarRevealAnimation
- );
- super.setTranslationY(mTranslationForReorderBounce.y
- + mTranslationForReorderPreview.y
- + mTranslationForMoveFromCenterAnimation.y
- + mTranslationYForTaskbarAlignmentAnimation
- + mTranslationYForTaskbarRevealAnimation);
- }
-
- public void setReorderBounceOffset(float x, float y) {
- mTranslationForReorderBounce.set(x, y);
- updateTranslation();
- }
-
- public void getReorderBounceOffset(PointF offset) {
- offset.set(mTranslationForReorderBounce);
+ @Override
+ public MultiTranslateDelegate getTranslateDelegate() {
+ return mTranslateDelegate;
}
@Override
- public void setReorderPreviewOffset(float x, float y) {
- mTranslationForReorderPreview.set(x, y);
- updateTranslation();
- }
-
- @Override
- public void getReorderPreviewOffset(PointF offset) {
- offset.set(mTranslationForReorderPreview);
- }
-
public void setReorderBounceScale(float scale) {
mScaleForReorderBounce = scale;
super.setScaleX(scale);
super.setScaleY(scale);
}
+ @Override
public float getReorderBounceScale() {
return mScaleForReorderBounce;
}
- /**
- * Sets translation values for move from center animation
- */
- public void setTranslationForMoveFromCenterAnimation(float x, float y) {
- mTranslationForMoveFromCenterAnimation.set(x, y);
- updateTranslation();
- }
-
- /**
- * Sets translationX for taskbar to launcher alignment animation
- */
- public void setTranslationXForTaskbarAlignmentAnimation(float translationX) {
- mTranslationXForTaskbarAlignmentAnimation = translationX;
- updateTranslation();
- }
-
- /**
- * Returns translationX value for taskbar to launcher alignment animation
- */
- public float getTranslationXForTaskbarAlignmentAnimation() {
- return mTranslationXForTaskbarAlignmentAnimation;
- }
-
- /**
- * Sets translationX for taskbar to launcher alignment animation
- */
- public void setTranslationYForTaskbarAlignmentAnimation(float translationY) {
- mTranslationYForTaskbarAlignmentAnimation = translationY;
- updateTranslation();
- }
-
- /**
- * Returns translationY value for taskbar to launcher alignment animation
- */
- public float getTranslationYForTaskbarAlignmentAnimation() {
- return mTranslationYForTaskbarAlignmentAnimation;
- }
-
- /**
- * Sets translationX value for taskbar reveal animation
- */
- public void setTranslationXForTaskbarRevealAnimation(float translationX) {
- mTranslationXForTaskbarRevealAnimation = translationX;
- updateTranslation();
- }
-
- /**
- * Returns translation values for taskbar reveal animation
- */
- public float getTranslationXForTaskbarRevealAnimation() {
- return mTranslationXForTaskbarRevealAnimation;
- }
-
- /**
- * Sets translationY value for taskbar reveal animation
- */
- public void setTranslationYForTaskbarRevealAnimation(float translationY) {
- mTranslationYForTaskbarRevealAnimation = translationY;
- updateTranslation();
- }
-
- /**
- * Returns translationY values for taskbar reveal animation
- */
- public float getTranslationYForTaskbarRevealAnimation() {
- return mTranslationYForTaskbarRevealAnimation;
- }
-
- public View getView() {
- return this;
- }
-
@Override
public int getViewType() {
return DRAGGABLE_ICON;
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index b96e4df..731ad74 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -22,6 +22,8 @@
import static com.android.launcher3.config.FeatureFlags.SHOW_HOME_GARDENING;
import static com.android.launcher3.dragndrop.DraggableView.DRAGGABLE_ICON;
import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_REORDER_BOUNCE_OFFSET;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_REORDER_PREVIEW_OFFSET;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -70,6 +72,7 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.CellAndSpan;
import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
@@ -1099,13 +1102,12 @@
lp.isLockedToGrid = false;
// End compute new x and y
- item.getReorderPreviewOffset(mTmpPointF);
- final float initPreviewOffsetX = mTmpPointF.x;
- final float initPreviewOffsetY = mTmpPointF.y;
+ MultiTranslateDelegate mtd = item.getTranslateDelegate();
+ float initPreviewOffsetX = mtd.getTranslationX(INDEX_REORDER_PREVIEW_OFFSET).getValue();
+ float initPreviewOffsetY = mtd.getTranslationY(INDEX_REORDER_PREVIEW_OFFSET).getValue();
final float finalPreviewOffsetX = newX - oldX;
final float finalPreviewOffsetY = newY - oldY;
-
// Exit early if we're not actually moving the view
if (finalPreviewOffsetX == 0 && finalPreviewOffsetY == 0
&& initPreviewOffsetX == 0 && initPreviewOffsetY == 0) {
@@ -1123,7 +1125,7 @@
float r = (Float) animation.getAnimatedValue();
float x = (1 - r) * initPreviewOffsetX + r * finalPreviewOffsetX;
float y = (1 - r) * initPreviewOffsetY + r * finalPreviewOffsetY;
- item.setReorderPreviewOffset(x, y);
+ item.getTranslateDelegate().setTranslation(INDEX_REORDER_PREVIEW_OFFSET, x, y);
}
});
va.addListener(new AnimatorListenerAdapter() {
@@ -1134,7 +1136,8 @@
// place just yet.
if (!cancelled) {
lp.isLockedToGrid = true;
- item.setReorderPreviewOffset(0, 0);
+ item.getTranslateDelegate()
+ .setTranslation(INDEX_REORDER_PREVIEW_OFFSET, 0, 0);
child.requestLayout();
}
if (mReorderAnimators.containsKey(lp)) {
@@ -1434,7 +1437,7 @@
CellLayoutLayoutParams lp = (CellLayoutLayoutParams) child.getLayoutParams();
if (c != null && !skip && (child instanceof Reorderable)) {
- ReorderPreviewAnimation rha = new ReorderPreviewAnimation((Reorderable) child,
+ ReorderPreviewAnimation rha = new ReorderPreviewAnimation(child,
mode, lp.getCellX(), lp.getCellY(), c.cellX, c.cellY, c.spanX, c.spanY);
rha.animate();
}
@@ -1456,8 +1459,8 @@
// Class which represents the reorder preview animations. These animations show that an item is
// in a temporary state, and hint at where the item will return to.
- class ReorderPreviewAnimation {
- final Reorderable child;
+ class ReorderPreviewAnimation<T extends View & Reorderable> {
+ final T child;
float finalDeltaX;
float finalDeltaY;
float initDeltaX;
@@ -1477,7 +1480,7 @@
float animationProgress = 0;
ValueAnimator a;
- public ReorderPreviewAnimation(Reorderable child, int mode, int cellX0, int cellY0,
+ ReorderPreviewAnimation(View childView, int mode, int cellX0, int cellY0,
int cellX1, int cellY1, int spanX, int spanY) {
regionToCenterPoint(cellX0, cellY0, spanX, spanY, mTmpPoint);
final int x0 = mTmpPoint[0];
@@ -1488,16 +1491,16 @@
final int dX = x1 - x0;
final int dY = y1 - y0;
- this.child = child;
+ this.child = (T) childView;
this.mode = mode;
finalDeltaX = 0;
finalDeltaY = 0;
- child.getReorderBounceOffset(mTmpPointF);
- initDeltaX = mTmpPointF.x;
- initDeltaY = mTmpPointF.y;
+ MultiTranslateDelegate mtd = child.getTranslateDelegate();
+ initDeltaX = mtd.getTranslationX(INDEX_REORDER_BOUNCE_OFFSET).getValue();
+ initDeltaY = mtd.getTranslationY(INDEX_REORDER_BOUNCE_OFFSET).getValue();
initScale = child.getReorderBounceScale();
- finalScale = mChildScale - (CHILD_DIVIDEND / child.getView().getWidth()) * initScale;
+ finalScale = mChildScale - (CHILD_DIVIDEND / child.getWidth()) * initScale;
int dir = mode == MODE_HINT ? -1 : 1;
if (dX == dY && dX == 0) {
@@ -1573,7 +1576,7 @@
float r1 = (mode == MODE_HINT && repeating) ? 1.0f : animationProgress;
float x = r1 * finalDeltaX + (1 - r1) * initDeltaX;
float y = r1 * finalDeltaY + (1 - r1) * initDeltaY;
- child.setReorderBounceOffset(x, y);
+ child.getTranslateDelegate().setTranslation(INDEX_REORDER_BOUNCE_OFFSET, x, y);
float s = animationProgress * finalScale + (1 - animationProgress) * initScale;
child.setReorderBounceScale(s);
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 90b2374..87ee4f6 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1417,14 +1417,7 @@
*/
public int getOverviewActionsClaimedSpaceBelow() {
if (isTaskbarPresent) {
- if (FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- return transientTaskbarSize + transientTaskbarMargin * 2;
- }
-
- return isGestureMode
- ? stashedTaskbarSize
- // Align vertically to where nav buttons are.
- : ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
+ return transientTaskbarSize + transientTaskbarMargin * 2;
}
return mInsets.bottom;
}
@@ -1597,6 +1590,8 @@
writer.println(prefix + pxToDpStr("iconTextSizePx", iconTextSizePx));
writer.println(prefix + pxToDpStr("iconDrawablePaddingPx", iconDrawablePaddingPx));
+ writer.println(prefix + "\tinv.numFolderRows: " + inv.numFolderRows);
+ writer.println(prefix + "\tinv.numFolderColumns: " + inv.numFolderColumns);
writer.println(prefix + pxToDpStr("folderCellWidthPx", folderCellWidthPx));
writer.println(prefix + pxToDpStr("folderCellHeightPx", folderCellHeightPx));
writer.println(prefix + pxToDpStr("folderChildIconSizePx", folderChildIconSizePx));
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 4ac7f07..a498323 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -59,6 +59,7 @@
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Partner;
import com.android.launcher3.util.Themes;
@@ -205,7 +206,9 @@
if (!newGridName.equals(gridName)) {
LauncherPrefs.get(context).put(GRID_NAME, newGridName);
}
- new DeviceGridState(this).writeToPrefs(context);
+ LockedUserState.get(context).runOnUserUnlocked(() -> {
+ new DeviceGridState(this).writeToPrefs(context);
+ });
DisplayController.INSTANCE.get(context).setPriorityListener(
(displayContext, info, flags) -> {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 06ea72c..22b07ef 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1647,7 +1647,7 @@
@Override
protected void onNewIntent(Intent intent) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
Log.d(TestProtocol.PERMANENT_DIAG_TAG, "Launcher.onNewIntent: " + intent);
}
Object traceToken = TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT);
@@ -1860,6 +1860,9 @@
}
private void setWorkspaceLoading(boolean value) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.FLAKY_BINDING, "running: setWorkspaceLoading=" + value);
+ }
mWorkspaceLoading = value;
}
@@ -2306,6 +2309,9 @@
*/
public void startBinding() {
Object traceToken = TraceHelper.INSTANCE.beginSection("startBinding");
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.FLAKY_BINDING, "running: startBinding");
+ }
// Floating panels (except the full widget sheet) are associated with individual icons. If
// we are starting a fresh bind, close all such panels as all the icons are about
// to go away.
@@ -2778,6 +2784,9 @@
*/
public void finishBindingItems(IntSet pagesBoundFirst) {
Object traceToken = TraceHelper.INSTANCE.beginSection("finishBindingItems");
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.FLAKY_BINDING, "running: finishBindingItems");
+ }
mWorkspace.restoreInstanceStateForRemainingPages();
setWorkspaceLoading(false);
@@ -3163,7 +3172,7 @@
// Setting the touch point to (-1, -1) will show the options popup in the center of
// the screen.
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
Log.d(TestProtocol.PERMANENT_DIAG_TAG, "Opening options popup on key up");
}
showDefaultOptions(-1, -1);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 2b98d98..c81ad01 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -44,6 +44,7 @@
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.InstallSessionTracker;
import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RunnableList;
@@ -106,25 +107,27 @@
}
mOnTerminateCallback.add(() -> mContext.unregisterReceiver(modelChangeReceiver));
- CustomWidgetManager.INSTANCE.get(mContext)
- .setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
-
SafeCloseable userChangeListener = UserCache.INSTANCE.get(mContext)
.addUserChangeListener(mModel::forceReload);
mOnTerminateCallback.add(userChangeListener::close);
- IconObserver observer = new IconObserver();
- SafeCloseable iconChangeTracker = mIconProvider.registerIconChangeListener(
- observer, MODEL_EXECUTOR.getHandler());
- mOnTerminateCallback.add(iconChangeTracker::close);
- MODEL_EXECUTOR.execute(observer::verifyIconChanged);
- LauncherPrefs.get(context).addListener(observer, THEMED_ICONS);
- mOnTerminateCallback.add(
- () -> LauncherPrefs.get(mContext).removeListener(observer, THEMED_ICONS));
+ LockedUserState.get(context).runOnUserUnlocked(() -> {
+ CustomWidgetManager.INSTANCE.get(mContext)
+ .setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
- InstallSessionTracker installSessionTracker =
- InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(mModel);
- mOnTerminateCallback.add(installSessionTracker::unregister);
+ IconObserver observer = new IconObserver();
+ SafeCloseable iconChangeTracker = mIconProvider.registerIconChangeListener(
+ observer, MODEL_EXECUTOR.getHandler());
+ mOnTerminateCallback.add(iconChangeTracker::close);
+ MODEL_EXECUTOR.execute(observer::verifyIconChanged);
+ LauncherPrefs.get(context).addListener(observer, THEMED_ICONS);
+ mOnTerminateCallback.add(
+ () -> LauncherPrefs.get(mContext).removeListener(observer, THEMED_ICONS));
+
+ InstallSessionTracker installSessionTracker =
+ InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(mModel);
+ mOnTerminateCallback.add(installSessionTracker::unregister);
+ });
// Register an observer to rebind the notification listener when dots are re-enabled.
SettingsCache settingsCache = SettingsCache.INSTANCE.get(mContext);
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index e5a1879..e675add 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -1,8 +1,25 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.launcher3
import android.content.Context
+import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
+import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY
import com.android.launcher3.LauncherFiles.SHARED_PREFERENCES_KEY
@@ -17,12 +34,37 @@
/**
* Use same context for shared preferences, so that we use a single cached instance
+ *
* TODO(b/262721340): Replace all direct SharedPreference refs with LauncherPrefs / Item methods.
*/
-class LauncherPrefs(private val context: Context) {
+class LauncherPrefs(private val encryptedContext: Context) {
+ private val deviceProtectedStorageContext =
+ encryptedContext.createDeviceProtectedStorageContext()
+
+ private val bootAwarePrefs
+ get() =
+ deviceProtectedStorageContext.getSharedPreferences(BOOT_AWARE_PREFS_KEY, MODE_PRIVATE)
+
+ private val Item.encryptedPrefs
+ get() = encryptedContext.getSharedPreferences(sharedPrefFile, MODE_PRIVATE)
+
+ // This call to `SharedPreferences` needs to be explicit rather than using `get` since doing so
+ // would result in a circular dependency between `isStartupDataMigrated` and `choosePreferences`
+ val isStartupDataMigrated: Boolean
+ get() =
+ bootAwarePrefs.getBoolean(
+ IS_STARTUP_DATA_MIGRATED.sharedPrefKey,
+ IS_STARTUP_DATA_MIGRATED.defaultValue
+ )
+
+ private fun chooseSharedPreferences(item: Item): SharedPreferences =
+ if (isBootAwareStartupDataEnabled && item.isBootAware && isStartupDataMigrated)
+ bootAwarePrefs
+ else item.encryptedPrefs
/** Wrapper around `getInner` for a `ContextualItem` */
- fun <T> get(item: ContextualItem<T>): T = getInner(item, item.defaultValueFromContext(context))
+ fun <T> get(item: ContextualItem<T>): T =
+ getInner(item, item.defaultValueFromContext(encryptedContext))
/** Wrapper around `getInner` for an `Item` */
fun <T> get(item: ConstantItem<T>): T = getInner(item, item.defaultValue)
@@ -34,7 +76,7 @@
*/
@Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
private fun <T> getInner(item: Item, default: T): T {
- val sp = context.getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE)
+ val sp = chooseSharedPreferences(item)
return when (item.type) {
String::class.java -> sp.getString(item.sharedPrefKey, default as? String)
@@ -67,16 +109,8 @@
fun put(vararg itemsToValues: Pair<Item, Any>): Unit =
prepareToPutValues(itemsToValues).forEach { it.apply() }
- /**
- * Stores the value provided in `SharedPreferences` according to the item configuration provided
- * It is asynchronous, so the caller can't assume that the value put is immediately available.
- */
- fun <T : Any> put(item: Item, value: T): Unit =
- context
- .getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE)
- .edit()
- .putValue(item, value)
- .apply()
+ /** See referenced `put` method above. */
+ fun <T : Any> put(item: Item, value: T): Unit = put(item.to(value))
/**
* Synchronously stores all the values provided according to their associated Item
@@ -86,27 +120,35 @@
prepareToPutValues(itemsToValues).forEach { it.commit() }
/**
- * Update each shared preference file with the item - value pairs provided. This method is
- * optimized to avoid retrieving the same shared preference file multiple times.
+ * Updates the values stored in `SharedPreferences` for each corresponding Item-value pair. If
+ * the item is boot aware, this method updates both the boot aware and the encrypted files. This
+ * is done because: 1) It allows for easy roll-back if the data is already in encrypted prefs
+ * and we need to turn off the boot aware data feature & 2) It simplifies Backup/Restore, which
+ * already points to encrypted storage.
*
- * @return `List<SharedPreferences.Editor>` 1 for each distinct shared preference file among the
- * items given as part of the itemsToValues parameter
+ * Returns a list of editors with all transactions added so that the caller can determine to use
+ * .apply() or .commit()
*/
private fun prepareToPutValues(
- itemsToValues: Array<out Pair<Item, Any>>
- ): List<SharedPreferences.Editor> =
- itemsToValues
- .groupBy { it.first.sharedPrefFile }
- .map { fileToItemValueList ->
- context
- .getSharedPreferences(fileToItemValueList.key, Context.MODE_PRIVATE)
- .edit()
- .apply {
- fileToItemValueList.value.forEach { itemToValue ->
- putValue(itemToValue.first, itemToValue.second)
- }
- }
+ updates: Array<out Pair<Item, Any>>
+ ): List<SharedPreferences.Editor> {
+ val updatesPerPrefFile = updates.groupBy { it.first.encryptedPrefs }.toMutableMap()
+
+ if (isBootAwareStartupDataEnabled) {
+ val bootAwareUpdates = updates.filter { it.first.isBootAware }
+ if (bootAwareUpdates.isNotEmpty()) {
+ updatesPerPrefFile[bootAwarePrefs] = bootAwareUpdates
}
+ }
+
+ return updatesPerPrefFile.map { prefToItemValueList ->
+ prefToItemValueList.key.edit().apply {
+ prefToItemValueList.value.forEach { itemToValue: Pair<Item, Any> ->
+ putValue(itemToValue.first, itemToValue.second)
+ }
+ }
+ }
+ }
/**
* Handles adding values to `SharedPreferences` regardless of type. This method is especially
@@ -116,10 +158,10 @@
@Suppress("UNCHECKED_CAST")
private fun SharedPreferences.Editor.putValue(
item: Item,
- value: Any
+ value: Any?
): SharedPreferences.Editor =
- when (value::class.java) {
- String::class.java -> putString(item.sharedPrefKey, value as String)
+ when (item.type) {
+ String::class.java -> putString(item.sharedPrefKey, value as? String)
Boolean::class.java,
java.lang.Boolean::class.java -> putBoolean(item.sharedPrefKey, value as Boolean)
Int::class.java,
@@ -128,10 +170,10 @@
java.lang.Float::class.java -> putFloat(item.sharedPrefKey, value as Float)
Long::class.java,
java.lang.Long::class.java -> putLong(item.sharedPrefKey, value as Long)
- Set::class.java -> putStringSet(item.sharedPrefKey, value as Set<String>)
+ Set::class.java -> putStringSet(item.sharedPrefKey, value as? Set<String>)
else ->
throw IllegalArgumentException(
- "item type: ${value::class} is not compatible with sharedPref methods"
+ "item type: ${item.type} is not compatible with sharedPref methods"
)
}
@@ -142,13 +184,9 @@
*/
fun addListener(listener: OnSharedPreferenceChangeListener, vararg items: Item) {
items
- .map { it.sharedPrefFile }
+ .map { chooseSharedPreferences(it) }
.distinct()
- .forEach {
- context
- .getSharedPreferences(it, Context.MODE_PRIVATE)
- .registerOnSharedPreferenceChangeListener(listener)
- }
+ .forEach { it.registerOnSharedPreferenceChangeListener(listener) }
}
/**
@@ -158,13 +196,9 @@
fun removeListener(listener: OnSharedPreferenceChangeListener, vararg items: Item) {
// If a listener is not registered to a SharedPreference, unregistering it does nothing
items
- .map { it.sharedPrefFile }
+ .map { chooseSharedPreferences(it) }
.distinct()
- .forEach {
- context
- .getSharedPreferences(it, Context.MODE_PRIVATE)
- .unregisterOnSharedPreferenceChangeListener(listener)
- }
+ .forEach { it.unregisterOnSharedPreferenceChangeListener(listener) }
}
/**
@@ -173,10 +207,8 @@
*/
fun has(vararg items: Item): Boolean {
items
- .groupBy { it.sharedPrefFile }
- .forEach { (file, itemsSublist) ->
- val prefs: SharedPreferences =
- context.getSharedPreferences(file, Context.MODE_PRIVATE)
+ .groupBy { chooseSharedPreferences(it) }
+ .forEach { (prefs, itemsSublist) ->
if (!itemsSublist.none { !prefs.contains(it.sharedPrefKey) }) return false
}
return true
@@ -191,62 +223,128 @@
fun removeSync(vararg items: Item) = prepareToRemove(items).forEach { it.commit() }
/**
- * Creates `SharedPreferences.Editor` transactions for removing all the provided [Item] values
- * from their respective `SharedPreferences` files. These returned `Editors` can then be
- * committed or applied for synchronous or async behavior.
+ * Removes the key value pairs stored in `SharedPreferences` for each corresponding Item. If the
+ * item is boot aware, this method removes the data from both the boot aware and encrypted
+ * files.
+ *
+ * @return a list of editors with all transactions added so that the caller can determine to use
+ * .apply() or .commit()
*/
- private fun prepareToRemove(items: Array<out Item>): List<SharedPreferences.Editor> =
- items
- .groupBy { it.sharedPrefFile }
- .map { (file, items) ->
- context.getSharedPreferences(file, Context.MODE_PRIVATE).edit().also { editor ->
- items.forEach { item -> editor.remove(item.sharedPrefKey) }
- }
+ private fun prepareToRemove(items: Array<out Item>): List<SharedPreferences.Editor> {
+ val itemsPerFile = items.groupBy { it.encryptedPrefs }.toMutableMap()
+
+ if (isBootAwareStartupDataEnabled) {
+ val bootAwareUpdates = items.filter { it.isBootAware }
+ if (bootAwareUpdates.isNotEmpty()) {
+ itemsPerFile[bootAwarePrefs] = bootAwareUpdates
}
+ }
+
+ return itemsPerFile.map { (prefs, items) ->
+ prefs.edit().also { editor ->
+ items.forEach { item -> editor.remove(item.sharedPrefKey) }
+ }
+ }
+ }
+
+ fun migrateStartupDataToDeviceProtectedStorage() {
+ if (!isBootAwareStartupDataEnabled) return
+
+ Log.d(
+ TAG,
+ "Migrating data to unencrypted shared preferences to enable preloading " +
+ "while the user is locked the next time the device reboots."
+ )
+
+ with(bootAwarePrefs.edit()) {
+ BOOT_AWARE_ITEMS.forEach { putValue(it, get(it)) }
+ putBoolean(IS_STARTUP_DATA_MIGRATED.sharedPrefKey, true)
+ apply()
+ }
+ }
companion object {
+ private const val TAG = "LauncherPrefs"
+ @VisibleForTesting const val BOOT_AWARE_PREFS_KEY = "boot_aware_prefs"
+
@JvmField var INSTANCE = MainThreadInitializedObject { LauncherPrefs(it) }
@JvmStatic fun get(context: Context): LauncherPrefs = INSTANCE.get(context)
- @JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "")
- @JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false)
+ @JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "", true)
+ @JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, true)
@JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "")
@JvmField val WORK_EDU_STEP = backedUpItem(WorkProfileManager.KEY_WORK_EDU_STEP, 0)
- @JvmField val WORKSPACE_SIZE = backedUpItem(DeviceGridState.KEY_WORKSPACE_SIZE, "")
- @JvmField val HOTSEAT_COUNT = backedUpItem(DeviceGridState.KEY_HOTSEAT_COUNT, -1)
+ @JvmField val WORKSPACE_SIZE = backedUpItem(DeviceGridState.KEY_WORKSPACE_SIZE, "", true)
+ @JvmField val HOTSEAT_COUNT = backedUpItem(DeviceGridState.KEY_HOTSEAT_COUNT, -1, true)
@JvmField
val DEVICE_TYPE =
- backedUpItem(DeviceGridState.KEY_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE)
- @JvmField val DB_FILE = backedUpItem(DeviceGridState.KEY_DB_FILE, "")
+ backedUpItem(DeviceGridState.KEY_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE, true)
+ @JvmField val DB_FILE = backedUpItem(DeviceGridState.KEY_DB_FILE, "", true)
@JvmField
val RESTORE_DEVICE =
- backedUpItem(RestoreDbTask.RESTORED_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE)
+ backedUpItem(
+ RestoreDbTask.RESTORED_DEVICE_TYPE,
+ InvariantDeviceProfile.TYPE_PHONE,
+ true
+ )
@JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "")
@JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "")
- @JvmField val GRID_NAME = ConstantItem("idp_grid_name", true, null, String::class.java)
+ @JvmField
+ val GRID_NAME =
+ ConstantItem(
+ "idp_grid_name",
+ isBackedUp = true,
+ defaultValue = null,
+ isBootAware = true,
+ type = String::class.java
+ )
@JvmField
val ALLOW_ROTATION =
backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) {
RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info)
}
+ @JvmField
+ val IS_STARTUP_DATA_MIGRATED =
+ ConstantItem(
+ "is_startup_data_boot_aware",
+ isBackedUp = false,
+ defaultValue = false,
+ isBootAware = true
+ )
@VisibleForTesting
@JvmStatic
- fun <T> backedUpItem(sharedPrefKey: String, defaultValue: T): ConstantItem<T> =
- ConstantItem(sharedPrefKey, true, defaultValue)
+ fun <T> backedUpItem(
+ sharedPrefKey: String,
+ defaultValue: T,
+ isBootAware: Boolean = false
+ ): ConstantItem<T> =
+ ConstantItem(sharedPrefKey, isBackedUp = true, defaultValue, isBootAware)
@JvmStatic
fun <T> backedUpItem(
sharedPrefKey: String,
type: Class<out T>,
+ isBootAware: Boolean = false,
defaultValueFromContext: (c: Context) -> T
- ): ContextualItem<T> = ContextualItem(sharedPrefKey, true, defaultValueFromContext, type)
+ ): ContextualItem<T> =
+ ContextualItem(
+ sharedPrefKey,
+ isBackedUp = true,
+ defaultValueFromContext,
+ isBootAware,
+ type
+ )
@VisibleForTesting
@JvmStatic
- fun <T> nonRestorableItem(sharedPrefKey: String, defaultValue: T): ConstantItem<T> =
- ConstantItem(sharedPrefKey, false, defaultValue)
+ fun <T> nonRestorableItem(
+ sharedPrefKey: String,
+ defaultValue: T,
+ isBootAware: Boolean = false
+ ): ConstantItem<T> =
+ ConstantItem(sharedPrefKey, isBackedUp = false, defaultValue, isBootAware)
@Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.")
@JvmStatic
@@ -254,7 +352,7 @@
// Use application context for shared preferences, so we use single cached instance
return context.applicationContext.getSharedPreferences(
SHARED_PREFERENCES_KEY,
- Context.MODE_PRIVATE
+ MODE_PRIVATE
)
}
@@ -264,16 +362,23 @@
// Use application context for shared preferences, so we use a single cached instance
return context.applicationContext.getSharedPreferences(
DEVICE_PREFERENCES_KEY,
- Context.MODE_PRIVATE
+ MODE_PRIVATE
)
}
}
}
+// This is hard-coded to false for now until it is time to release this optimization. It is only
+// a var because the unit tests are setting this to true so they can run.
+@VisibleForTesting var isBootAwareStartupDataEnabled: Boolean = false
+
+private val BOOT_AWARE_ITEMS: MutableSet<ConstantItem<*>> = mutableSetOf()
+
abstract class Item {
abstract val sharedPrefKey: String
abstract val isBackedUp: Boolean
abstract val type: Class<*>
+ abstract val isBootAware: Boolean
val sharedPrefFile: String
get() = if (isBackedUp) SHARED_PREFERENCES_KEY else DEVICE_PREFERENCES_KEY
@@ -284,14 +389,22 @@
override val sharedPrefKey: String,
override val isBackedUp: Boolean,
val defaultValue: T,
+ override val isBootAware: Boolean,
// The default value can be null. If so, the type needs to be explicitly stated, or else NPE
override val type: Class<out T> = defaultValue!!::class.java
-) : Item()
+) : Item() {
+ init {
+ if (isBootAware && isBootAwareStartupDataEnabled) {
+ BOOT_AWARE_ITEMS.add(this)
+ }
+ }
+}
data class ContextualItem<T>(
override val sharedPrefKey: String,
override val isBackedUp: Boolean,
private val defaultSupplier: (c: Context) -> T,
+ override val isBootAware: Boolean,
override val type: Class<out T>
) : Item() {
private var default: T? = null
diff --git a/src/com/android/launcher3/MainProcessInitializer.java b/src/com/android/launcher3/MainProcessInitializer.java
index f2a3de7..3d7e11e 100644
--- a/src/com/android/launcher3/MainProcessInitializer.java
+++ b/src/com/android/launcher3/MainProcessInitializer.java
@@ -18,7 +18,6 @@
import android.content.Context;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.BitmapCreationCheck;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.logging.FileLog;
@@ -37,7 +36,6 @@
protected void init(Context context) {
FileLog.setDir(context.getApplicationContext().getFilesDir());
- FeatureFlags.initialize(context);
IconShape.init(context);
if (BitmapCreationCheck.ENABLED) {
diff --git a/src/com/android/launcher3/MultipageCellLayout.java b/src/com/android/launcher3/MultipageCellLayout.java
index 0d59848..6a518a7 100644
--- a/src/com/android/launcher3/MultipageCellLayout.java
+++ b/src/com/android/launcher3/MultipageCellLayout.java
@@ -70,7 +70,7 @@
boolean createAreaForResize(int cellX, int cellY, int spanX, int spanY, View dragView,
int[] direction, boolean commit) {
// Add seam to x position
- if (cellX > mCountX / 2) {
+ if (cellX >= mCountX / 2) {
cellX++;
}
int finalCellX = cellX;
@@ -109,7 +109,7 @@
lp.canReorder = false;
mCountX++;
mShortcutsAndWidgets.addViewInLayout(mSeam, lp);
- mOccupied = createGridOccupancy();
+ mOccupied = createGridOccupancyWithSeam(mOccupied);
mTmpOccupied = new GridOccupancy(mCountX, mCountY);
}
@@ -139,14 +139,19 @@
return solution;
}
- GridOccupancy createGridOccupancy() {
- GridOccupancy grid = new GridOccupancy(mCountX, mCountY);
- for (int i = 0; i < mShortcutsAndWidgets.getChildCount(); i++) {
- View view = mShortcutsAndWidgets.getChildAt(i);
- CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams();
- int seamOffset = lp.getCellX() >= mCountX / 2 && lp.canReorder ? 1 : 0;
- grid.markCells(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, lp.cellVSpan,
- true);
+
+
+ GridOccupancy createGridOccupancyWithSeam(GridOccupancy gridOccupancy) {
+ GridOccupancy grid = new GridOccupancy(getCountX(), getCountY());
+ for (int x = 0; x < getCountX(); x++) {
+ for (int y = 0; y < getCountY(); y++) {
+ int offset = x >= getCountX() / 2 ? 1 : 0;
+ if (x == getCountX() / 2) {
+ grid.cells[x][y] = true;
+ } else {
+ grid.cells[x][y] = gridOccupancy.cells[x - offset][y];
+ }
+ }
}
return grid;
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index c3d8a53..c7431ed 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -773,7 +773,7 @@
if (mScroller.isFinished() && pageScrollChanged) {
// TODO(b/246283207): Remove logging once root cause of flake detected.
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS && !(this instanceof Workspace)) {
+ if (Utilities.isRunningInTestHarness() && !(this instanceof Workspace)) {
Log.d("b/246283207", this.getClass().getSimpleName() + "#onLayout() -> "
+ "if(mScroller.isFinished() && pageScrollChanged) -> getNextPage(): "
+ getNextPage() + ", getScrollForPage(getNextPage()): "
@@ -1713,7 +1713,7 @@
return false;
}
- if (FeatureFlags.IS_STUDIO_BUILD && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (FeatureFlags.IS_STUDIO_BUILD && !Utilities.isRunningInTestHarness()) {
duration *= Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.WINDOW_ANIMATION_SCALE, 1);
}
diff --git a/src/com/android/launcher3/Reorderable.java b/src/com/android/launcher3/Reorderable.java
index 047fb01..5afd95d 100644
--- a/src/com/android/launcher3/Reorderable.java
+++ b/src/com/android/launcher3/Reorderable.java
@@ -16,33 +16,19 @@
package com.android.launcher3;
-import android.graphics.PointF;
-import android.view.View;
+import com.android.launcher3.util.MultiTranslateDelegate;
public interface Reorderable {
/**
- * Set the offset related to reorder hint and bounce animations
+ * Returns the delegate to control translation
*/
- void setReorderBounceOffset(float x, float y);
-
- void getReorderBounceOffset(PointF offset);
-
- /**
- * Set the offset related to previewing the new reordered position
- */
- void setReorderPreviewOffset(float x, float y);
-
- void getReorderPreviewOffset(PointF offset);
+ MultiTranslateDelegate getTranslateDelegate();
/**
* Set the scale related to reorder hint and "bounce" animations
*/
void setReorderBounceScale(float scale);
- float getReorderBounceScale();
- /**
- * Get the com.android.view related to this object
- */
- View getView();
+ float getReorderBounceScale();
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 55b745b..b00199f 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -21,6 +21,7 @@
import static com.android.launcher3.CellLayout.FOLDER;
import static com.android.launcher3.CellLayout.HOTSEAT;
import static com.android.launcher3.CellLayout.WORKSPACE;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_WIDGET_CENTERING;
import android.app.WallpaperManager;
import android.content.Context;
@@ -208,7 +209,8 @@
float scaleY = appWidgetScale.y;
nahv.setScaleToFit(Math.min(scaleX, scaleY));
- nahv.setTranslationForCentering(-(lp.width - (lp.width * scaleX)) / 2.0f,
+ nahv.getTranslateDelegate().setTranslation(INDEX_WIDGET_CENTERING,
+ -(lp.width - (lp.width * scaleX)) / 2.0f,
-(lp.height - (lp.height * scaleY)) / 2.0f);
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 67bc7fc..59327dc 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -131,10 +131,10 @@
/**
* Indicates if the device has a debug build. Should only be used to store additional info or
* add extra logging and not for changing the app behavior.
+ * @deprecated Use {@link BuildConfig#IS_DEBUG_DEVICE} directly
*/
- public static final boolean IS_DEBUG_DEVICE =
- Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") ||
- Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
+ @Deprecated
+ public static final boolean IS_DEBUG_DEVICE = BuildConfig.IS_DEBUG_DEVICE;
/**
* Returns true if theme is dark.
@@ -150,11 +150,14 @@
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
}
- public static boolean IS_RUNNING_IN_TEST_HARNESS =
- ActivityManager.isRunningInTestHarness();
+ private static boolean sIsRunningInTestHarness = ActivityManager.isRunningInTestHarness();
+
+ public static boolean isRunningInTestHarness() {
+ return sIsRunningInTestHarness;
+ }
public static void enableRunningInTestHarnessForTests() {
- IS_RUNNING_IN_TEST_HARNESS = true;
+ sIsRunningInTestHarness = true;
}
public static boolean isPropertyEnabled(String propertyName) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 4430a94..54bf6a8 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -406,6 +406,8 @@
Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
setter.setFloat(getAppsViewProgressAlpha(), MultiPropertyFactory.MULTI_PROPERTY_VALUE,
hasAllAppsContent ? 1 : 0, allAppsFade);
+ setter.setFloat(getAppsViewPullbackAlpha(), MultiPropertyFactory.MULTI_PROPERTY_VALUE,
+ hasAllAppsContent ? 1 : 0, allAppsFade);
boolean shouldProtectHeader =
ALL_APPS == state || mLauncher.getStateManager().getState() == ALL_APPS;
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index 0188a47..df22425 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -127,7 +127,7 @@
|| onboardingPrefs.getBoolean(OnboardingPrefs.HOME_BOUNCE_SEEN)
|| AbstractFloatingView.getTopOpenView(launcher) != null
|| launcher.getSystemService(UserManager.class).isDemoUser()
- || Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ || Utilities.isRunningInTestHarness()) {
return;
}
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 770e931..24cc0ac 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -127,7 +127,7 @@
*/
private static AccessibilityManager getAccessibilityManagerForTest(Context context) {
// If not running in a test harness, don't participate in test exchanges.
- if (!Utilities.IS_RUNNING_IN_TEST_HARNESS) return null;
+ if (!Utilities.isRunningInTestHarness()) return null;
final AccessibilityManager accessibilityManager = getManager(context);
if (!accessibilityManager.isEnabled()) return null;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index a5b19a9..98b61d1 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -16,16 +16,18 @@
package com.android.launcher3.config;
+import static com.android.launcher3.uioverrides.flags.FlagsFactory.getDebugFlag;
+import static com.android.launcher3.uioverrides.flags.FlagsFactory.getReleaseFlag;
+
import android.content.Context;
-import android.content.SharedPreferences;
+
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BuildConfig;
import com.android.launcher3.Utilities;
-import com.android.launcher3.uioverrides.DeviceFlag;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
/**
* Defines a set of flags used to control various launcher behaviors.
@@ -34,26 +36,32 @@
*/
public final class FeatureFlags {
- private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
-
public static final String FLAGS_PREF_NAME = "featureFlags";
- private FeatureFlags() {
- }
+ @VisibleForTesting
+ public static Predicate<BooleanFlag> sBooleanReader = f -> f.mCurrentValue;
+ @VisibleForTesting
+ public static ToIntFunction<IntFlag> sIntReader = f -> f.mCurrentValue;
+
+ private FeatureFlags() { }
public static boolean showFlagTogglerUi(Context context) {
- return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
+ return BuildConfig.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
}
/**
* True when the build has come from Android Studio and is being used for local debugging.
+ * @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly
*/
- public static final boolean IS_STUDIO_BUILD = BuildConfig.DEBUG;
+ @Deprecated
+ public static final boolean IS_STUDIO_BUILD = BuildConfig.IS_STUDIO_BUILD;
/**
* Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature
* and should be modified at a project level.
+ * @deprecated Use {@link BuildConfig#QSB_ON_FIRST_SCREEN} directly
*/
+ @Deprecated
public static final boolean QSB_ON_FIRST_SCREEN = BuildConfig.QSB_ON_FIRST_SCREEN;
/**
@@ -65,88 +73,88 @@
* Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"),
* and set a default value for the flag. This will be the default value on Debug builds.
*/
- public static final BooleanFlag ENABLE_INPUT_CONSUMER_REASON_LOGGING = getDebugFlag(
+ public static final BooleanFlag ENABLE_INPUT_CONSUMER_REASON_LOGGING = getDebugFlag(270390028,
"ENABLE_INPUT_CONSUMER_REASON_LOGGING",
true,
"Log the reason why an Input Consumer was selected for a gesture.");
- public static final BooleanFlag ENABLE_GESTURE_ERROR_DETECTION = getDebugFlag(
+ public static final BooleanFlag ENABLE_GESTURE_ERROR_DETECTION = getDebugFlag(270389990,
"ENABLE_GESTURE_ERROR_DETECTION",
true,
"Analyze gesture events and log detected errors");
// When enabled the promise icon is visible in all apps while installation an app.
- public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(
+ public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012,
"PROMISE_APPS_IN_ALL_APPS", false, "Add promise icon in all-apps");
- public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
+ public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904,
"KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
- public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag(
+ public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907,
"ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR =
- getDebugFlag("ENABLE_FLOATING_SEARCH_BAR", false,
+ getDebugFlag(270390286, "ENABLE_FLOATING_SEARCH_BAR", false,
"Keep All Apps search bar at the bottom (but above keyboard if open)");
- public static final BooleanFlag ENABLE_HIDE_HEADER = new DeviceFlag("ENABLE_HIDE_HEADER",
- true, "Hide header on keyboard before typing in all apps");
+ public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930,
+ "ENABLE_HIDE_HEADER", true, "Hide header on keyboard before typing in all apps");
- public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = new DeviceFlag(
+ public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getReleaseFlag(270390779,
"ENABLE_EXPANDING_PAUSE_WORK_BUTTON", false,
"Expand and collapse pause work button while scrolling");
- public static final BooleanFlag ENABLE_RECENT_BLOCK = getDebugFlag("ENABLE_RECENT_BLOCK",
- false, "Show recently tapped search target block in zero state");
+ public static final BooleanFlag ENABLE_RECENT_BLOCK = getDebugFlag(270390950,
+ "ENABLE_RECENT_BLOCK", false, "Show recently tapped search target block in zero state");
- public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
+ public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455,
"COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
- public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(
+ public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937,
"ENABLE_TWOLINE_ALLAPPS", false, "Enables two line label inside all apps.");
- public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = new DeviceFlag(
- "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", false,
+ public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag(
+ 270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", false,
"Allows on device search in all apps logging");
- public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(
+ public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693,
"IME_STICKY_SNACKBAR_EDU", true, "Show sticky IME edu in AllApps");
- public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(
+ public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653,
"ENABLE_PEOPLE_TILE_PREVIEW", false,
"Experimental: Shows conversation shortcuts on home screen as search results");
- public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(
+ public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638,
"FOLDER_NAME_MAJORITY_RANKING", true,
"Suggests folder names based on majority based ranking.");
- public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = new DeviceFlag(
- "INJECT_FALLBACK_APP_CORPUS_RESULTS", false, "Inject "
- + "fallback app corpus result when AiAi fails to return it.");
+ public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706,
+ "INJECT_FALLBACK_APP_CORPUS_RESULTS", false,
+ "Inject fallback app corpus result when AiAi fails to return it.");
- public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(
+ public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(270391641,
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
- public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(
+ public static final BooleanFlag ENABLE_BULK_WORKSPACE_ICON_LOADING = getDebugFlag(270392203,
"ENABLE_BULK_WORKSPACE_ICON_LOADING",
true,
"Enable loading workspace icons in bulk.");
- public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(
+ public static final BooleanFlag ENABLE_BULK_ALL_APPS_ICON_LOADING = getDebugFlag(270392465,
"ENABLE_BULK_ALL_APPS_ICON_LOADING",
true,
"Enable loading all apps icons in bulk.");
- public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
+ public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(270392706,
"ENABLE_DATABASE_RESTORE", false,
"Enable database restore when new restore session is created");
- public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(
+ public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(270391664,
"ENABLE_SMARTSPACE_DISMISS", true,
"Adds a menu option to dismiss the current Enhanced Smartspace card.");
- public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(
+ public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(270392629,
"ENABLE_OVERLAY_CONNECTION_OPTIM",
false,
"Enable optimizing overlay service connection");
@@ -154,341 +162,256 @@
/**
* Enables region sampling for text color: Needs system health assessment before turning on
*/
- public static final BooleanFlag ENABLE_REGION_SAMPLING = getDebugFlag(
+ public static final BooleanFlag ENABLE_REGION_SAMPLING = getDebugFlag(270391669,
"ENABLE_REGION_SAMPLING", false,
"Enable region sampling to determine color of text on screen.");
public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS =
- getDebugFlag(
+ getDebugFlag(270393096,
"ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", false,
"Always use hardware optimization for folder animations.");
- public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(
+ public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(270392980,
"SEPARATE_RECENTS_ACTIVITY", false,
"Uses a separate recents activity instead of using the integrated recents+Launcher UI");
- public static final BooleanFlag ENABLE_MINIMAL_DEVICE = getDebugFlag(
+ public static final BooleanFlag ENABLE_MINIMAL_DEVICE = getDebugFlag(270392984,
"ENABLE_MINIMAL_DEVICE", false,
"Allow user to toggle minimal device mode in launcher.");
public static final BooleanFlag ENABLE_TASKBAR_POPUP_MENU = getDebugFlag(
- "ENABLE_TASKBAR_POPUP_MENU", true, "Enables long pressing taskbar icons to show the"
- + " popup menu.");
+ 270392477, "ENABLE_TASKBAR_POPUP_MENU", true,
+ "Enables long pressing taskbar icons to show the popup menu.");
- public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(
+ public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(270392643,
"ENABLE_TWO_PANEL_HOME", true,
"Uses two panel on home screen. Only applicable on large screen devices.");
- public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(
+ public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276,
"ENABLE_SCRIM_FOR_APP_LAUNCH", false,
"Enables scrim during app launch animation.");
- public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = new DeviceFlag(
+ public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = getReleaseFlag(270393258,
"ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets");
- public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false,
+ public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(
+ 270393108, "NOTIFY_CRASHES", false,
"Sends a notification whenever launcher encounters an uncaught exception.");
- public static final BooleanFlag ENABLE_WALLPAPER_SCRIM = getDebugFlag(
+ public static final BooleanFlag ENABLE_WALLPAPER_SCRIM = getDebugFlag(270393604,
"ENABLE_WALLPAPER_SCRIM", false,
"Enables scrim over wallpaper for text protection.");
- public static final BooleanFlag WIDGETS_IN_LAUNCHER_PREVIEW = getDebugFlag(
+ public static final BooleanFlag WIDGETS_IN_LAUNCHER_PREVIEW = getDebugFlag(270393268,
"WIDGETS_IN_LAUNCHER_PREVIEW", true,
"Enables widgets in Launcher preview for the Wallpaper app.");
- public static final BooleanFlag QUICK_WALLPAPER_PICKER = getDebugFlag(
+ public static final BooleanFlag QUICK_WALLPAPER_PICKER = getDebugFlag(270393112,
"QUICK_WALLPAPER_PICKER", true,
"Shows quick wallpaper picker in long-press menu");
- public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(
+ public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426,
"ENABLE_BACK_SWIPE_HOME_ANIMATION", true,
"Enables home animation to icon when user swipes back.");
- public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(
+ public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(270393294,
"ENABLE_ICON_LABEL_AUTO_SCALING", true,
"Enables scaling/spacing for icon labels to make more characters visible");
- public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(
+ public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897,
"ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", false,
"Enables displaying the all apps button in the hotseat.");
- public static final BooleanFlag ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR = getDebugFlag(
+ public static final BooleanFlag ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR = getDebugFlag(270393900,
"ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR", false,
"Enables One Search box in Taskbar All Apps.");
- public static final BooleanFlag ENABLE_TASKBAR_IN_OVERVIEW = getDebugFlag(
- "ENABLE_TASKBAR_IN_OVERVIEW", true,
- "Enables accessing the system Taskbar in overview.");
-
- public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(
+ public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906,
"ENABLE_SPLIT_FROM_WORKSPACE", true,
"Enable initiating split screen from workspace.");
public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS =
- getDebugFlag("ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", false,
+ getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", false,
"Enable splitting from fullscreen app with keyboard shortcuts");
public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag(
- "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", false,
+ 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", false,
"Enable initiating split screen from workspace to workspace.");
- public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(
+ public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455,
"ENABLE_NEW_MIGRATION_LOGIC", true,
"Enable the new grid migration logic, keeping pages when src < dest");
- public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(
+ public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(270394384,
"ENABLE_WIDGET_HOST_IN_BACKGROUND", false,
"Enable background widget updates listening for widget holder");
- public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
+ public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = getReleaseFlag(270394223,
"ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
- public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = new DeviceFlag(
- "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", false,
+ public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
+ 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", false,
"Enable option to replace decorator-based search result backgrounds with drawables");
- public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = new DeviceFlag(
- "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
+ public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
+ 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
"Enable option to launch search results using the new view container transitions");
- public static final BooleanFlag TWO_PREDICTED_ROWS_ALL_APPS_SEARCH = new DeviceFlag(
- "TWO_PREDICTED_ROWS_ALL_APPS_SEARCH", false,
- "Use 2 rows of app predictions in All Apps search zero-state");
-
- public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = new DeviceFlag(
- "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", true,
+ public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag(
+ 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", true,
"Enable option to show keyboard when going to all-apps");
- public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(
+ public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(270394973,
"USE_LOCAL_ICON_OVERRIDES", true,
"Use inbuilt monochrome icons if app doesn't provide one");
- public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(
+ public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476,
"ENABLE_DISMISS_PREDICTION_UNDO", false,
"Show an 'Undo' snackbar when users dismiss a predicted hotseat item");
- public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(
+ public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(270395008,
"ENABLE_CACHED_WIDGET", true,
"Show previously cached widgets as opposed to deferred widget where available");
- public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(
+ public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(270395010,
"USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", false,
"Use local overrides for search request timeout");
- public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(
+ public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171,
"CONTINUOUS_VIEW_TREE_CAPTURE", false, "Capture View tree every frame");
- public static final BooleanFlag FOLDABLE_WORKSPACE_REORDER = getDebugFlag(
+ public static final BooleanFlag FOLDABLE_WORKSPACE_REORDER = getDebugFlag(270395070,
"FOLDABLE_WORKSPACE_REORDER", true,
"In foldables, when reordering the icons and widgets, is now going to use both sides");
- public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(
+ public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073,
"ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", false,
"Allow bottom sheet depth to be smaller than 1 for multi-display devices.");
- public static final BooleanFlag SCROLL_TOP_TO_RESET = new DeviceFlag(
- "SCROLL_TOP_TO_RESET", true, "Bring up IME and focus on "
- + "input when scroll to top if 'Always show keyboard' is enabled or in prefix state");
+ public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(
+ 270395177, "SCROLL_TOP_TO_RESET", true,
+ "Bring up IME and focus on input when scroll to top if 'Always show keyboard'"
+ + " is enabled or in prefix state");
- public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(
+ public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516,
"ENABLE_MATERIAL_U_POPUP", false, "Switch popup UX to use material U");
- public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = new DeviceFlag(
+ public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269,
"ENABLE_SEARCH_UNINSTALLED_APPS", false, "Search uninstalled app results.");
- public static final BooleanFlag SHOW_HOME_GARDENING = getDebugFlag(
+ public static final BooleanFlag SHOW_HOME_GARDENING = getDebugFlag(270395183,
"SHOW_HOME_GARDENING", false,
"Show the new home gardening mode");
- public static final BooleanFlag HOME_GARDENING_WORKSPACE_BUTTONS = getDebugFlag(
+ public static final BooleanFlag HOME_GARDENING_WORKSPACE_BUTTONS = getDebugFlag(270395133,
"HOME_GARDENING_WORKSPACE_BUTTONS", false,
"Change workspace edit buttons to reflect home gardening");
- public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = new DeviceFlag(
+ public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134,
"ENABLE_DOWNLOAD_APP_UX_V2", true, "Updates the download app UX"
+ " to have better visuals");
- public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(
+ public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186,
"ENABLE_DOWNLOAD_APP_UX_V3", false, "Updates the download app UX"
- + " to have better visuals, improve contrast, and color");
+ + " to have better visuals, improve contrast, and color");
- public static final BooleanFlag FORCE_PERSISTENT_TASKBAR = getDebugFlag(
+ public static final BooleanFlag FORCE_PERSISTENT_TASKBAR = getDebugFlag(270395077,
"FORCE_PERSISTENT_TASKBAR", false, "Forces taskbar to be persistent, even in gesture"
+ " nav mode and when transient taskbar is enabled.");
- public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(
+ public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274,
"FOLDABLE_SINGLE_PAGE", false,
"Use a single page for the workspace");
- public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(
+ public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798,
"ENABLE_TRANSIENT_TASKBAR", true, "Enables transient taskbar.");
- public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(
+ public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140,
"SECONDARY_DRAG_N_DROP_TO_PIN", false,
"Enable dragging and dropping to pin apps within secondary display");
- public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(
+ public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143,
"ENABLE_ICON_IN_TEXT_HEADER", false, "Show icon in textheader");
- public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(
+ public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087,
"ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", false, "Show app icon for inline shortcut");
- public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(
+ public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278,
"SHOW_DOT_PAGINATION", false, "Enable showing dot pagination in workspace");
- public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(
+ public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809,
"LARGE_SCREEN_WIDGET_PICKER", false, "Enable new widget picker that takes "
+ "advantage of large screen format");
- public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(
+ public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(270396257,
"ENABLE_NEW_GESTURE_NAV_TUTORIAL", false,
"Enable the redesigned gesture navigation tutorial");
- public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(
+ public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(270395567,
"ENABLE_LAUNCH_FROM_STAGED_APP", true,
"Enable the ability to tap a staged app during split select to launch it in full screen"
);
- public static final BooleanFlag ENABLE_HAPTICS_ALL_APPS = getDebugFlag(
+
+ public static final BooleanFlag ENABLE_HAPTICS_ALL_APPS = getDebugFlag(270396358,
"ENABLE_HAPTICS_ALL_APPS", false, "Enables haptics opening/closing All apps");
- public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(
+ public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209,
"ENABLE_FORCED_MONO_ICON", false,
"Enable the ability to generate monochromatic icons, if it is not provided by the app"
);
- public static final BooleanFlag ENABLE_DREAM_TRANSITION = getDebugFlag(
- "ENABLE_DREAM_TRANSITION", true,
- "Enable the launcher transition when the device enters a dream");
-
- public static final BooleanFlag ENABLE_TASKBAR_EDU_TOOLTIP = getDebugFlag(
+ public static final BooleanFlag ENABLE_TASKBAR_EDU_TOOLTIP = getDebugFlag(270396268,
"ENABLE_TASKBAR_EDU_TOOLTIP", true,
"Enable the tooltip version of the Taskbar education flow.");
- public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(
+ public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680,
"ENABLE_MULTI_INSTANCE", false,
"Enables creation and filtering of multiple task instances in overview");
- public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(
+ public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583,
"ENABLE_TASKBAR_PINNING", false,
"Enables taskbar pinning to allow user to switch between transient and persistent "
+ "taskbar flavors");
- public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(
+ public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
"ENABLE_GRID_ONLY_OVERVIEW", false,
"Enable a grid-only overview without a focused task.");
- public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(
+ public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209,
"RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", true,
"Enables receiving unfold animation events from sysui instead of calculating "
+ "them in launcher process using hinge sensor values.");
- public static final BooleanFlag ENABLE_KEYBOARD_QUICK_SWITCH = getDebugFlag(
+ public static final BooleanFlag ENABLE_KEYBOARD_QUICK_SWITCH = getDebugFlag(270396844,
"ENABLE_KEYBOARD_QUICK_SWITCH", false,
"Enables keyboard quick switching");
- public static void initialize(Context context) {
- synchronized (sDebugFlags) {
- for (DebugFlag flag : sDebugFlags) {
- flag.initialize(context);
- }
-
- sDebugFlags.sort((f1, f2) -> {
- // Sort first by any prefs that the user has changed, then alphabetically.
- int changeComparison = Boolean.compare(f2.mHasBeenChangedAtLeastOnce,
- f1.mHasBeenChangedAtLeastOnce);
- return changeComparison != 0
- ? changeComparison
- : f1.key.compareToIgnoreCase(f2.key);
- });
- }
- }
-
- static List<DebugFlag> getDebugFlags() {
- synchronized (sDebugFlags) {
- return new ArrayList<>(sDebugFlags);
- }
- }
-
- public static void dump(PrintWriter pw) {
- pw.println("DeviceFlags:");
- synchronized (sDebugFlags) {
- for (DebugFlag flag : sDebugFlags) {
- if (flag instanceof DeviceFlag) {
- pw.println(" " + flag.toString());
- }
- }
- }
- pw.println("DebugFlags:");
- synchronized (sDebugFlags) {
- for (DebugFlag flag : sDebugFlags) {
- if (!(flag instanceof DeviceFlag)) {
- pw.println(" " + flag.toString());
- }
- }
- }
- }
-
public static class BooleanFlag {
- public final String key;
- public final boolean defaultValue;
+ private final boolean mCurrentValue;
- public BooleanFlag(String key, boolean defaultValue) {
- this.key = key;
- this.defaultValue = defaultValue;
+ public BooleanFlag(boolean currentValue) {
+ mCurrentValue = currentValue;
}
public boolean get() {
- return defaultValue;
- }
-
- @Override
- public String toString() {
- return appendProps(new StringBuilder()).toString();
- }
-
- protected StringBuilder appendProps(StringBuilder src) {
- return src.append(key).append(", defaultValue=").append(defaultValue);
+ return sBooleanReader.test(this);
}
}
- public static class DebugFlag extends BooleanFlag {
+ /**
+ * Class representing an integer flag
+ */
+ public static class IntFlag {
- public final String description;
- protected boolean mHasBeenChangedAtLeastOnce;
- protected boolean mCurrentValue;
+ private final int mCurrentValue;
- public DebugFlag(String key, boolean defaultValue, String description) {
- super(key, defaultValue);
- this.description = description;
- mCurrentValue = this.defaultValue;
- synchronized (sDebugFlags) {
- sDebugFlags.add(this);
- }
+ public IntFlag(int currentValue) {
+ mCurrentValue = currentValue;
}
- @Override
- public boolean get() {
- return mCurrentValue;
+ public int get() {
+ return sIntReader.applyAsInt(this);
}
-
- public void initialize(Context context) {
- SharedPreferences prefs =
- context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
- mHasBeenChangedAtLeastOnce = prefs.contains(key);
- mCurrentValue = prefs.getBoolean(key, defaultValue);
- }
-
- @Override
- protected StringBuilder appendProps(StringBuilder src) {
- return super.appendProps(src).append(", mCurrentValue=").append(mCurrentValue);
- }
- }
-
- private static BooleanFlag getDebugFlag(String key, boolean defaultValue, String description) {
- return Utilities.IS_DEBUG_DEVICE
- ? new DebugFlag(key, defaultValue, description)
- : new BooleanFlag(key, defaultValue);
}
}
diff --git a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
index 08e50dd..0e76bbb 100644
--- a/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
+++ b/src/com/android/launcher3/dragndrop/SpringLoadedDragController.java
@@ -43,7 +43,7 @@
private long getEnterSpringLoadHoverTime() {
// Some TAPL tests are flaky on Cuttlefish with a low waiting time
- return Utilities.IS_RUNNING_IN_TEST_HARNESS
+ return Utilities.isRunningInTestHarness()
? ENTER_SPRING_LOAD_HOVER_TIME_IN_TEST
: ENTER_SPRING_LOAD_HOVER_TIME;
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index ee1a060..86f4beb 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -28,7 +28,6 @@
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -77,6 +76,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.IconLabelDotView;
@@ -93,6 +93,7 @@
public class FolderIcon extends FrameLayout implements FolderListener, IconLabelDotView,
DraggableView, Reorderable {
+ private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this);
@Thunk ActivityContext mActivity;
@Thunk Folder mFolder;
public FolderInfo mInfo;
@@ -133,14 +134,6 @@
private Rect mTouchArea = new Rect();
- private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
- private float mTranslationXForTaskbarAlignmentAnimation = 0f;
- private float mTranslationYForTaskbarAlignmentAnimation = 0f;
- private float mTranslationXForTaskbarRevealAnimation = 0f;
- private float mTranslationYForTaskbarRevealAnimation = 0f;
-
- private final PointF mTranslationForReorderBounce = new PointF(0, 0);
- private final PointF mTranslationForReorderPreview = new PointF(0, 0);
private float mScaleForReorderBounce = 1f;
private static final Property<FolderIcon, Float> DOT_SCALE_PROPERTY
@@ -770,120 +763,23 @@
mPreviewItemManager.onFolderClose(currentPage);
}
- private void updateTranslation() {
- super.setTranslationX(mTranslationForReorderBounce.x
- + mTranslationForReorderPreview.x
- + mTranslationForMoveFromCenterAnimation.x
- + mTranslationXForTaskbarAlignmentAnimation
- + mTranslationXForTaskbarRevealAnimation);
- super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
- + mTranslationForMoveFromCenterAnimation.y
- + mTranslationYForTaskbarAlignmentAnimation
- + mTranslationYForTaskbarRevealAnimation);
- }
-
- public void setReorderBounceOffset(float x, float y) {
- mTranslationForReorderBounce.set(x, y);
- updateTranslation();
- }
-
- public void getReorderBounceOffset(PointF offset) {
- offset.set(mTranslationForReorderBounce);
- }
-
- /**
- * Sets translationX value for taskbar to launcher alignment animation
- */
- public void setTranslationXForTaskbarAlignmentAnimation(float translationX) {
- mTranslationXForTaskbarAlignmentAnimation = translationX;
- updateTranslation();
- }
-
- /**
- * Returns translation values for taskbar to launcher alignment animation
- */
- public float getTranslationXForTaskbarAlignmentAnimation() {
- return mTranslationXForTaskbarAlignmentAnimation;
- }
-
- /**
- * Sets translationY value for taskbar to launcher alignment animation
- */
- public void setTranslationYForTaskbarAlignmentAnimation(float translationY) {
- mTranslationYForTaskbarAlignmentAnimation = translationY;
- updateTranslation();
- }
-
- /**
- * Returns translation values for taskbar to launcher alignment animation
- */
- public float getTranslationYForTaskbarAlignmentAnimation() {
- return mTranslationYForTaskbarAlignmentAnimation;
- }
-
- /**
- * Sets translationX value for taskbar reveal animation
- */
- public void setTranslationXForTaskbarRevealAnimation(float translationX) {
- mTranslationXForTaskbarRevealAnimation = translationX;
- updateTranslation();
- }
-
- /**
- * Returns translation values for taskbar reveal animation
- */
- public float getTranslationXForTaskbarRevealAnimation() {
- return mTranslationXForTaskbarRevealAnimation;
- }
-
- /**
- * Sets translationY value for taskbar reveal animation
- */
- public void setTranslationYForTaskbarRevealAnimation(float translationY) {
- mTranslationYForTaskbarRevealAnimation = translationY;
- updateTranslation();
- }
-
- /**
- * Returns translationY values for taskbar reveal animation
- */
- public float getTranslationYForTaskbarRevealAnimation() {
- return mTranslationYForTaskbarRevealAnimation;
- }
-
- /**
- * Sets translation values for move from center animation
- */
- public void setTranslationForMoveFromCenterAnimation(float x, float y) {
- mTranslationForMoveFromCenterAnimation.set(x, y);
- updateTranslation();
+ @Override
+ public MultiTranslateDelegate getTranslateDelegate() {
+ return mTranslateDelegate;
}
@Override
- public void setReorderPreviewOffset(float x, float y) {
- mTranslationForReorderPreview.set(x, y);
- updateTranslation();
- }
-
- @Override
- public void getReorderPreviewOffset(PointF offset) {
- offset.set(mTranslationForReorderPreview);
- }
-
public void setReorderBounceScale(float scale) {
mScaleForReorderBounce = scale;
super.setScaleX(scale);
super.setScaleY(scale);
}
+ @Override
public float getReorderBounceScale() {
return mScaleForReorderBounce;
}
- public View getView() {
- return this;
- }
-
@Override
public int getViewType() {
return DRAGGABLE_ICON;
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 8efd12a..5a50569 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -92,7 +92,7 @@
private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
private static final int ALPHA_DURATION_MILLIS = 3000;
- private static final int OVERLAY_ALPHA_RANGE = 127;
+ private static final int OVERLAY_ALPHA_RANGE = 191;
private static final long WAVE_MOTION_DELAY_FACTOR_MILLIS = 100;
private static final WeakHashMap<Integer, PorterDuffColorFilter> COLOR_FILTER_MAP =
new WeakHashMap<>();
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 9f8db51..8519a3e 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -246,6 +246,9 @@
sortWorkspaceItemsSpatially(idp, otherWorkspaceItems);
// Tell the workspace that we're about to start binding items
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.FLAKY_BINDING, "scheduling: startBinding");
+ }
executeCallbacksTask(c -> {
c.clearPendingBinds();
c.startBinding();
@@ -264,6 +267,9 @@
Executor pendingExecutor = pendingTasks::add;
bindWorkspaceItems(otherWorkspaceItems, pendingExecutor);
bindAppWidgets(otherAppWidgets, pendingExecutor);
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.FLAKY_BINDING, "scheduling: finishBindingItems");
+ }
executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor);
pendingExecutor.execute(
() -> {
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 8d6a5cb..d3a237c 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -52,6 +52,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.states.RotationHelper;
+import com.android.launcher3.uioverrides.flags.DeveloperOptionsFragment;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.DisplayController;
diff --git a/src/com/android/launcher3/statemanager/BaseState.java b/src/com/android/launcher3/statemanager/BaseState.java
index 2390425..a01d402 100644
--- a/src/com/android/launcher3/statemanager/BaseState.java
+++ b/src/com/android/launcher3/statemanager/BaseState.java
@@ -70,4 +70,12 @@
default boolean showTaskThumbnailSplash() {
return false;
}
+
+ /**
+ * For this state, whether member variables and other forms of data state should be preserved
+ * or wiped when the state is reapplied. (See {@link StateManager#reapplyState()})
+ */
+ default boolean shouldPreserveDataStateOnReapply() {
+ return false;
+ }
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 34ac8c2..89d89d6 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -184,6 +184,13 @@
public void reapplyState(boolean cancelCurrentAnimation) {
boolean wasInAnimation = mConfig.currentAnimation != null;
if (cancelCurrentAnimation) {
+ // Animation canceling can trigger a cleanup routine, causing problems when we are in a
+ // launcher state that relies on member variable data. So if we are in one of those
+ // states, accelerate the current animation to its end point rather than canceling it
+ // outright.
+ if (mState.shouldPreserveDataStateOnReapply() && mConfig.currentAnimation != null) {
+ mConfig.currentAnimation.end();
+ }
mAtomicAnimationFactory.cancelAllStateElementAnimation();
cancelAnimation();
}
diff --git a/src/com/android/launcher3/testing/TestInformationProvider.java b/src/com/android/launcher3/testing/TestInformationProvider.java
index 5444d92..17b472a 100644
--- a/src/com/android/launcher3/testing/TestInformationProvider.java
+++ b/src/com/android/launcher3/testing/TestInformationProvider.java
@@ -61,7 +61,7 @@
@Override
public Bundle call(String method, String arg, Bundle extras) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
TestInformationHandler handler = TestInformationHandler.newInstance(getContext());
handler.init(getContext());
diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java
index c151606..f95548d 100644
--- a/src/com/android/launcher3/testing/TestLogging.java
+++ b/src/com/android/launcher3/testing/TestLogging.java
@@ -39,13 +39,13 @@
}
public static void recordEvent(String sequence, String event) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
recordEventSlow(sequence, event);
}
}
public static void recordEvent(String sequence, String message, Object parameter) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
recordEventSlow(sequence, message + ": " + parameter);
}
}
@@ -58,14 +58,14 @@
}
public static void recordKeyEvent(String sequence, String message, KeyEvent event) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+ if (Utilities.isRunningInTestHarness()) {
recordEventSlow(sequence, message + ": " + event);
registerEventNotFromTest(event);
}
}
public static void recordMotionEvent(String sequence, String message, MotionEvent event) {
- if (Utilities.IS_RUNNING_IN_TEST_HARNESS && event.getAction() != MotionEvent.ACTION_MOVE) {
+ if (Utilities.isRunningInTestHarness() && event.getAction() != MotionEvent.ACTION_MOVE) {
recordEventSlow(sequence, message + ": " + event);
registerEventNotFromTest(event);
}
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index cf470f4..c356da9 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -448,7 +448,7 @@
@Override
public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
- int splitInstructionsWidth, int threeButtonNavShift) {
+ int splitInstructionsWidth) {
out.setPivotX(0);
out.setPivotY(splitInstructionsHeight);
out.setRotation(getDegreesRotated());
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 6234462..39ef129 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -142,7 +142,7 @@
* @param splitInstructionsWidth The SplitInstructionView's width.
*/
void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
- int splitInstructionsWidth, int threeButtonNavShift);
+ int splitInstructionsWidth);
/**
* @param splitDividerSize height of split screen drag handle in portrait, width in landscape
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 75378f6..628aa9a 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -27,7 +27,6 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
-import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
@@ -51,8 +50,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
@@ -517,57 +514,29 @@
@Override
public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
- int splitInstructionsWidth, int threeButtonNavShift) {
+ int splitInstructionsWidth) {
out.setPivotX(0);
out.setPivotY(splitInstructionsHeight);
out.setRotation(getDegreesRotated());
int distanceToEdge;
- if ((DisplayController.getNavigationMode(out.getContext()) == THREE_BUTTONS)
- && (dp.isTwoPanels || dp.isTablet)
- // If taskbar is in overview, overview action has dedicated space above nav buttons
- && !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
- // If 3-button nav is active, align the splitInstructionsView with it.
- distanceToEdge = dp.getTaskbarOffsetY()
- + ((dp.taskbarSize - splitInstructionsHeight) / 2);
- } else {
- // If 3-button nav is not active, set bottom margin according to spec.
- if (dp.isPhone) {
- if (dp.isLandscape) {
- distanceToEdge = out.getResources().getDimensionPixelSize(
- R.dimen.split_instructions_bottom_margin_phone_landscape);
- } else {
- distanceToEdge = out.getResources().getDimensionPixelSize(
- R.dimen.split_instructions_bottom_margin_phone_portrait);
- }
- } else if (dp.isTwoPanels) {
- if (dp.isLandscape) {
- distanceToEdge = out.getResources().getDimensionPixelSize(
- R.dimen.split_instructions_bottom_margin_twopanels_landscape);
- } else {
- distanceToEdge = out.getResources().getDimensionPixelSize(
- R.dimen.split_instructions_bottom_margin_twopanels_portrait);
- }
+ if (dp.isPhone) {
+ if (dp.isLandscape) {
+ distanceToEdge = out.getResources().getDimensionPixelSize(
+ R.dimen.split_instructions_bottom_margin_phone_landscape);
} else {
- if (dp.isLandscape) {
- distanceToEdge = out.getResources().getDimensionPixelSize(
- R.dimen.split_instructions_bottom_margin_tablet_landscape);
- } else {
- distanceToEdge = out.getResources().getDimensionPixelSize(
- R.dimen.split_instructions_bottom_margin_tablet_portrait);
- }
+ distanceToEdge = out.getResources().getDimensionPixelSize(
+ R.dimen.split_instructions_bottom_margin_phone_portrait);
}
+ } else {
+ distanceToEdge = dp.getOverviewActionsClaimedSpaceBelow();
}
// Center the view in case of unbalanced insets on left or right of screen
int insetCorrectionX = (dp.getInsets().right - dp.getInsets().left) / 2;
// Adjust for any insets on the bottom edge
int insetCorrectionY = dp.getInsets().bottom;
- // Adjust for taskbar in overview
- int taskbarCorrectionY =
- dp.isTaskbarPresent && FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()
- ? dp.taskbarSize : 0;
- out.setTranslationX(insetCorrectionX + threeButtonNavShift);
- out.setTranslationY(-distanceToEdge + insetCorrectionY - taskbarCorrectionY);
+ out.setTranslationX(insetCorrectionX);
+ out.setTranslationY(-distanceToEdge + insetCorrectionY);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) out.getLayoutParams();
lp.gravity = CENTER_HORIZONTAL | BOTTOM;
out.setLayoutParams(lp);
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index 3363443..ec01231 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -184,7 +184,7 @@
@Override
public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
- int splitInstructionsWidth, int threeButtonNavShift) {
+ int splitInstructionsWidth) {
out.setPivotX(0);
out.setPivotY(splitInstructionsHeight);
out.setRotation(getDegreesRotated());
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 9ed6700..3d455d8 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -139,11 +139,11 @@
// TODO(b/258604917): When running in test harness, use !sTransientTaskbarStatusForTests
// once tests are updated to expect new persistent behavior such as not allowing long press
// to stash.
- if (!Utilities.IS_RUNNING_IN_TEST_HARNESS && FORCE_PERSISTENT_TASKBAR.get()) {
+ if (!Utilities.isRunningInTestHarness() && FORCE_PERSISTENT_TASKBAR.get()) {
return false;
}
return getInfo().navigationMode == NavigationMode.NO_BUTTON
- && (Utilities.IS_RUNNING_IN_TEST_HARNESS
+ && (Utilities.isRunningInTestHarness()
? sTransientTaskbarStatusForTests
: ENABLE_TRANSIENT_TASKBAR.get());
}
diff --git a/src/com/android/launcher3/util/LockedUserState.kt b/src/com/android/launcher3/util/LockedUserState.kt
index 7b49583..f5e13d2 100644
--- a/src/com/android/launcher3/util/LockedUserState.kt
+++ b/src/com/android/launcher3/util/LockedUserState.kt
@@ -50,7 +50,9 @@
}
companion object {
- @VisibleForTesting val INSTANCE = MainThreadInitializedObject { LockedUserState(it) }
+ @VisibleForTesting
+ @JvmField
+ val INSTANCE = MainThreadInitializedObject { LockedUserState(it) }
@JvmStatic fun get(context: Context): LockedUserState = INSTANCE.get(context)
}
diff --git a/src/com/android/launcher3/util/MultiTranslateDelegate.java b/src/com/android/launcher3/util/MultiTranslateDelegate.java
new file mode 100644
index 0000000..0b5bc8d
--- /dev/null
+++ b/src/com/android/launcher3/util/MultiTranslateDelegate.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
+
+import android.view.View;
+
+import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
+
+/**
+ * A utility class to split translation components for various workspace items
+ */
+public class MultiTranslateDelegate {
+
+ // offset related to reorder hint and bounce animations
+ public static final int INDEX_REORDER_BOUNCE_OFFSET = 0;
+ // offset related to previewing the new reordered position
+ public static final int INDEX_REORDER_PREVIEW_OFFSET = 1;
+ public static final int INDEX_MOVE_FROM_CENTER_ANIM = 2;
+
+ // Specific for icons and folders
+ public static final int INDEX_TASKBAR_ALIGNMENT_ANIM = 3;
+ public static final int INDEX_TASKBAR_REVEAL_ANIM = 4;
+
+ // Specific for widgets
+ public static final int INDEX_WIDGET_CENTERING = 3;
+
+ public static final int COUNT = 5;
+
+ private final MultiPropertyFactory<View> mTranslationX;
+ private final MultiPropertyFactory<View> mTranslationY;
+
+ public MultiTranslateDelegate(View target) {
+ this(target, COUNT, COUNT);
+ }
+
+ public MultiTranslateDelegate(View target, int countX, int countY) {
+ mTranslationX = new MultiPropertyFactory<>(target, VIEW_TRANSLATE_X, countX, Float::sum);
+ mTranslationY = new MultiPropertyFactory<>(target, VIEW_TRANSLATE_Y, countY, Float::sum);
+ }
+
+ /**
+ * Helper method to set both translations, x and y at a given index
+ */
+ public void setTranslation(int index, float x, float y) {
+ getTranslationX(index).setValue(x);
+ getTranslationY(index).setValue(y);
+ }
+
+ /**
+ * Returns the translation x for the provided index
+ */
+ public MultiProperty getTranslationX(int index) {
+ return mTranslationX.get(index);
+ }
+
+ /**
+ * Returns the translation y for the provided index
+ */
+ public MultiProperty getTranslationY(int index) {
+ return mTranslationY.get(index);
+ }
+}
diff --git a/src/com/android/launcher3/views/IconButtonView.java b/src/com/android/launcher3/views/IconButtonView.java
index 64e9327..71f6756 100644
--- a/src/com/android/launcher3/views/IconButtonView.java
+++ b/src/com/android/launcher3/views/IconButtonView.java
@@ -31,11 +31,13 @@
import android.util.AttributeSet;
import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.icons.LauncherIcons;
+import com.android.launcher3.util.MultiTranslateDelegate;
/**
* Button in Taskbar that shows a tinted background and foreground.
@@ -44,6 +46,12 @@
private static final int[] ATTRS = {android.R.attr.icon};
+ private static final int INDEX_TASKBAR_ALL_APPS_ICON = MultiTranslateDelegate.COUNT;
+ private static final int MY_COUNT = MultiTranslateDelegate.COUNT + 1;
+
+ private final MultiTranslateDelegate mTranslateDelegate =
+ new MultiTranslateDelegate(this, MY_COUNT, MultiTranslateDelegate.COUNT);
+
public IconButtonView(Context context) {
this(context, null);
}
@@ -70,6 +78,15 @@
}
}
+ /** Sets given Drawable as icon */
+ public void setIconDrawable(@NonNull Drawable drawable) {
+ ColorStateList tintList = getBackgroundTintList();
+ int tint = tintList == null ? Color.WHITE : tintList.getDefaultColor();
+ try (BaseIconFactory factory = LauncherIcons.obtain(getContext())) {
+ setIcon(new IconDrawable(factory.getWhiteShadowLayer(), tint, drawable));
+ }
+ }
+
/** Updates the color of the icon's foreground layer. */
public void setForegroundTint(@ColorInt int tintColor) {
FastBitmapDrawable icon = getIcon();
@@ -78,6 +95,18 @@
}
}
+ @Override
+ public MultiTranslateDelegate getTranslateDelegate() {
+ return mTranslateDelegate;
+ }
+
+ /**
+ * Sets translationX for taskbar all apps icon
+ */
+ public void setTranslationXForTaskbarAllAppsIcon(float translationX) {
+ getTranslateDelegate().getTranslationX(INDEX_TASKBAR_ALL_APPS_ICON).setValue(translationX);
+ }
+
private static class IconDrawable extends FastBitmapDrawable {
private final Drawable mFg;
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 2ac1e94..68ece03 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -341,7 +341,7 @@
/** Returns {@code true} if tip has previously been shown on any of {@link BaseWidgetSheet}. */
protected boolean hasSeenEducationTip() {
return mActivityContext.getSharedPrefs().getBoolean(KEY_WIDGETS_EDUCATION_TIP_SEEN, false)
- || Utilities.IS_RUNNING_IN_TEST_HARNESS;
+ || Utilities.isRunningInTestHarness();
}
@Override
diff --git a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
index 241c937..3389fb1 100644
--- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
@@ -19,7 +19,6 @@
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.View;
@@ -29,6 +28,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Reorderable;
import com.android.launcher3.dragndrop.DraggableView;
+import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -39,20 +39,13 @@
public abstract class NavigableAppWidgetHostView extends AppWidgetHostView
implements DraggableView, Reorderable {
+ private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this);
+
/**
* The scaleX and scaleY value such that the widget fits within its cellspans, scaleX = scaleY.
*/
private float mScaleToFit = 1f;
- /**
- * The translation values to center the widget within its cellspans.
- */
- private final PointF mTranslationForCentering = new PointF(0, 0);
-
- private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
-
- private final PointF mTranslationForReorderBounce = new PointF(0, 0);
- private final PointF mTranslationForReorderPreview = new PointF(0, 0);
private float mScaleForReorderBounce = 1f;
private final Rect mTempRect = new Rect();
@@ -163,57 +156,23 @@
setSelected(childIsFocused);
}
- public View getView() {
- return this;
- }
-
- private void updateTranslation() {
- super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x
- + mTranslationForCentering.x + mTranslationForMoveFromCenterAnimation.x);
- super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
- + mTranslationForCentering.y + mTranslationForMoveFromCenterAnimation.y);
- }
-
- public void setTranslationForCentering(float x, float y) {
- mTranslationForCentering.set(x, y);
- updateTranslation();
- }
-
- public void setTranslationForMoveFromCenterAnimation(float x, float y) {
- mTranslationForMoveFromCenterAnimation.set(x, y);
- updateTranslation();
- }
-
- public void setReorderBounceOffset(float x, float y) {
- mTranslationForReorderBounce.set(x, y);
- updateTranslation();
- }
-
- public void getReorderBounceOffset(PointF offset) {
- offset.set(mTranslationForReorderBounce);
- }
-
- @Override
- public void setReorderPreviewOffset(float x, float y) {
- mTranslationForReorderPreview.set(x, y);
- updateTranslation();
- }
-
- @Override
- public void getReorderPreviewOffset(PointF offset) {
- offset.set(mTranslationForReorderPreview);
- }
-
private void updateScale() {
super.setScaleX(mScaleToFit * mScaleForReorderBounce);
super.setScaleY(mScaleToFit * mScaleForReorderBounce);
}
+ @Override
+ public MultiTranslateDelegate getTranslateDelegate() {
+ return mTranslateDelegate;
+ }
+
+ @Override
public void setReorderBounceScale(float scale) {
mScaleForReorderBounce = scale;
updateScale();
}
+ @Override
public float getReorderBounceScale() {
return mScaleForReorderBounce;
}
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index ce47d70..80bc1a7 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
import static com.android.launcher3.Utilities.ATLEAST_S;
+import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_WIDGET_CENTERING;
import android.content.Context;
import android.graphics.Bitmap;
@@ -314,7 +315,7 @@
setScaleToFit(1.0f);
}
// When the drag start, translations need to be set to zero to center the view
- setTranslationForCentering(0f, 0f);
+ getTranslateDelegate().setTranslation(INDEX_WIDGET_CENTERING, 0f, 0f);
}
}
@@ -464,7 +465,8 @@
} else {
mAppWidgetHostViewPreview.setScaleToFit(mAppWidgetHostViewScale);
}
- mAppWidgetHostViewPreview.setTranslationForCentering(
+ mAppWidgetHostViewPreview.getTranslateDelegate().setTranslation(
+ INDEX_WIDGET_CENTERING,
-(params.width - (params.width * mPreviewContainerScale)) / 2.0f,
-(params.height - (params.height * mPreviewContainerScale)) / 2.0f);
mWidgetImageContainer.addView(mAppWidgetHostViewPreview, /* index= */ 0);
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index f8068aa..f4d6749 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -201,6 +201,7 @@
private TextView mHeaderTitle;
private FrameLayout mRightPane;
private WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder;
+ private DeviceProfile mDeviceProfile;
private final boolean mIsTwoPane;
private int mOrientation;
@@ -210,8 +211,10 @@
public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- DeviceProfile dp = Launcher.getLauncher(context).getDeviceProfile();
- mIsTwoPane = dp.isTablet && dp.isLandscape && LARGE_SCREEN_WIDGET_PICKER.get();
+ mDeviceProfile = Launcher.getLauncher(context).getDeviceProfile();
+ mIsTwoPane = mDeviceProfile.isTablet
+ && mDeviceProfile.isLandscape
+ && LARGE_SCREEN_WIDGET_PICKER.get();
mHasWorkProfile = context.getSystemService(LauncherApps.class).getProfiles().size() > 1;
mAdapters.put(AdapterHolder.PRIMARY, new AdapterHolder(AdapterHolder.PRIMARY));
mAdapters.put(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK));
@@ -874,7 +877,9 @@
}
// Checks the orientation of the screen
- if (LARGE_SCREEN_WIDGET_PICKER.get() && mOrientation != newConfig.orientation) {
+ if (LARGE_SCREEN_WIDGET_PICKER.get()
+ && mOrientation != newConfig.orientation
+ && mDeviceProfile.isTablet) {
mOrientation = newConfig.orientation;
handleClose(false);
show(Launcher.getLauncher(getContext()), false);
@@ -934,7 +939,7 @@
protected boolean hasSeenEducationDialog() {
return mActivityContext.getSharedPrefs()
.getBoolean(KEY_WIDGETS_EDUCATION_DIALOG_SEEN, false)
- || Utilities.IS_RUNNING_IN_TEST_HARNESS;
+ || Utilities.isRunningInTestHarness();
}
private void setUpEducationViewsIfNeeded() {
diff --git a/src/com/android/launcher3/workspace/WorkspaceSpecs.kt b/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
index 0f6e1b0..971fd9b 100644
--- a/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
+++ b/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
@@ -77,8 +77,7 @@
attrs.getInt(
R.styleable.WorkspaceSpec_specType,
WorkspaceSpec.SpecType.HEIGHT.ordinal
- )
- ]
+ )]
attrs.recycle()
var startPadding: SizeSpec? = null
diff --git a/src_build_config/com/android/launcher3/BuildConfig.java b/src_build_config/com/android/launcher3/BuildConfig.java
index 9a81d3f..1f2e0e5 100644
--- a/src_build_config/com/android/launcher3/BuildConfig.java
+++ b/src_build_config/com/android/launcher3/BuildConfig.java
@@ -18,10 +18,16 @@
public final class BuildConfig {
public static final String APPLICATION_ID = "com.android.launcher3";
- public static final boolean DEBUG = false;
+
+ public static final boolean IS_STUDIO_BUILD = false;
/**
* Flag to state if the QSB is on the first screen and placed on the top,
* this can be overwritten in other launchers with a different value, if needed.
*/
public static final boolean QSB_ON_FIRST_SCREEN = true;
+
+ /**
+ * Flag to control various developer centric features
+ */
+ public static final boolean IS_DEBUG_DEVICE = false;
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/DeviceFlag.java b/src_ui_overrides/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
similarity index 62%
rename from src_ui_overrides/com/android/launcher3/uioverrides/DeviceFlag.java
rename to src_ui_overrides/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index 5c1ac28..68843f2 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/DeviceFlag.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,14 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.launcher3.uioverrides.flags;
-package com.android.launcher3.uioverrides;
-
-import com.android.launcher3.config.FeatureFlags.DebugFlag;
-
-public class DeviceFlag extends DebugFlag {
-
- public DeviceFlag(String key, boolean defaultValue, String description) {
- super(key, defaultValue, description);
- }
+/**
+ * Place holder class for developer options.
+ */
+public class DeveloperOptionsFragment {
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
new file mode 100644
index 0000000..4463adc
--- /dev/null
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides.flags;
+
+import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+import com.android.launcher3.config.FeatureFlags.IntFlag;
+
+import java.io.PrintWriter;
+
+/**
+ * Helper class to create various flags for launcher build. The base implementation does
+ * not provide any flagging system, and simply replies with the default value.
+ */
+public class FlagsFactory {
+
+ /**
+ * Creates a new debug flag
+ */
+ public static BooleanFlag getDebugFlag(
+ int bugId, String key, boolean defaultValue, String description) {
+ return new BooleanFlag(defaultValue);
+ }
+
+ /**
+ * Creates a new debug flag
+ */
+ public static BooleanFlag getReleaseFlag(
+ int bugId, String key, boolean defaultValueInCode, String description) {
+ return new BooleanFlag(defaultValueInCode);
+ }
+
+ /**
+ * Creates a new integer flag. Integer flags are always release flags
+ */
+ public static IntFlag getIntFlag(
+ int bugId, String key, int defaultValueInCode, String description) {
+ return new IntFlag(defaultValueInCode);
+ }
+
+ /**
+ * Dumps the current flags state to the print writer
+ */
+ public static void dump(PrintWriter pw) { }
+}
diff --git a/tests/Android.bp b/tests/Android.bp
index 7144d65..dfbaf86 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -44,6 +44,7 @@
srcs: [
"src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
"src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
+ "src/com/android/launcher3/ui/TaplTestsLauncher3.java",
"src/com/android/launcher3/util/TestUtil.java",
"src/com/android/launcher3/util/Wait.java",
"src/com/android/launcher3/util/WidgetUtils.java",
@@ -54,7 +55,7 @@
"src/com/android/launcher3/util/rule/ShellCommandRule.java",
"src/com/android/launcher3/util/rule/SimpleActivityRule.java",
"src/com/android/launcher3/util/rule/TestStabilityRule.java",
- "src/com/android/launcher3/ui/TaplTestsLauncher3.java",
+ "src/com/android/launcher3/util/rule/TISBindRule.java",
"src/com/android/launcher3/testcomponent/BaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java",
"src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 65873f1..c69ec2c 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -154,6 +154,8 @@
public static final String MISSING_PROMISE_ICON = "b/202985412";
public static final String TASKBAR_IN_APP_STATE = "b/227657604";
public static final String NPE_TRANSIENT_TASKBAR = "b/257549303";
+ public static final String FLAKY_BINDING = "b/270216650";
+ public static final String VIEW_AND_ACTIVITY_LEAKS = "b/260260325";
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/src/com/android/launcher3/LauncherPrefsTest.kt
index e8372b1..41ef3de 100644
--- a/tests/src/com/android/launcher3/LauncherPrefsTest.kt
+++ b/tests/src/com/android/launcher3/LauncherPrefsTest.kt
@@ -1,9 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.launcher3
+import android.content.Context
+import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.LauncherPrefs.Companion.BOOT_AWARE_PREFS_KEY
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@@ -13,19 +31,22 @@
private val TEST_BOOLEAN_ITEM = LauncherPrefs.nonRestorableItem("1", false)
private val TEST_STRING_ITEM = LauncherPrefs.nonRestorableItem("2", "( ͡❛ ͜ʖ ͡❛)")
private val TEST_INT_ITEM = LauncherPrefs.nonRestorableItem("3", -1)
-private val TEST_CONTEXTUAL_ITEM = ContextualItem("4", true, { true }, Boolean::class.java)
+private val TEST_CONTEXTUAL_ITEM = ContextualItem("4", true, { true }, false, Boolean::class.java)
private const val TEST_DEFAULT_VALUE = "default"
private const val TEST_PREF_KEY = "test_pref_key"
+private const val WAIT_TIME_IN_SECONDS = 3L
+
@SmallTest
@RunWith(AndroidJUnit4::class)
class LauncherPrefsTest {
- private val launcherPrefs by lazy {
- LauncherPrefs.get(InstrumentationRegistry.getInstrumentation().targetContext).apply {
- remove(TEST_BOOLEAN_ITEM, TEST_STRING_ITEM, TEST_INT_ITEM)
- }
+ private val context by lazy { InstrumentationRegistry.getInstrumentation().targetContext }
+ private val launcherPrefs by lazy { LauncherPrefs.get(context) }
+
+ init {
+ isBootAwareStartupDataEnabled = true
}
@Test
@@ -52,7 +73,7 @@
addListener(listener, TEST_STRING_ITEM)
putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"))
- assertThat(latch.await(2, TimeUnit.SECONDS)).isTrue()
+ assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isTrue()
remove(TEST_STRING_ITEM)
}
}
@@ -68,7 +89,7 @@
putSync(TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "hello."))
// latch will be still be 1 (and await will return false) if the listener was not called
- assertThat(latch.await(2, TimeUnit.SECONDS)).isFalse()
+ assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isFalse()
remove(TEST_STRING_ITEM)
}
}
@@ -85,7 +106,7 @@
TEST_STRING_ITEM.to(TEST_STRING_ITEM.defaultValue + "abc"),
TEST_BOOLEAN_ITEM.to(!TEST_BOOLEAN_ITEM.defaultValue)
)
- assertThat(latch.await(2, TimeUnit.SECONDS)).isTrue()
+ assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isTrue()
removeListener(listener, TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
latch = CountDownLatch(1)
@@ -96,7 +117,7 @@
)
remove(TEST_INT_ITEM, TEST_STRING_ITEM, TEST_BOOLEAN_ITEM)
- assertThat(latch.await(2, TimeUnit.SECONDS)).isFalse()
+ assertThat(latch.await(WAIT_TIME_IN_SECONDS, TimeUnit.SECONDS)).isFalse()
}
}
@@ -166,4 +187,133 @@
val backedUpItem = LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE)
assertThat(backedUpItem.sharedPrefFile).isEqualTo(LauncherFiles.SHARED_PREFERENCES_KEY)
}
+
+ @Test
+ fun put_bootAwareItem_updatesDeviceProtectedStorage() {
+ val bootAwareItem =
+ LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
+
+ val bootAwarePrefs: SharedPreferences =
+ context
+ .createDeviceProtectedStorageContext()
+ .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
+ bootAwarePrefs.edit().remove(bootAwareItem.sharedPrefKey).commit()
+
+ launcherPrefs.putSync(bootAwareItem.to(bootAwareItem.defaultValue))
+ assertThat(bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)).isTrue()
+
+ launcherPrefs.removeSync(bootAwareItem)
+ }
+
+ @Test
+ fun put_bootAwareItem_updatesEncryptedStorage() {
+ val bootAwareItem =
+ LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
+
+ val encryptedPrefs: SharedPreferences =
+ context.getSharedPreferences(bootAwareItem.sharedPrefFile, Context.MODE_PRIVATE)
+ encryptedPrefs.edit().remove(bootAwareItem.sharedPrefKey).commit()
+
+ launcherPrefs.putSync(bootAwareItem.to(TEST_STRING_ITEM.defaultValue))
+ assertThat(encryptedPrefs.contains(bootAwareItem.sharedPrefKey)).isTrue()
+
+ launcherPrefs.removeSync(bootAwareItem)
+ }
+
+ @Test
+ fun remove_bootAwareItem_removesFromDeviceProtectedStorage() {
+ val bootAwareItem =
+ LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
+
+ val bootAwarePrefs: SharedPreferences =
+ context
+ .createDeviceProtectedStorageContext()
+ .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
+
+ bootAwarePrefs
+ .edit()
+ .putString(bootAwareItem.sharedPrefKey, bootAwareItem.defaultValue)
+ .commit()
+
+ launcherPrefs.removeSync(bootAwareItem)
+ assertThat(bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)).isFalse()
+ }
+
+ @Test
+ fun remove_bootAwareItem_removesFromEncryptedStorage() {
+ val bootAwareItem =
+ LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
+
+ val encryptedPrefs: SharedPreferences =
+ context.getSharedPreferences(bootAwareItem.sharedPrefFile, Context.MODE_PRIVATE)
+
+ encryptedPrefs
+ .edit()
+ .putString(bootAwareItem.sharedPrefKey, bootAwareItem.defaultValue)
+ .commit()
+
+ launcherPrefs.removeSync(bootAwareItem)
+ assertThat(encryptedPrefs.contains(bootAwareItem.sharedPrefKey)).isFalse()
+ }
+
+ @Test
+ fun migrate_bootAwareItemsToDeviceProtectedStorage_worksAsIntended() {
+ val bootAwareItem =
+ LauncherPrefs.backedUpItem(TEST_PREF_KEY, TEST_DEFAULT_VALUE, isBootAware = true)
+ launcherPrefs.removeSync(bootAwareItem)
+
+ val bootAwarePrefs: SharedPreferences =
+ context
+ .createDeviceProtectedStorageContext()
+ .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
+
+ if (bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)) {
+ bootAwarePrefs.edit().remove(bootAwareItem.sharedPrefKey).commit()
+ }
+
+ val encryptedPrefs: SharedPreferences =
+ context.getSharedPreferences(bootAwareItem.sharedPrefFile, Context.MODE_PRIVATE)
+
+ encryptedPrefs
+ .edit()
+ .putString(bootAwareItem.sharedPrefKey, bootAwareItem.defaultValue)
+ .commit()
+
+ launcherPrefs.migrateStartupDataToDeviceProtectedStorage()
+ assertThat(bootAwarePrefs.contains(bootAwareItem.sharedPrefKey)).isTrue()
+
+ launcherPrefs.removeSync(bootAwareItem)
+ }
+
+ @Test
+ fun migrate_onlyEncryptedItemsToDeviceProtectedStorage_doesNotHappen() {
+ val onlyEncryptedItem =
+ LauncherPrefs.backedUpItem(
+ TEST_PREF_KEY + "_",
+ TEST_DEFAULT_VALUE + "_",
+ isBootAware = false
+ )
+
+ val bootAwarePrefs: SharedPreferences =
+ context
+ .createDeviceProtectedStorageContext()
+ .getSharedPreferences(BOOT_AWARE_PREFS_KEY, Context.MODE_PRIVATE)
+
+ if (bootAwarePrefs.contains(onlyEncryptedItem.sharedPrefKey)) {
+ bootAwarePrefs.edit().remove(onlyEncryptedItem.sharedPrefKey).commit()
+ }
+
+ val encryptedPrefs: SharedPreferences =
+ context.getSharedPreferences(onlyEncryptedItem.sharedPrefFile, Context.MODE_PRIVATE)
+
+ encryptedPrefs
+ .edit()
+ .putString(onlyEncryptedItem.sharedPrefKey, onlyEncryptedItem.defaultValue)
+ .commit()
+
+ launcherPrefs.migrateStartupDataToDeviceProtectedStorage()
+ assertThat(bootAwarePrefs.contains(onlyEncryptedItem.sharedPrefKey)).isFalse()
+
+ encryptedPrefs.edit().remove(onlyEncryptedItem.sharedPrefKey).commit()
+ }
}
diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
index 77fca96..c2fe3de 100644
--- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
+++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java
@@ -33,6 +33,7 @@
import com.android.launcher3.celllayout.testcases.SimpleReorderCase;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.tapl.WidgetResizeFrame;
+import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -118,7 +119,14 @@
// waitForLauncherCondition to wait for that condition, otherwise the condition would
// always be true and it wouldn't wait for the changes to be applied.
resetLoaderState();
- waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
+ Log.d(TestProtocol.FLAKY_BINDING, "waiting for: isWorkspaceLoading=false");
+ waitForLauncherCondition("Workspace didn't finish loading", l -> {
+ boolean isWorkspaceLoading = l.isWorkspaceLoading();
+
+ Log.d(TestProtocol.FLAKY_BINDING, "checking: isWorkspaceLoading=" + isWorkspaceLoading);
+
+ return !isWorkspaceLoading;
+ });
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
mainWidgetCellPos.getCellY());
assertNotNull(widget);
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index ca269a9..f24f0da 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -33,7 +33,6 @@
import com.android.launcher3.provider.LauncherDbUtils
import com.android.launcher3.util.LauncherModelHelper
import com.android.launcher3.util.LauncherModelHelper.*
-import com.android.launcher3.util.TestUtil
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -619,8 +618,6 @@
assertThat(locMap[testPackage3]).isEqualTo(1)
assertThat(locMap[testPackage4]).isEqualTo(1)
assertThat(locMap[testPackage5]).isEqualTo(2)
-
- disableNewMigrationLogic()
}
/**
@@ -685,7 +682,6 @@
assertThat(locMap[testPackage3]).isEqualTo(0)
assertThat(locMap[testPackage4]).isEqualTo(0)
assertThat(locMap[testPackage5]).isEqualTo(0)
- disableNewMigrationLogic()
}
/** Migrating from a larger grid to a smaller, we reflow from page 0 */
@@ -746,19 +742,9 @@
assertThat(locMap[testPackage3]).isEqualTo(0)
assertThat(locMap[testPackage4]).isEqualTo(0)
assertThat(locMap[testPackage5]).isEqualTo(0)
-
- disableNewMigrationLogic()
}
private fun enableNewMigrationLogic(srcGridSize: String) {
LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize))
- TestUtil.overrideBooleanFlagValue(context,
- FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC, true);
- FeatureFlags.initialize(context)
- }
-
- private fun disableNewMigrationLogic() {
- TestUtil.overrideBooleanFlagValue(context,
- FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC, false);
}
}
diff --git a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
index d981267..af31e93 100644
--- a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
+++ b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
@@ -76,6 +76,8 @@
"\ticonSizePx: 147.0px (56.0dp)\n" +
"\ticonTextSizePx: 38.0px (14.476191dp)\n" +
"\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tinv.numFolderRows: 4\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 195.0px (74.28571dp)\n" +
"\tfolderCellHeightPx: 230.0px (87.61905dp)\n" +
"\tfolderChildIconSizePx: 147.0px (56.0dp)\n" +
@@ -206,6 +208,8 @@
"\ticonSizePx: 147.0px (56.0dp)\n" +
"\ticonTextSizePx: 38.0px (14.476191dp)\n" +
"\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tinv.numFolderRows: 4\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 195.0px (74.28571dp)\n" +
"\tfolderCellHeightPx: 230.0px (87.61905dp)\n" +
"\tfolderChildIconSizePx: 147.0px (56.0dp)\n" +
@@ -336,6 +340,8 @@
"\ticonSizePx: 147.0px (56.0dp)\n" +
"\ticonTextSizePx: 0.0px (0.0dp)\n" +
"\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
+ "\tinv.numFolderRows: 4\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 142.0px (54.095238dp)\n" +
"\tfolderCellHeightPx: 168.0px (64.0dp)\n" +
"\tfolderChildIconSizePx: 108.0px (41.142857dp)\n" +
@@ -466,6 +472,8 @@
"\ticonSizePx: 147.0px (56.0dp)\n" +
"\ticonTextSizePx: 0.0px (0.0dp)\n" +
"\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
+ "\tinv.numFolderRows: 4\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 128.0px (48.761906dp)\n" +
"\tfolderCellHeightPx: 152.0px (57.904762dp)\n" +
"\tfolderChildIconSizePx: 98.0px (37.333332dp)\n" +
@@ -597,6 +605,8 @@
"\ticonSizePx: 120.0px (60.0dp)\n" +
"\ticonTextSizePx: 28.0px (14.0dp)\n" +
"\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 3\n" +
"\tfolderCellWidthPx: 397.0px (198.5dp)\n" +
"\tfolderCellHeightPx: 371.0px (185.5dp)\n" +
"\tfolderChildIconSizePx: 99.0px (49.5dp)\n" +
@@ -728,6 +738,8 @@
"\ticonSizePx: 120.0px (60.0dp)\n" +
"\ticonTextSizePx: 28.0px (14.0dp)\n" +
"\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 3\n" +
"\tfolderCellWidthPx: 397.0px (198.5dp)\n" +
"\tfolderCellHeightPx: 371.0px (185.5dp)\n" +
"\tfolderChildIconSizePx: 99.0px (49.5dp)\n" +
@@ -859,6 +871,8 @@
"\ticonSizePx: 120.0px (60.0dp)\n" +
"\ticonTextSizePx: 28.0px (14.0dp)\n" +
"\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 3\n" +
"\tfolderCellWidthPx: 408.0px (204.0dp)\n" +
"\tfolderCellHeightPx: 648.0px (324.0dp)\n" +
"\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
@@ -990,6 +1004,8 @@
"\ticonSizePx: 120.0px (60.0dp)\n" +
"\ticonTextSizePx: 28.0px (14.0dp)\n" +
"\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 3\n" +
"\tfolderCellWidthPx: 408.0px (204.0dp)\n" +
"\tfolderCellHeightPx: 648.0px (324.0dp)\n" +
"\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
@@ -1126,6 +1142,8 @@
"\ticonSizePx: 141.0px (53.714287dp)\n" +
"\ticonTextSizePx: 34.0px (12.952381dp)\n" +
"\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
"\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
"\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
@@ -1261,6 +1279,8 @@
"\ticonSizePx: 141.0px (53.714287dp)\n" +
"\ticonTextSizePx: 34.0px (12.952381dp)\n" +
"\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
"\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
"\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
@@ -1396,6 +1416,8 @@
"\ticonSizePx: 141.0px (53.714287dp)\n" +
"\ticonTextSizePx: 34.0px (12.952381dp)\n" +
"\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
"\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
"\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
@@ -1527,6 +1549,8 @@
"\ticonSizePx: 141.0px (53.714287dp)\n" +
"\ticonTextSizePx: 34.0px (12.952381dp)\n" +
"\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tinv.numFolderRows: 3\n" +
+ "\tinv.numFolderColumns: 4\n" +
"\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
"\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
"\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
diff --git a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
index 33a7f5c..7e9d9da 100644
--- a/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
+++ b/tests/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncherTest.java
@@ -21,7 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
-import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.os.SystemClock;
@@ -34,11 +33,8 @@
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.ui.AbstractLauncherUiTest;
-import com.android.launcher3.util.LauncherModelHelper;
-import com.android.launcher3.util.TestUtil;
import org.junit.After;
import org.junit.Ignore;
@@ -278,9 +274,6 @@
}
private void setDragNDropFlag(Boolean status) {
- Context context = new LauncherModelHelper().sandboxContext;
- TestUtil.overrideBooleanFlagValue(
- context, FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN, status);
startSecondaryDisplayActivity();
}
}
diff --git a/tests/src/com/android/launcher3/settings/SettingsActivityTest.java b/tests/src/com/android/launcher3/settings/SettingsActivityTest.java
index 1c205f0..837973f 100644
--- a/tests/src/com/android/launcher3/settings/SettingsActivityTest.java
+++ b/tests/src/com/android/launcher3/settings/SettingsActivityTest.java
@@ -50,6 +50,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.flags.DeveloperOptionsFragment;
import com.android.systemui.shared.plugins.PluginPrefs;
import org.junit.After;
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 401c25a4..19b8b0c 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -51,11 +51,13 @@
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.util.TestUtil;
import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+import com.android.launcher3.util.rule.TISBindRule;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.WidgetsRecyclerView;
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,6 +73,9 @@
private static final String STORE_APP_NAME = "Play Store";
private static final String GMAIL_APP_NAME = "Gmail";
+ @Rule
+ public TISBindRule mTISBindRule = new TISBindRule();
+
@Before
public void setUp() throws Exception {
super.setUp();
@@ -214,7 +219,7 @@
false /* tapRight */);
}
- @IwTest(focusArea="launcher")
+ @IwTest(focusArea = "launcher")
@Test
@ScreenRecord // b/202433017
public void testWorkspace() throws Exception {
@@ -341,7 +346,7 @@
}
}
- @IwTest(focusArea="launcher")
+ @IwTest(focusArea = "launcher")
@Test
@PortraitLandscape
@ScreenRecord // b/256898879
@@ -610,16 +615,16 @@
/**
* @return List of workspace grid coordinates. Those are not pixels. See {@link
- * Workspace#getIconGridDimensions()}
+ * Workspace#getIconGridDimensions()}
*/
private Point[] getCornersAndCenterPositions() {
final Point dimensions = mLauncher.getWorkspace().getIconGridDimensions();
- return new Point[] {
- new Point(0, 1),
- new Point(0, dimensions.y - 2),
- new Point(dimensions.x - 1, 1),
- new Point(dimensions.x - 1, dimensions.y - 2),
- new Point(dimensions.x / 2, dimensions.y / 2)
+ return new Point[]{
+ new Point(0, 1),
+ new Point(0, dimensions.y - 2),
+ new Point(dimensions.x - 1, 1),
+ new Point(dimensions.x - 1, dimensions.y - 2),
+ new Point(dimensions.x / 2, dimensions.y / 2)
};
}
diff --git a/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt b/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
index 4303bfb..c9c9616 100644
--- a/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
+++ b/tests/src/com/android/launcher3/util/KotlinMockitoHelpers.kt
@@ -101,15 +101,18 @@
/**
* Helper function for creating and using a single-use ArgumentCaptor in kotlin.
+ *
* ```
* val captor = argumentCaptor<Foo>()
* verify(...).someMethod(captor.capture())
* val captured = captor.value
* ```
+ *
* becomes:
* ```
* val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
* ```
+ *
* NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
*/
inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index fa4c519..545b645 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -510,7 +510,7 @@
UserCache.INSTANCE, InstallSessionHelper.INSTANCE, LauncherPrefs.INSTANCE,
LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE,
DisplayController.INSTANCE, CustomWidgetManager.INSTANCE,
- SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE,
+ SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE, LockedUserState.INSTANCE,
ItemInstallQueue.INSTANCE, WindowManagerProxy.INSTANCE);
mPm = spy(getBaseContext().getPackageManager());
mDbDir = new File(getCacheDir(), UUID.randomUUID().toString());
diff --git a/tests/src/com/android/launcher3/util/TestUtil.java b/tests/src/com/android/launcher3/util/TestUtil.java
index 38de4c3..433fd31 100644
--- a/tests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/src/com/android/launcher3/util/TestUtil.java
@@ -19,17 +19,17 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.InstrumentationRegistry.getTargetContext;
-import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
import androidx.test.uiautomator.UiDevice;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.config.FeatureFlags.BooleanFlag;
+import com.android.launcher3.config.FeatureFlags.IntFlag;
import org.junit.Assert;
@@ -37,6 +37,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.CountDownLatch;
+import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
public class TestUtil {
public static final String DUMMY_PACKAGE = "com.example.android.aardwolf";
@@ -72,16 +74,34 @@
}
}
- @VisibleForTesting
- // Override feature flag, mainly to be used ONLY in tests
- public static void overrideBooleanFlagValue(
- Context context, FeatureFlags.BooleanFlag flagToOverride,
- boolean bool) {
- context.getSharedPreferences(FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE)
- .edit()
- .putBoolean(flagToOverride.key, bool)
- .commit();
- FeatureFlags.initialize(context);
+ /**
+ * Utility class to override a boolean flag during test. Note that the returned SafeCloseable
+ * must be closed to restore the original state
+ */
+ public static SafeCloseable overrideFlag(BooleanFlag flag, boolean value) {
+ Predicate<BooleanFlag> originalProxy = FeatureFlags.sBooleanReader;
+ Predicate<BooleanFlag> testProxy = f -> f == flag ? value : originalProxy.test(f);
+ FeatureFlags.sBooleanReader = testProxy;
+ return () -> {
+ if (FeatureFlags.sBooleanReader == testProxy) {
+ FeatureFlags.sBooleanReader = originalProxy;
+ }
+ };
+ }
+
+ /**
+ * Utility class to override a int flag during test. Note that the returned SafeCloseable
+ * must be closed to restore the original state
+ */
+ public static SafeCloseable overrideFlag(IntFlag flag, int value) {
+ ToIntFunction<IntFlag> originalProxy = FeatureFlags.sIntReader;
+ ToIntFunction<IntFlag> testProxy = f -> f == flag ? value : originalProxy.applyAsInt(f);
+ FeatureFlags.sIntReader = testProxy;
+ return () -> {
+ if (FeatureFlags.sIntReader == testProxy) {
+ FeatureFlags.sIntReader = originalProxy;
+ }
+ };
}
public static void uninstallDummyApp() throws IOException {
diff --git a/tests/src/com/android/launcher3/util/rule/TISBindRule.java b/tests/src/com/android/launcher3/util/rule/TISBindRule.java
new file mode 100644
index 0000000..3ec4a29
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/rule/TISBindRule.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util.rule;
+
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+public class TISBindRule implements TestRule {
+ public static String TAG = "TISBindRule";
+ public static String INTENT_FILTER = "android.intent.action.QUICKSTEP_SERVICE";
+ public static String TIS_PERMISSIONS = "android.permission.STATUS_BAR_SERVICE";
+
+ private String getLauncherPackageName(Context context) {
+ return ComponentName.unflattenFromString(context.getString(
+ com.android.internal.R.string.config_recentsComponentName)).getPackageName();
+ }
+
+ private ServiceConnection createConnection() {
+ return new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+ Log.d(TAG, "Connected to TouchInteractionService");
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ Log.d(TAG, "Disconnected from TouchInteractionService");
+ }
+ };
+ }
+
+ @NonNull
+ @Override
+ public Statement apply(@NonNull Statement base, @NonNull Description description) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final ServiceConnection connection = createConnection();
+ UiAutomation uiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ uiAutomation.adoptShellPermissionIdentity(TIS_PERMISSIONS);
+ Intent launchIntent = new Intent(INTENT_FILTER);
+ launchIntent.setPackage(getLauncherPackageName(context));
+ context.bindService(launchIntent, connection, Context.BIND_AUTO_CREATE);
+ uiAutomation.dropShellPermissionIdentity();
+ try {
+ base.evaluate();
+ } finally {
+ context.unbindService(connection);
+ }
+ }
+ };
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java b/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java
new file mode 100644
index 0000000..0931cd4
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsQsb.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on AllApp screen qsb.
+ */
+class AllAppsQsb extends Qsb {
+
+ private final UiObject2 mAllAppsContainer;
+
+ AllAppsQsb(LauncherInstrumentation launcher, UiObject2 allAppsContainer) {
+ super(launcher);
+ mAllAppsContainer = allAppsContainer;
+ waitForQsbObject();
+ }
+
+ @Override
+ protected UiObject2 waitForQsbObject() {
+ return mLauncher.waitForObjectInContainer(mAllAppsContainer, "search_container_all_apps");
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
index 82d9630..667290f 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
@@ -54,5 +54,14 @@
return createMenuItem(menuItem);
}
+ /**
+ * Returns a menu item that matches the text "Split screen". Fails if it doesn't exist.
+ */
+ public SplitScreenMenuItem getSplitScreenMenuItem() {
+ final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
+ AppIcon.getAppIconSelector("Split screen", mLauncher));
+ return new SplitScreenMenuItem(mLauncher, menuItem);
+ }
+
protected abstract AppIconMenuItem createMenuItem(UiObject2 menuItem);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
index e0c4c19..44de65a 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
@@ -109,4 +109,13 @@
}
}
}
+
+ /**
+ * Return the QSB UI object on the AllApps screen.
+ * @return the QSB UI object.
+ */
+ @NonNull
+ public Qsb getQsb() {
+ return new AllAppsQsb(mLauncher, verifyActiveContainer());
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
index c365708..20d09a1 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeQsb.java
@@ -15,69 +15,23 @@
*/
package com.android.launcher3.tapl;
-import androidx.annotation.NonNull;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
/**
- * Operations on home screen qsb.
+ * Operations on Home screen qsb.
*/
-public class HomeQsb {
+class HomeQsb extends Qsb {
- private final LauncherInstrumentation mLauncher;
- private static final String ASSISTANT_APP_PACKAGE = "com.google.android.googlequicksearchbox";
- private static final String ASSISTANT_ICON_RES_ID = "mic_icon";
+ private final UiObject2 mHotSeat;
-
- HomeQsb(LauncherInstrumentation launcher) {
- mLauncher = launcher;
- mLauncher.waitForLauncherObject("search_container_hotseat");
+ HomeQsb(LauncherInstrumentation launcher, UiObject2 hotseat) {
+ super(launcher);
+ mHotSeat = hotseat;
+ waitForQsbObject();
}
- /**
- * Launch assistant app by tapping mic icon on qsb.
- */
- @NonNull
- public LaunchedAppState launchAssistant() {
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to click assistant mic icon button");
- LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- UiObject2 assistantIcon = mLauncher.waitForLauncherObject(ASSISTANT_ICON_RES_ID);
-
- LauncherInstrumentation.log("HomeQsb.launchAssistant before click "
- + assistantIcon.getVisibleCenter() + " in "
- + mLauncher.getVisibleBounds(assistantIcon));
-
- mLauncher.clickLauncherObject(assistantIcon);
-
- try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
- // assert Assistant App Launched
- BySelector selector = By.pkg(ASSISTANT_APP_PACKAGE);
- mLauncher.assertTrue(
- "assistant app didn't start: (" + selector + ")",
- mLauncher.getDevice().wait(Until.hasObject(selector),
- LauncherInstrumentation.WAIT_TIME_MS)
- );
- return new LaunchedAppState(mLauncher);
- }
- }
- }
-
- /**
- * Show search result page from tapping qsb.
- */
- public SearchResultFromQsb showSearchResult() {
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "want to open search result page");
- LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- mLauncher.clickLauncherObject(
- mLauncher.waitForLauncherObject("search_container_hotseat"));
- try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
- "clicked qsb to open search result page")) {
- return new SearchResultFromQsb(mLauncher);
- }
- }
+ @Override
+ protected UiObject2 waitForQsbObject() {
+ return mLauncher.waitForObjectInContainer(mHotSeat, "search_container_hotseat");
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 3dcb437..48e327f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -76,6 +76,27 @@
}
}
+ /**
+ * Clicks a launcher object to initiate splitscreen, where the selected app will be one of two
+ * apps running on the screen. Should be called when Launcher is in a "split staging" state
+ * and is waiting for the user's selection of a second app. Expects a SPLIT_START_EVENT to be
+ * fired when the click is executed.
+ */
+ public LaunchedAppState launchIntoSplitScreen() {
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "want to launch split tasks from " + launchableType())) {
+ LauncherInstrumentation.log("Launchable.launch before click "
+ + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
+
+ mLauncher.clickLauncherObject(mObject);
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_START_EVENT);
+ return new LaunchedAppState(mLauncher);
+ }
+ }
+ }
+
protected LaunchedAppState assertAppLaunched(BySelector selector) {
mLauncher.assertTrue(
"App didn't start: (" + selector + ")",
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index adc993d..90f3d13 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -37,10 +37,9 @@
public final class OverviewTask {
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
- static final Pattern TASK_START_EVENT =
- Pattern.compile("startActivityFromRecentsAsync");
- static final Pattern SPLIT_START_EVENT =
- Pattern.compile("launchSplitTasks");
+ static final Pattern TASK_START_EVENT = Pattern.compile("startActivityFromRecentsAsync");
+ static final Pattern SPLIT_SELECT_EVENT = Pattern.compile("enterSplitSelect");
+ static final Pattern SPLIT_START_EVENT = Pattern.compile("launchSplitTasks");
private final LauncherInstrumentation mLauncher;
private final UiObject2 mTask;
private final BaseOverview mOverview;
diff --git a/tests/tapl/com/android/launcher3/tapl/Qsb.java b/tests/tapl/com/android/launcher3/tapl/Qsb.java
new file mode 100644
index 0000000..6bc4f21
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/Qsb.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.tapl;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
+/**
+ * Operations on qsb from either Home screen or AllApp screen.
+ */
+public abstract class Qsb {
+
+ private static final String ASSISTANT_APP_PACKAGE = "com.google.android.googlequicksearchbox";
+ private static final String ASSISTANT_ICON_RES_ID = "mic_icon";
+ protected final LauncherInstrumentation mLauncher;
+
+ protected Qsb(LauncherInstrumentation launcher) {
+ mLauncher = launcher;
+ }
+
+ // Waits for the quick search box.
+ protected abstract UiObject2 waitForQsbObject();
+ /**
+ * Launch assistant app by tapping mic icon on qsb.
+ */
+
+ @NonNull
+ public LaunchedAppState launchAssistant() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to click assistant mic icon button");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ UiObject2 assistantIcon = mLauncher.waitForLauncherObject(ASSISTANT_ICON_RES_ID);
+
+ LauncherInstrumentation.log("Qsb.launchAssistant before click "
+ + assistantIcon.getVisibleCenter() + " in "
+ + mLauncher.getVisibleBounds(assistantIcon));
+
+ mLauncher.clickLauncherObject(assistantIcon);
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ // assert Assistant App Launched
+ BySelector selector = By.pkg(ASSISTANT_APP_PACKAGE);
+ mLauncher.assertTrue(
+ "assistant app didn't start: (" + selector + ")",
+ mLauncher.getDevice().wait(Until.hasObject(selector),
+ LauncherInstrumentation.WAIT_TIME_MS)
+ );
+ return new LaunchedAppState(mLauncher);
+ }
+ }
+ }
+
+ /**
+ * Show search result page from tapping qsb.
+ */
+ public SearchResultFromQsb showSearchResult() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "want to open search result page");
+ LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+ mLauncher.clickLauncherObject(waitForQsbObject());
+ // wait for the result rendering to complete
+ mLauncher.waitForIdle();
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer(
+ "clicked qsb to open search result page")) {
+ return new SearchResultFromQsb(mLauncher);
+ }
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index 80e4116..80176e9 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -23,7 +23,7 @@
import java.util.ArrayList;
/**
- * Operations on search result page opened from home screen qsb.
+ * Operations on search result page opened from qsb.
*/
public class SearchResultFromQsb {
// The input resource id in the search box.
diff --git a/tests/tapl/com/android/launcher3/tapl/SplitScreenMenuItem.java b/tests/tapl/com/android/launcher3/tapl/SplitScreenMenuItem.java
new file mode 100644
index 0000000..47cf20b
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SplitScreenMenuItem.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.launcher3.testing.shared.TestProtocol;
+
+/**
+ * A class representing the "Split screen" menu item in the app long-press menu. Used for TAPL
+ * testing in a similar way as other menu items {@link AppIconMenuItem}, but unlike AppIconMenuItem,
+ * the split screen command does not trigger an app launch. Instead, it causes Launcher to shift to
+ * a different state (OverviewSplitSelect).
+ */
+public final class SplitScreenMenuItem {
+ private final LauncherInstrumentation mLauncher;
+ private final UiObject2 mObject;
+
+ SplitScreenMenuItem(LauncherInstrumentation launcher, UiObject2 object) {
+ mLauncher = launcher;
+ mObject = object;
+ }
+
+ /**
+ * Executes a click command on this menu item. Expects a SPLIT_SELECT_EVENT to be fired.
+ */
+ public void click() {
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+ "want to enter split select from app long-press menu")) {
+ LauncherInstrumentation.log("clicking on split screen menu item "
+ + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
+
+ mLauncher.clickLauncherObject(mObject);
+
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_SELECT_EVENT);
+ mLauncher.waitForLauncherObject("split_placeholder");
+ }
+ }
+ }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 0197a11..1939dc6 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -119,10 +119,11 @@
*
* The qsb must already be visible when calling this method.
*/
- public HomeQsb getQsb() {
+ @NonNull
+ public Qsb getQsb() {
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"want to get the home qsb")) {
- return new HomeQsb(mLauncher);
+ return new HomeQsb(mLauncher, mHotseat);
}
}