Merge "Animated fullscreen and desktop carousel attaching together" into main
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 38af572..9fb5b7b 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -433,3 +433,14 @@
description: "Enables tracking active gesture logs in ProtoLog"
bug: "293182501"
}
+
+
+flag {
+ name: "coordinate_workspace_scale"
+ namespace: "launcher"
+ description: "Ensure that the workspace and hotseat scale doesn't conflict and transitions smoothly between launching and closing apps"
+ bug: "366403487"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 28bd69a..0848ddd 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"ሁልጊዜ የተግባር አሞሌ ያሳዩ"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"የአሰሳ ሁነታን ይለውጡ"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"የተግባር አሞሌ አካፋይ"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"የተግባር አሞሌ ትርፍ ፍሰት"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ወደ ላይ/ግራ ይውሰዱ"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ወደ ታች/ቀኝ ይውሰዱ"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{ተጨማሪ መተግበሪያ}one{ተጨማሪ መተግበሪያ}other{ተጨማሪ መተግበሪያዎች}}"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index f08cf83..aa16f3c 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Uvek prikazuj traku zadataka"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Promeni režim navigacije"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdelnik trake zadataka"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Preklopna traka zadataka"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premesti gore levo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premesti dole desno"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}few{dodatne aplikacije}other{dodatnih aplikacija}}"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index fb5b556..4dcfe62 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Заўсёды паказваць панэль задач"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Змяніць рэжым навігацыі"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Раздзяляльнік панэлі задач"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Меню з пашырэннем панэлі задач"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Перамясціць уверх/улева"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{даступная праграма}one{даступная праграма}few{даступныя праграмы}many{даступных праграм}other{даступнай праграмы}}"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 6588dd0..3357a6e 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdjelnik trake zadataka"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Dodatni izbornik trake sa zadacima"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore lijevo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje desno"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}few{dodatne aplikacije}other{dodatnih aplikacija}}"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 527bdc3..d8bbc55 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Barra de tareas visible"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Cambiar el modo de navegación"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor de Barra de Tareas"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Barra de tareas ampliada"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover arriba/a la izquierda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover abajo/a la derecha"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{aplicación más}other{aplicaciones más}}"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index a2bf691..2514aa1 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Uvijek prikaži traku zadataka"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Promijeni način navigacije"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdjelnik trake sa zadacima"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Dodatni izbornik trake sa zadacima"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premjesti gore/lijevo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje/desno"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}few{dodatne aplikacije}other{dodatnih aplikacija}}"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 274e1da..3aec0ce 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Alltaf sýna forritastiku"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Breyta leiðsagnarstillingu"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Skipting forritastiku"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Yfirflæði á forritastiku"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Færa efst/til vinstri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Færa neðst/til hægri"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{forrit til viðbótar}one{forrit til viðbótar}other{forrit til viðbótar}}"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 0cff4c1..28b7746 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"常にタスクバーを表示する"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"ナビゲーション モードを変更"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"タスクバーの区切り"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"タスクバーのオーバフロー"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"上 / 左に移動"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"下 / 右に移動"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{個のその他のアプリ}other{個のその他のアプリ}}"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index efff980..d84d53e 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"ამოცანათა ზოლის მუდამ ჩვენება"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"შეცვალეთ ნავიგაციის რეჟიმი"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ამოცანათა ზოლის გამყოფი"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"ამოცანათა ზოლის გადავსება"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ზემოთ/მარცხნივ გადატანა"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ქვემოთ/მარჯვნივ გადატანა"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{სხვა აპი}other{სხვა აპი}}"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 193b606..4cdbfc4 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Тапсырма жолағын үнемі көрсету"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Навигация режимін өзгерту"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Тапсырмалар жолағын бөлгіш"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"\"Тапсырмалар жолағы\" қосымша мәзірі"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жоғары/солға жылжыту"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{қосымша қолданба}other{қосымша қолданба}}"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index aadfd67..5cf1b92 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"បង្ហាញរបារកិច្ចការជានិច្ច"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"ប្ដូរមុខងាររុករក"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"បន្ទាត់ខណ្ឌចែករបារកិច្ចការ"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"ម៉ឺនុយបន្ថែមរបារកិច្ចការ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ផ្លាស់ទីទៅខាងលើ/ឆ្វេង"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{កម្មវិធីច្រើនទៀត}other{កម្មវិធីច្រើនទៀត}}"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 8eba2a5..faf5675 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Такта ар дайым көрүнсүн"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Өтүү режимин өзгөртүү"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Тапшырмалар панелин бөлгүч"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"\"Тапшырмалар панели\" кошумча менюсу"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Жогорку/сол бурчка жылдыруу"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмөнкү/оң бурчка жылдыруу"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{колдонмо бар}other{колдонмо бар}}"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 1c20015..a95249b 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Visada rodyti užduočių juostą"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Keisti naršymo režimą"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Užduočių juostos daliklis"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Užduočių juostos perpildymas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Perkelti aukštyn, kairėn"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Perkelti žemyn, dešinėn"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{papildoma programa}one{papildoma programa}few{papildomos programos}many{papildomos programos}other{papildomų programų}}"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index bb5c014..c15a241 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"ടാസ്ക്ബാർ എപ്പോഴും കാണിക്കൂ"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"നാവിഗേഷൻ മോഡ് മാറ്റുക"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"ടാസ്ക്ബാർ ഡിവൈഡർ"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"ടാസ്ക്ബാർ ഓവർഫ്ലോ"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"മുകളിലേക്കോ ഇടത്തേക്കോ നീക്കുക"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"താഴേക്കോ വലത്തേക്കോ നീക്കുക"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{കൂടുതൽ ആപ്പ്}other{കൂടുതൽ ആപ്പുകൾ}}"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 9bdc973..a1f19a9 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Papar Bar Tugas selalu"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Tukar mod navigasi"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Pembahagi Bar Tugas"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Limpahan Bar Tugas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Alihkan ke atas/kiri"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Alihkan ke bawah/kanan"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{apl lagi}other{apl lagi}}"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 4c9747f..a2d4d32 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"टास्कबार सधैँ देखाउनुहोस्"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"नेभिगेसन मोड बदल्नुहोस्"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"टास्कबार डिभाइडर"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"टास्कबार ओभरफ्लो"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"सिरान/बायाँतिर सार्नुहोस्"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"फेद/दायाँतिर सार्नुहोस्"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{थप एप}other{थप एपहरू}}"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 5ad32af..2167875 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Ver sempre Barra de tarefas"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Alterar modo de navegação"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Divisor da Barra de tarefas"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Menu adicional da Barra de tarefas"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para a parte superior esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para a part superior direita"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{outra app}other{outras apps}}"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 28b3414..9309810 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Sempre mostrar a Barra de tarefas"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Mudar o modo de navegação"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Separador da Barra de tarefas"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Barra de tarefas flutuante"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Mover para cima/para a esquerda"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para baixo/para a direita"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{outro app}one{outro app}other{outros apps}}"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 20f579d..76c4e1f 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Всегда показывать панель задач"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Изменить режим навигации"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделитель панели задач"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Дополнительное меню панели задач"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Переместить вверх или влево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Переместить вниз или вправо"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{дополнительное приложение}one{дополнительное приложение}few{дополнительных приложения}many{дополнительных приложений}other{дополнительного приложения}}"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index dd9739c..0953b38 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"සෑම විටම කාර්ය තීරුව පෙන්වන්න"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"සංචාලන ප්රකාරය වෙනස් කරන්න"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"කාර්ය තීරු බෙදනය"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"කාර්ය තීරුව පිටාර යාම"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ඉහළ/වම වෙත ගෙන යන්න"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"පහළ/දකුණ වෙත ගෙන යන්න"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{තව යෙදුම}one{තවත් යෙදුම්}other{තවත් යෙදුම්}}"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 9394a5a..94de1e05 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Stalen prikaz oprav. vrstice"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Spreminjanje načina navigacije"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Razdelilnik opravilne vrstice"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Oblaček opravilne vrstice z dodatnimi elementi"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Premakni na vrh/levo"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premakni na dno/desno"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{dodatna aplikacija}one{dodatna aplikacija}two{dodatni aplikaciji}few{dodatne aplikacije}other{dodatnih aplikacij}}"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index a7760b9..d6e5d03 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Увек приказуј траку задатака"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Промени режим навигације"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Разделник траке задатака"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Преклопна трака задатака"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Премести горе лево"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести доле десно"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{додатна апликација}one{додатна апликација}few{додатне апликације}other{додатних апликација}}"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index d4c3a69..bba98c6 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"Visa alltid aktivitetsfältet"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"Ändra navigeringsläge"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"Avdelare för aktivitetsfältet"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"Fler alternativ för aktivitetsfältet"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"Flytta högst upp/till vänster"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytta längst ned/till höger"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{app till}other{appar till}}"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 86161b4..91ef846 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -139,8 +139,7 @@
<string name="always_show_taskbar" msgid="3608801276107751229">"టాస్క్బార్ను నిరంతరం చూపండి"</string>
<string name="change_navigation_mode" msgid="9088393078736808968">"నావిగేషన్ మోడ్ను మార్చండి"</string>
<string name="taskbar_divider_a11y_title" msgid="6608690309720242080">"టాస్క్బార్ డివైడర్"</string>
- <!-- no translation found for taskbar_overflow_a11y_title (7960342079198820179) -->
- <skip />
+ <string name="taskbar_overflow_a11y_title" msgid="7960342079198820179">"టాస్క్బార్ ఓవర్ఫ్లో"</string>
<string name="move_drop_target_top_or_left" msgid="2988702185049595807">"ఎగువ/ఎడమ వైపునకు తరలించండి"</string>
<string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"దిగువ/కుడి వైపునకు తరలించండి"</string>
<string name="quick_switch_overflow" msgid="3679780650881041632">"{count,plural, =1{మరో యాప్}other{మరిన్ని యాప్లు}}"</string>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index a64936d..18337d3 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -116,6 +116,7 @@
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
+import com.android.app.animation.Animations;
import com.android.internal.jank.Cuj;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
@@ -574,23 +575,45 @@
} else {
List<View> viewsToAnimate = new ArrayList<>();
Workspace<?> workspace = mLauncher.getWorkspace();
- workspace.forEachVisiblePage(
- view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets()));
+ if (Flags.coordinateWorkspaceScale()) {
+ viewsToAnimate.add(workspace);
+ } else {
+ workspace.forEachVisiblePage(
+ view -> viewsToAnimate.add(((CellLayout) view).getShortcutsAndWidgets()));
+ }
+ Hotseat hotseat = mLauncher.getHotseat();
// Do not scale hotseat as a whole when taskbar is present, and scale QSB only if it's
// not inline.
if (mDeviceProfile.isTaskbarPresent) {
if (!mDeviceProfile.isQsbInline) {
- viewsToAnimate.add(mLauncher.getHotseat().getQsb());
+ viewsToAnimate.add(hotseat.getQsb());
}
} else {
- viewsToAnimate.add(mLauncher.getHotseat());
+ viewsToAnimate.add(hotseat);
}
viewsToAnimate.forEach(view -> {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, SCALE_PROPERTY, scales)
+ float[] scale = scales;
+ if (Flags.coordinateWorkspaceScale()) {
+ // Start the animation from the current value, instead of assuming the views are
+ // in their resting state, so interrupted animations merge seamlessly.
+ // TODO(b/367591368): ideally these animations would be refactored to be
+ // controlled centrally so each instances doesn't need to care about this
+ // coordination.
+ scale = new float[]{view.getScaleX(), scales[1]};
+
+ // Cancel any ongoing animations. This is necessary to avoid a conflict between
+ // e.g. the unfinished animation triggered when closing an app back to Home and
+ // this animation caused by a launch.
+ Animations.Companion.cancelOngoingAnimation(view);
+ // Make sure to cache the current animation, so it can be properly interrupted.
+ Animations.Companion.setOngoingAnimation(view, launcherAnimator);
+ }
+
+ ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, SCALE_PROPERTY, scale)
.setDuration(CONTENT_SCALE_DURATION);
scaleAnim.setInterpolator(DECELERATE_1_5);
launcherAnimator.play(scaleAnim);
@@ -600,6 +623,11 @@
viewsToAnimate.forEach(view -> {
SCALE_PROPERTY.set(view, 1f);
view.setLayerType(View.LAYER_TYPE_NONE, null);
+
+ if (Flags.coordinateWorkspaceScale()) {
+ // Reset the cached animation.
+ Animations.Companion.setOngoingAnimation(view, null /* animation */);
+ }
});
mLauncher.resumeExpensiveViewUpdates();
};
@@ -1353,8 +1381,13 @@
? null
: mLauncher.getTaskbarUIController().findMatchingView(launcherView),
true /* hideOriginal */, targetRect, false /* isOpening */);
- isInHotseat = launcherView.getTag() instanceof ItemInfo
- && ((ItemInfo) launcherView.getTag()).isInHotseat();
+ if (launcherView.getTag() instanceof ItemInfo itemInfo) {
+ isInHotseat = itemInfo.isInHotseat();
+ if (isInHotseat) {
+ int dx = mLauncher.getHotseatItemTranslationX(itemInfo);
+ targetRect.offset(dx, 0);
+ }
+ }
} else {
targetRect.set(getDefaultWindowTargetRect());
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt b/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt
new file mode 100644
index 0000000..b8060e1
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
+import android.view.View
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.app.animation.Interpolators
+import com.android.launcher3.LauncherAnimUtils
+import com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X
+import com.android.launcher3.anim.SpringAnimationBuilder
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+
+/** Animator helper that creates bars animators. */
+object BarsLocationAnimatorHelper {
+
+ private const val FADE_OUT_ANIM_ALPHA_DURATION_MS: Long = 50L
+ private const val FADE_OUT_ANIM_ALPHA_DELAY_MS: Long = 50L
+ private const val FADE_OUT_ANIM_POSITION_DURATION_MS: Long = 100L
+ private const val FADE_IN_ANIM_ALPHA_DURATION_MS: Long = 100L
+
+ // Use STIFFNESS_MEDIUMLOW which is not defined in the API constants
+ private const val FADE_IN_ANIM_POSITION_SPRING_STIFFNESS: Float = 400f
+
+ // During fade out animation we shift the bubble bar 1/80th of the screen width
+ private const val FADE_OUT_ANIM_POSITION_SHIFT: Float = 1 / 80f
+
+ // During fade in animation we shift the bubble bar 1/60th of the screen width
+ private const val FADE_IN_ANIM_POSITION_SHIFT: Float = 1 / 60f
+
+ private val View.screenWidth: Int
+ get() = resources.displayMetrics.widthPixels
+
+ private val View.outShift: Float
+ get() = screenWidth * FADE_OUT_ANIM_POSITION_SHIFT
+
+ private val View.inShiftX: Float
+ get() = screenWidth * FADE_IN_ANIM_POSITION_SHIFT
+
+ /**
+ * Creates out animation for targetView that animates it finalTx and plays targetViewAlphaAnim
+ * to its final value.
+ */
+ private fun createLocationOutAnimator(
+ finalTx: Float,
+ targetViewAlphaAnim: ObjectAnimator,
+ targetView: View,
+ ): Animator {
+ val positionAnim =
+ ObjectAnimator.ofFloat(targetView, VIEW_TRANSLATE_X, finalTx)
+ .setDuration(FADE_OUT_ANIM_POSITION_DURATION_MS)
+ positionAnim.interpolator = Interpolators.EMPHASIZED_ACCELERATE
+
+ targetViewAlphaAnim.setDuration(FADE_OUT_ANIM_ALPHA_DURATION_MS)
+ targetViewAlphaAnim.startDelay = FADE_OUT_ANIM_ALPHA_DELAY_MS
+
+ val animatorSet = AnimatorSet()
+ animatorSet.playTogether(positionAnim, targetViewAlphaAnim)
+ return animatorSet
+ }
+
+ /**
+ * Creates in animation for targetView that animates it from startTx to finalTx and plays
+ * targetViewAlphaAnim to its final value.
+ */
+ private fun createLocationInAnimator(
+ startTx: Float,
+ finalTx: Float,
+ targetViewAlphaAnim: ObjectAnimator,
+ targetView: View,
+ ): Animator {
+ targetViewAlphaAnim.setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS)
+ val positionAnim: ValueAnimator =
+ SpringAnimationBuilder(targetView.context)
+ .setStartValue(startTx)
+ .setEndValue(finalTx)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+ .setStiffness(FADE_IN_ANIM_POSITION_SPRING_STIFFNESS)
+ .build(targetView, VIEW_TRANSLATE_X)
+ val animatorSet = AnimatorSet()
+ animatorSet.playTogether(positionAnim, targetViewAlphaAnim)
+ return animatorSet
+ }
+
+ /** Creates an animator for the bubble bar view in part. */
+ @JvmStatic
+ fun getBubbleBarLocationInAnimator(
+ newLocation: BubbleBarLocation,
+ currentLocation: BubbleBarLocation,
+ distanceFromOtherSide: Float,
+ targetViewAlphaAnim: ObjectAnimator,
+ bubbleBarView: View,
+ ): Animator {
+ val shift: Float = bubbleBarView.outShift
+
+ val onLeft = newLocation.isOnLeft(bubbleBarView.isLayoutRtl)
+ val startTx: Float
+ val finalTx =
+ if (newLocation == currentLocation) {
+ // Animated location matches layout location.
+ 0f
+ } else {
+ // We are animating in to a transient location, need to move the bar
+ // accordingly.
+ distanceFromOtherSide * (if (onLeft) -1 else 1)
+ }
+ startTx =
+ if (onLeft) {
+ // Bar will be shown on the left side. Start point is shifted right.
+ finalTx + shift
+ } else {
+ // Bar will be shown on the right side. Start point is shifted left.
+ finalTx - shift
+ }
+ return createLocationInAnimator(startTx, finalTx, targetViewAlphaAnim, bubbleBarView)
+ }
+
+ /** Creates an animator for the bubble bar view out part. */
+ @JvmStatic
+ fun getBubbleBarLocationOutAnimator(
+ bubbleBarView: View,
+ bubbleBarLocation: BubbleBarLocation,
+ targetViewAlphaAnim: ObjectAnimator,
+ ): Animator {
+ val onLeft = bubbleBarLocation.isOnLeft(bubbleBarView.isLayoutRtl)
+ val shift = bubbleBarView.outShift
+ val finalTx = bubbleBarView.translationX + (if (onLeft) -shift else shift)
+ return this.createLocationOutAnimator(finalTx, targetViewAlphaAnim, bubbleBarView)
+ }
+
+ /** Creates a teleport animator for the navigation buttons view. */
+ @JvmStatic
+ fun getTeleportAnimatorForNavButtons(
+ location: BubbleBarLocation,
+ navButtonsView: View,
+ navBarTargetTranslationX: Float,
+ ): Animator {
+ val outShift: Float = navButtonsView.outShift
+ val isNavBarOnRight: Boolean = location.isOnLeft(navButtonsView.isLayoutRtl)
+ val finalOutTx =
+ navButtonsView.translationX + (if (isNavBarOnRight) outShift else -outShift)
+ val fadeout: Animator =
+ createLocationOutAnimator(
+ finalOutTx,
+ ObjectAnimator.ofFloat(navButtonsView, LauncherAnimUtils.VIEW_ALPHA, 0f),
+ navButtonsView,
+ )
+ val inShift: Float = navButtonsView.inShiftX
+ val inStartX = navBarTargetTranslationX + (if (isNavBarOnRight) -inShift else inShift)
+ val fadeIn: Animator =
+ createLocationInAnimator(
+ inStartX,
+ navBarTargetTranslationX,
+ ObjectAnimator.ofFloat(navButtonsView, LauncherAnimUtils.VIEW_ALPHA, 1f),
+ navButtonsView,
+ )
+ val teleportAnimator = AnimatorSet()
+ teleportAnimator.play(fadeout).before(fadeIn)
+ return teleportAnimator
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 477f90c..10ff9ac 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -50,6 +50,7 @@
import com.android.quickstep.util.TISBindHelper;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import java.io.PrintWriter;
@@ -469,6 +470,18 @@
}
@Override
+ public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
+ mTaskbarLauncherStateController.onBubbleBarLocationChanged(location, /* animate = */ true);
+ mLauncher.setBubbleBarLocation(location);
+ }
+
+ @Override
+ public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
+ mTaskbarLauncherStateController.onBubbleBarLocationChanged(location, /* animate = */ false);
+ mLauncher.setBubbleBarLocation(location);
+ }
+
+ @Override
public void onSwipeToUnstashTaskbar() {
// Once taskbar is unstashed, the user cannot return back to the overlay. We can
// clear it here to set the expected state once the user goes home.
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 2ac5793..895535e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.LauncherAnimUtils.ROTATION_DRAWABLE_PERCENT;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
@@ -48,7 +49,9 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
+import static com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar;
+import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.DrawableRes;
@@ -175,6 +178,9 @@
/** Color to use for navigation bar buttons, if they are on on a Taskbar surface background. */
private final int mOnBackgroundIconColor;
+ private @Nullable Animator mNavBarLocationAnimator;
+ private @Nullable BubbleBarLocation mBubbleBarTargetLocation;
+
private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
this::updateNavButtonTranslationY);
private final AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay = new AnimatedFloat(
@@ -1174,14 +1180,30 @@
/** Adjusts navigation buttons layout accordingly to the bubble bar position. */
@Override
public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
+ cancelExistingNavBarAnimation();
+ mBubbleBarTargetLocation = location;
mNavButtonContainer.setTranslationX(getNavBarTranslationX(location));
+ mNavButtonContainer.setAlpha(1);
}
/** Animates navigation buttons accordingly to the bubble bar position. */
@Override
public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
- // TODO(b/346381754) add the teleport animation similarly to the bubble bar
- mNavButtonContainer.setTranslationX(getNavBarTranslationX(location));
+ cancelExistingNavBarAnimation();
+ mBubbleBarTargetLocation = location;
+ int finalX = getNavBarTranslationX(location);
+ Animator teleportAnimator = BarsLocationAnimatorHelper
+ .getTeleportAnimatorForNavButtons(location, mNavButtonContainer, finalX);
+ teleportAnimator.addListener(forEndCallback(() -> mNavBarLocationAnimator = null));
+ mNavBarLocationAnimator = teleportAnimator;
+ mNavBarLocationAnimator.start();
+ }
+
+ private void cancelExistingNavBarAnimation() {
+ if (mNavBarLocationAnimator != null) {
+ mNavBarLocationAnimator.cancel();
+ mNavBarLocationAnimator = null;
+ }
}
private int getNavBarTranslationX(BubbleBarLocation location) {
@@ -1218,12 +1240,16 @@
}
/** Adjusts the navigation buttons layout position according to the bubble bar location. */
- public void onTaskbarLayoutChange() {
- if (com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar()
+ public void onTaskbarLayoutChanged() {
+ if (mControllers.taskbarViewController.getIconLayoutBounds().isEmpty()) return;
+ if (enableBubbleBarInPersistentTaskBar()
&& mControllers.bubbleControllers.isPresent()) {
- BubbleBarLocation bubblesLocation = mControllers.bubbleControllers.get()
- .bubbleBarViewController.getBubbleBarLocation();
- onBubbleBarLocationUpdated(bubblesLocation);
+ if (mBubbleBarTargetLocation == null) {
+ // only set bubble bar location if it was not set before, e.g. at device boot
+ mBubbleBarTargetLocation = mControllers.bubbleControllers.get()
+ .bubbleBarViewController.getBubbleBarLocation();
+ }
+ onBubbleBarLocationUpdated(mBubbleBarTargetLocation);
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 56fd2bb..5974675 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -26,6 +26,7 @@
import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -219,7 +220,11 @@
uiController = newUiController;
uiController.init(this);
uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags);
-
+ bubbleControllers.ifPresent(bubbleControllers -> {
+ BubbleBarLocation location =
+ bubbleControllers.bubbleBarViewController.getBubbleBarLocation();
+ uiController.onBubbleBarLocationUpdated(location);
+ });
// Notify that the ui controller has changed
navbarButtonsViewController.onUiControllerChanged();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 876221b..065646a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -19,11 +19,14 @@
import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_ALIGNMENT;
import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_STASH;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
+import static com.android.launcher3.Utilities.isRtl;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_FOR_BUBBLES;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
+import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_IN_ANIM_ALPHA_DURATION_MS;
+import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_OUT_ANIM_POSITION_DURATION_MS;
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE;
@@ -42,8 +45,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Hotseat;
import com.android.launcher3.Hotseat.HotseatQsbAlphaId;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
@@ -62,6 +67,7 @@
import com.android.systemui.animation.ViewRootSync;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import java.io.PrintWriter;
import java.util.HashMap;
@@ -151,6 +157,7 @@
private AnimatedFloat mTaskbarAlpha;
private AnimatedFloat mTaskbarCornerRoundness;
private MultiProperty mTaskbarAlphaForHome;
+ private @Nullable Animator mHotseatTranslationXAnimation;
private QuickstepLauncher mLauncher;
private boolean mIsDestroyed = false;
@@ -168,6 +175,8 @@
private boolean mShouldDelayLauncherStateAnim;
+ private @Nullable BubbleBarLocation mBubbleBarLocation;
+
// We skip any view synchronizations during init/destroy.
private boolean mCanSyncViews;
@@ -185,6 +194,8 @@
mIsQsbInline = dp.isQsbInline;
TaskbarLauncherStateController.this.updateIconAlphaForHome(
mTaskbarAlphaForHome.getValue(), ALPHA_CHANNEL_TASKBAR_ALIGNMENT);
+ TaskbarLauncherStateController.this.onBubbleBarLocationChanged(
+ mBubbleBarLocation, /* animate = */ false);
}
};
@@ -833,6 +844,74 @@
}
}
+ /** Updates launcher home screen appearance accordingly to the bubble bar location. */
+ public void onBubbleBarLocationChanged(BubbleBarLocation location, boolean animate) {
+ DeviceProfile deviceProfile = mLauncher.getDeviceProfile();
+ if (mBubbleBarLocation == location) return;
+ mBubbleBarLocation = location;
+ if (!deviceProfile.shouldAdjustHotseatOnBubblesLocationUpdate(
+ mControllers.taskbarActivityContext)) {
+ return;
+ }
+ int targetX = 0;
+ if (mBubbleBarLocation != null) {
+ boolean isBubblesOnLeft = location.isOnLeft(isRtl(mLauncher.getResources()));
+ targetX = deviceProfile.getHotseatTranslationXForBubbleBar(/* isNavbarOnRight= */
+ isBubblesOnLeft);
+ }
+ updateHotseatAndQsbTranslationX(targetX, animate);
+ }
+
+ private void updateHotseatAndQsbTranslationX(float targetValue, boolean animate) {
+ // cancel existing animation
+ if (mHotseatTranslationXAnimation != null) {
+ mHotseatTranslationXAnimation.cancel();
+ }
+ Runnable alignTaskbar = new Runnable() {
+ @Override
+ public void run() {
+ // We only need to align the task bar when on launcher home screen
+ if (mControllers.taskbarStashController.isOnHome()) {
+ DeviceProfile dp = mLauncher.getDeviceProfile();
+ mControllers.taskbarViewController
+ .setLauncherIconAlignment(/* alignmentRatio = */ 1, dp);
+ }
+ }
+ };
+ Hotseat hotseat = mLauncher.getHotseat();
+ AnimatorSet translationXAnimation = new AnimatorSet();
+ MultiProperty iconsTranslationX = hotseat.getIconsTranslationX(
+ Hotseat.ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT);
+ if (animate) {
+ translationXAnimation.playTogether(iconsTranslationX.animateToValue(targetValue));
+ } else {
+ iconsTranslationX.setValue(targetValue);
+ }
+ float qsbTargetX = 0;
+ if (mIsQsbInline) {
+ qsbTargetX = targetValue;
+ }
+ MultiProperty qsbTranslationX = hotseat.getQsbTranslationX();
+ if (qsbTranslationX != null) {
+ if (animate) {
+ translationXAnimation.playTogether(qsbTranslationX.animateToValue(qsbTargetX));
+ } else {
+ qsbTranslationX.setValue(qsbTargetX);
+ }
+ }
+ if (!animate) {
+ alignTaskbar.run();
+ return;
+ }
+ mHotseatTranslationXAnimation = translationXAnimation;
+ translationXAnimation.setStartDelay(FADE_OUT_ANIM_POSITION_DURATION_MS);
+ translationXAnimation.setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS);
+ translationXAnimation.setInterpolator(Interpolators.EMPHASIZED);
+ translationXAnimation.addListener(AnimatorListeners.forEndCallback(alignTaskbar));
+ translationXAnimation.start();
+ }
+
+
private final class TaskBarRecentsAnimationListener implements
RecentsAnimationCallbacks.RecentsAnimationListener {
private final RecentsAnimationCallbacks mCallbacks;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index e39e904..6222e53 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -450,6 +450,11 @@
return hasAnyFlag(FLAG_IN_OVERVIEW);
}
+ /** Returns whether the taskbar is currently on launcher home screen. */
+ public boolean isOnHome() {
+ return !isInOverview() && !isInApp();
+ }
+
/** Returns whether taskbar is hidden for bubbles. */
public boolean isHiddenForBubbles() {
return hasAnyFlag(FLAG_STASHED_FOR_BUBBLES);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 9c8c2a9..b80aaf8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -36,6 +36,7 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.taskbar.bubbles.BubbleBarController;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.OverviewCommandHelper;
@@ -47,6 +48,7 @@
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import java.io.PrintWriter;
import java.util.Collections;
@@ -55,7 +57,7 @@
/**
* Base class for providing different taskbar UI
*/
-public class TaskbarUIController {
+public class TaskbarUIController implements BubbleBarController.BubbleBarLocationListener {
public static final TaskbarUIController DEFAULT = new TaskbarUIController();
// Initialized in init.
@@ -433,6 +435,14 @@
public void stashHotseat(boolean stash) {
}
+ @Override
+ public void onBubbleBarLocationAnimated(BubbleBarLocation location) {
+ }
+
+ @Override
+ public void onBubbleBarLocationUpdated(BubbleBarLocation location) {
+ }
+
/** Un-stash the hotseat instantly */
public void unStashHotseatInstantly() {
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 83527ab..b495e7d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -84,7 +84,6 @@
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
@@ -160,7 +159,7 @@
private final View.OnLayoutChangeListener mTaskbarViewLayoutChangeListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
updateTaskbarIconTranslationXForPinning();
- mControllers.navbarButtonsViewController.onTaskbarLayoutChange();
+ mControllers.navbarButtonsViewController.onTaskbarLayoutChanged();
};
// Animation to align icons with Launcher, created lazily. This allows the controller to be
@@ -834,6 +833,14 @@
: mPersistentTaskbarDp.taskbarBottomMargin;
int firstRecentTaskIndex = -1;
+ int hotseatNavBarTranslationX = 0;
+ if (mCurrentBubbleBarLocation != null
+ && taskbarDp.shouldAdjustHotseatOnBubblesLocationUpdate(mActivity)) {
+ boolean isBubblesOnLeft = mCurrentBubbleBarLocation.isOnLeft(
+ mTaskbarView.isLayoutRtl());
+ hotseatNavBarTranslationX = taskbarDp
+ .getHotseatTranslationXForBubbleBar(/* isNavbarOnRight = */ isBubblesOnLeft);
+ }
for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
View child = mTaskbarView.getChildAt(i);
boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonContainer();
@@ -869,16 +876,20 @@
: Interpolators.clampToProgress(LINEAR, 0.72f, 0.84f));
}
}
-
if (child == mTaskbarView.getQsb()) {
boolean isRtl = Utilities.isRtl(child.getResources());
float hotseatIconCenter = isRtl
? launcherDp.widthPx - hotseatPadding.right + borderSpacing
+ launcherDp.hotseatQsbWidth / 2f
: hotseatPadding.left - borderSpacing - launcherDp.hotseatQsbWidth / 2f;
+ if (taskbarDp.isQsbInline) {
+ hotseatIconCenter += hotseatNavBarTranslationX;
+ }
float childCenter = (child.getLeft() + child.getRight()) / 2f;
- childCenter += ((Reorderable) child).getTranslateDelegate().getTranslationX(
- INDEX_TASKBAR_PINNING_ANIM).getValue();
+ if (child instanceof Reorderable reorderableChild) {
+ childCenter += reorderableChild.getTranslateDelegate().getTranslationX(
+ INDEX_TASKBAR_PINNING_ANIM).getValue();
+ }
float halfQsbIconWidthDiff =
(launcherDp.hotseatQsbWidth - taskbarDp.taskbarIconSize) / 2f;
float scale = ((float) taskbarDp.taskbarIconSize)
@@ -887,8 +898,8 @@
float fromX = isRtl ? -halfQsbIconWidthDiff : halfQsbIconWidthDiff;
float toX = hotseatIconCenter - childCenter;
- if (child instanceof Reorderable) {
- MultiTranslateDelegate mtd = ((Reorderable) child).getTranslateDelegate();
+ if (child instanceof Reorderable reorderableChild) {
+ MultiTranslateDelegate mtd = reorderableChild.getTranslateDelegate();
setter.addFloat(mtd.getTranslationX(INDEX_TASKBAR_ALIGNMENT_ANIM),
MULTI_PROPERTY_VALUE, fromX, toX, interpolator);
@@ -935,6 +946,7 @@
+ (hotseatCellSize + borderSpacing) * positionInHotseat
+ hotseatCellSize / 2f;
}
+ hotseatIconCenter += hotseatNavBarTranslationX;
float childCenter = (child.getLeft() + child.getRight()) / 2f;
childCenter += ((Reorderable) child).getTranslateDelegate().getTranslationX(
INDEX_TASKBAR_PINNING_ANIM).getValue();
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 6860004..51e09ab 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -196,7 +196,8 @@
mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
key -> setSelectedBubbleInternal(mBubbles.get(key)));
mBubbleBarViewController.setBoundsChangeListener(this::onBubbleBarBoundsChanged);
-
+ mBubbleBarLocationListener.onBubbleBarLocationUpdated(
+ mBubbleBarViewController.getBubbleBarLocation());
if (sBubbleBarEnabled) {
mSystemUiProxy.setBubblesListener(this);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt
index a831fd7..bc562a6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeController.kt
@@ -21,10 +21,15 @@
import androidx.annotation.VisibleForTesting
import androidx.core.animation.doOnEnd
import androidx.dynamicanimation.animation.SpringForce
+import com.android.launcher3.R
import com.android.launcher3.anim.AnimatedFloat
import com.android.launcher3.anim.SpringAnimationBuilder
import com.android.launcher3.taskbar.TaskbarActivityContext
import com.android.launcher3.taskbar.TaskbarThresholdUtils
+import com.android.launcher3.taskbar.bubbles.BubbleBarSwipeController.StartState.COLLAPSED
+import com.android.launcher3.taskbar.bubbles.BubbleBarSwipeController.StartState.EXPANDED
+import com.android.launcher3.taskbar.bubbles.BubbleBarSwipeController.StartState.STASHED
+import com.android.launcher3.taskbar.bubbles.BubbleBarSwipeController.StartState.UNKNOWN
import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
import com.android.launcher3.touch.OverScroll
@@ -34,8 +39,8 @@
private val context: Context
private var bubbleStashedHandleViewController: BubbleStashedHandleViewController? = null
- private var bubbleBarViewController: BubbleBarViewController? = null
- private var bubbleStashController: BubbleStashController? = null
+ private lateinit var bubbleBarViewController: BubbleBarViewController
+ private lateinit var bubbleStashController: BubbleStashController
private var springAnimation: ValueAnimator? = null
private val animatedSwipeTranslation = AnimatedFloat(this::onSwipeUpdate)
@@ -43,6 +48,7 @@
private val unstashThreshold: Int
private val expandThreshold: Int
private val maxOverscroll: Int
+ private val stashThreshold: Int
private var swipeState: SwipeState = SwipeState()
@@ -54,6 +60,7 @@
unstashThreshold = dimensionProvider.unstashThreshold
expandThreshold = dimensionProvider.expandThreshold
maxOverscroll = dimensionProvider.maxOverscroll
+ stashThreshold = dimensionProvider.stashThreshold
}
fun init(bubbleControllers: BubbleControllers) {
@@ -66,23 +73,21 @@
/** Start tracking a new swipe gesture */
fun start() {
if (springAnimation != null) reset()
- val stashed = bubbleStashController?.isStashed ?: false
- val barVisible = bubbleStashController?.isBubbleBarVisible() ?: false
- val expanded = bubbleBarViewController?.isExpanded ?: false
-
- swipeState =
- SwipeState(
- stashedOnStart = stashed,
- collapsedOnStart = !stashed && barVisible && !expanded,
- expandedOnStart = expanded,
- )
+ val startState =
+ when {
+ bubbleStashController.isStashed -> STASHED
+ bubbleBarViewController.isExpanded -> EXPANDED
+ bubbleStashController.isBubbleBarVisible() -> COLLAPSED
+ else -> UNKNOWN
+ }
+ swipeState = SwipeState(startState = startState)
}
/** Update swipe distance to [dy] */
fun swipeTo(dy: Float) {
- // Only handle swipe up and stashed or collapsed bar
- if (dy > 0 || swipeState.expandedOnStart) return
-
+ if (!canHandleSwipe(dy)) {
+ return
+ }
animatedSwipeTranslation.updateValue(dy)
val prevState = swipeState
@@ -90,38 +95,63 @@
val passedUnstashThreshold = isUnstash(dy) || prevState.passedUnstashThreshold
// Expand happens at the end of the gesture, always keep the current value
val passedExpandThreshold = isExpand(dy)
+ // Stash happens at the end of the gesture, always keep the current value
+ val passedStashThreshold = isStash(dy)
if (
passedUnstashThreshold != prevState.passedUnstashThreshold ||
- passedExpandThreshold != prevState.passedExpandThreshold
+ passedExpandThreshold != prevState.passedExpandThreshold ||
+ passedStashThreshold != prevState.passedStashThreshold
) {
swipeState =
swipeState.copy(
passedUnstashThreshold = passedUnstashThreshold,
passedExpandThreshold = passedExpandThreshold,
+ passedStashThreshold = passedStashThreshold,
)
}
if (
- swipeState.stashedOnStart &&
+ swipeState.startState == STASHED &&
swipeState.passedUnstashThreshold &&
!prevState.passedUnstashThreshold
) {
- bubbleStashController?.showBubbleBar(expandBubbles = false)
+ bubbleStashController.showBubbleBar(expandBubbles = false)
}
}
/** Finish tracking swipe gesture. Animate views back to resting state */
fun finish() {
- if (swipeState.passedExpandThreshold) {
- bubbleStashController?.showBubbleBar(expandBubbles = true)
+ when {
+ swipeState.passedExpandThreshold &&
+ swipeState.startState in setOf(STASHED, COLLAPSED) -> {
+ bubbleStashController.showBubbleBar(expandBubbles = true)
+ }
+ swipeState.passedStashThreshold && swipeState.startState == COLLAPSED -> {
+ bubbleStashController.stashBubbleBar()
+ }
}
- springToRest()
+ if (animatedSwipeTranslation.value == 0f) {
+ reset()
+ } else {
+ springToRest()
+ }
}
/** Returns `true` if we are tracking a swipe gesture */
fun isSwipeGesture(): Boolean {
- return swipeState.passedUnstashThreshold || swipeState.passedExpandThreshold
+ return swipeState.passedUnstashThreshold ||
+ swipeState.passedExpandThreshold ||
+ swipeState.passedStashThreshold
+ }
+
+ private fun canHandleSwipe(dy: Float): Boolean {
+ return when (swipeState.startState) {
+ STASHED -> dy < 0 // stashed bar only handles swipe up
+ COLLAPSED -> true // collapsed bar can be swiped in either direction
+ UNKNOWN,
+ EXPANDED -> false // expanded bar can't be swiped
+ }
}
private fun isUnstash(dy: Float): Boolean {
@@ -132,6 +162,10 @@
return dy < -expandThreshold
}
+ private fun isStash(dy: Float): Boolean {
+ return dy > stashThreshold
+ }
+
private fun reset() {
springAnimation?.let {
if (it.isRunning) {
@@ -147,7 +181,7 @@
private fun onSwipeUpdate(value: Float) {
val dampedSwipe = -OverScroll.dampedScroll(-value, maxOverscroll).toFloat()
bubbleStashedHandleViewController?.setTranslationYForSwipe(dampedSwipe)
- bubbleBarViewController?.setTranslationYForSwipe(dampedSwipe)
+ bubbleBarViewController.setTranslationYForSwipe(dampedSwipe)
}
private fun springToRest() {
@@ -163,19 +197,26 @@
}
internal data class SwipeState(
- val stashedOnStart: Boolean = false,
- val collapsedOnStart: Boolean = false,
- val expandedOnStart: Boolean = false,
+ val startState: StartState = UNKNOWN,
val passedUnstashThreshold: Boolean = false,
val passedExpandThreshold: Boolean = false,
+ val passedStashThreshold: Boolean = false,
)
+ internal enum class StartState {
+ UNKNOWN,
+ STASHED,
+ COLLAPSED,
+ EXPANDED,
+ }
+
/** Allows overriding the dimension provider for testing */
@VisibleForTesting
interface DimensionProvider {
val unstashThreshold: Int
val expandThreshold: Int
val maxOverscroll: Int
+ val stashThreshold: Int
}
private class DefaultDimensionProvider(taskbarActivityContext: TaskbarActivityContext) :
@@ -183,6 +224,7 @@
override val unstashThreshold: Int
override val expandThreshold: Int
override val maxOverscroll: Int
+ override val stashThreshold: Int
init {
val resources = taskbarActivityContext.resources
@@ -198,6 +240,7 @@
taskbarActivityContext.deviceProfile,
)
maxOverscroll = taskbarActivityContext.deviceProfile.heightPx - unstashThreshold
+ stashThreshold = resources.getDimensionPixelSize(R.dimen.taskbar_to_nav_threshold)
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index d454fd7..7fed381 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -15,13 +15,9 @@
*/
package com.android.launcher3.taskbar.bubbles;
-import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
@@ -42,10 +38,9 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
-import androidx.dynamicanimation.animation.SpringForce;
-
import com.android.launcher3.R;
-import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper;
import com.android.launcher3.taskbar.bubbles.animation.BubbleAnimator;
import com.android.launcher3.util.DisplayController;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
@@ -83,8 +78,9 @@
*/
public class BubbleBarView extends FrameLayout {
+ public static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
+ public static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
private static final String TAG = "BubbleBarView";
-
// TODO: (b/273594744) calculate the amount of space we have and base the max on that
// if it's smaller than 5.
private static final int MAX_BUBBLES = 5;
@@ -93,18 +89,6 @@
private static final int WIDTH_ANIMATION_DURATION_MS = 200;
private static final int SCALE_ANIMATION_DURATION_MS = 200;
- private static final long FADE_OUT_ANIM_ALPHA_DURATION_MS = 50L;
- private static final long FADE_OUT_ANIM_ALPHA_DELAY_MS = 50L;
- public static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
- // During fade out animation we shift the bubble bar 1/80th of the screen width
- private static final float FADE_OUT_ANIM_POSITION_SHIFT = 1 / 80f;
-
- public static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
- // Use STIFFNESS_MEDIUMLOW which is not defined in the API constants
- private static final float FADE_IN_ANIM_POSITION_SPRING_STIFFNESS = 400f;
- // During fade in animation we shift the bubble bar 1/60th of the screen width
- private static final float FADE_IN_ANIM_POSITION_SHIFT = 1 / 60f;
-
/**
* Custom property to set alpha value for the bar view while a bubble is being dragged.
* Skips applying alpha to the dragged bubble.
@@ -578,77 +562,30 @@
// First animator hides the bar.
// After it completes, bubble positions in the bar and arrow position is updated.
// Second animator is started to show the bar.
- mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator(bubbleBarLocation);
- mBubbleBarLocationAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- updateBubblesLayoutProperties(bubbleBarLocation);
- mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl()));
+ ObjectAnimator alphaOutAnim = ObjectAnimator.ofFloat(
+ this, getLocationAnimAlphaProperty(), 0f);
+ mBubbleBarLocationAnimator = BarsLocationAnimatorHelper.getBubbleBarLocationOutAnimator(
+ this,
+ bubbleBarLocation,
+ alphaOutAnim);
+ mBubbleBarLocationAnimator.addListener(AnimatorListeners.forEndCallback(() -> {
+ updateBubblesLayoutProperties(bubbleBarLocation);
+ mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl()));
+ ObjectAnimator alphaInAnim = ObjectAnimator.ofFloat(BubbleBarView.this,
+ getLocationAnimAlphaProperty(), 1f);
- // Animate it in
- mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator(bubbleBarLocation);
- mBubbleBarLocationAnimator.start();
- }
- });
+ // Animate it in
+ mBubbleBarLocationAnimator = BarsLocationAnimatorHelper.getBubbleBarLocationInAnimator(
+ bubbleBarLocation,
+ mBubbleBarLocation,
+ getDistanceFromOtherSide(),
+ alphaInAnim,
+ BubbleBarView.this);
+ mBubbleBarLocationAnimator.start();
+ }));
mBubbleBarLocationAnimator.start();
}
- private Animator getLocationUpdateFadeOutAnimator(BubbleBarLocation newLocation) {
- final float shift =
- getResources().getDisplayMetrics().widthPixels * FADE_OUT_ANIM_POSITION_SHIFT;
- final boolean onLeft = newLocation.isOnLeft(isLayoutRtl());
- final float tx = getTranslationX() + (onLeft ? -shift : shift);
-
- ObjectAnimator positionAnim = ObjectAnimator.ofFloat(this, VIEW_TRANSLATE_X, tx)
- .setDuration(FADE_OUT_ANIM_POSITION_DURATION_MS);
- positionAnim.setInterpolator(EMPHASIZED_ACCELERATE);
-
- ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, getLocationAnimAlphaProperty(), 0f)
- .setDuration(FADE_OUT_ANIM_ALPHA_DURATION_MS);
- alphaAnim.setStartDelay(FADE_OUT_ANIM_ALPHA_DELAY_MS);
-
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(positionAnim, alphaAnim);
- return animatorSet;
- }
-
- private Animator getLocationUpdateFadeInAnimator(BubbleBarLocation newLocation) {
- final float shift =
- getResources().getDisplayMetrics().widthPixels * FADE_IN_ANIM_POSITION_SHIFT;
-
- final boolean onLeft = newLocation.isOnLeft(isLayoutRtl());
- final float startTx;
- final float finalTx;
- if (newLocation == mBubbleBarLocation) {
- // Animated location matches layout location.
- finalTx = 0;
- } else {
- // We are animating in to a transient location, need to move the bar accordingly.
- finalTx = getDistanceFromOtherSide() * (onLeft ? -1 : 1);
- }
- if (onLeft) {
- // Bar will be shown on the left side. Start point is shifted right.
- startTx = finalTx + shift;
- } else {
- // Bar will be shown on the right side. Start point is shifted left.
- startTx = finalTx - shift;
- }
-
- ValueAnimator positionAnim = new SpringAnimationBuilder(getContext())
- .setStartValue(startTx)
- .setEndValue(finalTx)
- .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
- .setStiffness(FADE_IN_ANIM_POSITION_SPRING_STIFFNESS)
- .build(this, VIEW_TRANSLATE_X);
-
- ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, getLocationAnimAlphaProperty(), 1f)
- .setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS);
-
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(positionAnim, alphaAnim);
- return animatorSet;
- }
-
/**
* Get property that can be used to animate the alpha value for the bar.
* When a bubble is being dragged, uses {@link #BUBBLE_DRAG_ALPHA}.
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index 8230f42..b5d94bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -22,6 +22,7 @@
import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.taskbar.bubbles.BubbleBarViewController.TaskbarViewPropertiesProvider;
+import com.android.launcher3.taskbar.bubbles.stashing.BubbleBarLocationOnDemandListener;
import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.RunnableList;
@@ -79,11 +80,11 @@
* in constructors for now, as some controllers may still be waiting for init().
*/
public void init(TaskbarControllers taskbarControllers) {
- // TODO(b/346381754) add TaskbarLauncherStateController implementation to adjust the hotseat
BubbleBarLocationCompositeListener bubbleBarLocationListeners =
new BubbleBarLocationCompositeListener(
taskbarControllers.navbarButtonsViewController,
- taskbarControllers.taskbarViewController
+ taskbarControllers.taskbarViewController,
+ new BubbleBarLocationOnDemandListener(() -> taskbarControllers.uiController)
);
bubbleBarController.init(this,
bubbleBarLocationListeners,
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt
index 4939c99..49760ff 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutController.kt
@@ -19,6 +19,7 @@
import android.view.Gravity
import android.view.ViewGroup
import android.widget.FrameLayout
+import androidx.core.animation.ValueAnimator
import com.android.launcher3.R
/** Creates and manages the visibility of the [BubbleBarFlyoutView]. */
@@ -33,7 +34,7 @@
fun setUpFlyout(message: BubbleBarFlyoutMessage) {
flyout?.let(container::removeView)
- val flyout = BubbleBarFlyoutView(container.context, onLeft = positioner.isOnLeft)
+ val flyout = BubbleBarFlyoutView(container.context, positioner)
flyout.translationY = positioner.targetTy
@@ -47,7 +48,11 @@
lp.marginEnd = horizontalMargin
container.addView(flyout, lp)
- flyout.setData(message)
+ val animator = ValueAnimator.ofFloat(0f, 1f)
+ animator.addUpdateListener { _ ->
+ flyout.updateExpansionProgress(animator.animatedValue as Float)
+ }
+ flyout.showFromCollapsed(message) { animator.start() }
this.flyout = flyout
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt
index deed1f5..b8c1c7f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutPositioner.kt
@@ -16,6 +16,8 @@
package com.android.launcher3.taskbar.bubbles.flyout
+import android.graphics.PointF
+
/** Provides positioning data to the flyout view. */
interface BubbleBarFlyoutPositioner {
@@ -24,4 +26,17 @@
/** The target translation Y that the flyout view should have when displayed. */
val targetTy: Float
+
+ /**
+ * The distance between the expanded position of the flyout and the collapsed position.
+ *
+ * The distance is calculated between the bottom corner which is aligned with the bubble bar.
+ */
+ val distanceToCollapsedPosition: PointF
+
+ /** The size of the flyout when collapsed. */
+ val collapsedSize: Float
+
+ /** The color of the flyout when collapsed. */
+ val collapsedColor: Int
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt
index 4b91f46..6723f57 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutView.kt
@@ -20,19 +20,32 @@
import android.content.res.Configuration
import android.graphics.Canvas
import android.graphics.Color
+import android.graphics.Outline
import android.graphics.Paint
import android.graphics.Path
+import android.graphics.PointF
+import android.graphics.RectF
import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewOutlineProvider
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.animation.ArgbEvaluator
import com.android.launcher3.R
import com.android.launcher3.popup.RoundedArrowDrawable
/** The flyout view used to notify the user of a new bubble notification. */
-class BubbleBarFlyoutView(context: Context, private val onLeft: Boolean) :
+class BubbleBarFlyoutView(context: Context, private val positioner: BubbleBarFlyoutPositioner) :
ConstraintLayout(context) {
+ private companion object {
+ // the minimum progress of the expansion animation before the triangle is made visible.
+ const val MIN_EXPANSION_PROGRESS_FOR_TRIANGLE = 0.1f
+ // the minimum progress of the expansion animation before the content starts fading in.
+ const val MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA = 0.75f
+ }
+
private val sender: TextView by
lazy(LazyThreadSafetyMode.NONE) { findViewById(R.id.bubble_flyout_name) }
@@ -79,9 +92,34 @@
context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_max_width)
}
+ /** The bounds of the background rect. */
+ private val backgroundRect = RectF()
private val cornerRadius: Float
private val triangle: Path = Path()
+ private val triangleOutline = Outline()
private var backgroundColor = Color.BLACK
+ /** Represents the progress of the expansion animation. 0 when collapsed. 1 when expanded. */
+ private var expansionProgress = 0f
+ /** Translation x-y values to move the flyout to its collapsed position. */
+ private var translationToCollapsedPosition = PointF(0f, 0f)
+ /** The size of the flyout when it's collapsed. */
+ private var collapsedSize = 0f
+ /** The corner radius of the flyout when it's collapsed. */
+ private var collapsedCornerRadius = 0f
+ /** The color of the flyout when collapsed. */
+ private var collapsedColor = 0
+
+ /** The corner radius of the background according to the progress of the animation. */
+ private val currentCornerRadius
+ get() = collapsedCornerRadius + (cornerRadius - collapsedCornerRadius) * expansionProgress
+
+ /** Translation X of the background. */
+ private val backgroundRectTx
+ get() = translationToCollapsedPosition.x * (1 - expansionProgress)
+
+ /** Translation Y of the background. */
+ private val backgroundRectTy
+ get() = translationToCollapsedPosition.y * (1 - expansionProgress)
/**
* The paint used to draw the background, whose color changes as the flyout transitions to the
@@ -97,7 +135,7 @@
ta.recycle()
setWillNotDraw(false)
- clipChildren = false
+ clipChildren = true
clipToPadding = false
val padding = context.resources.getDimensionPixelSize(R.dimen.bubblebar_flyout_padding)
@@ -112,11 +150,45 @@
triangleRadius.toFloat(),
triangle,
)
+ triangleOutline.setPath(triangle)
+
+ outlineProvider =
+ object : ViewOutlineProvider() {
+ override fun getOutline(view: View, outline: Outline) {
+ this@BubbleBarFlyoutView.getOutline(outline)
+ }
+ }
+ clipToOutline = true
applyConfigurationColors(resources.configuration)
}
- fun setData(flyoutMessage: BubbleBarFlyoutMessage) {
+ /** Sets the data for the flyout and starts playing the expand animation. */
+ fun showFromCollapsed(flyoutMessage: BubbleBarFlyoutMessage, expandAnimation: () -> Unit) {
+ avatar.alpha = 0f
+ sender.alpha = 0f
+ message.alpha = 0f
+ setData(flyoutMessage)
+ val txToCollapsedPosition =
+ if (positioner.isOnLeft) {
+ positioner.distanceToCollapsedPosition.x
+ } else {
+ -positioner.distanceToCollapsedPosition.x
+ }
+ val tyToCollapsedPosition =
+ positioner.distanceToCollapsedPosition.y + triangleHeight - triangleOverlap
+ translationToCollapsedPosition = PointF(txToCollapsedPosition, tyToCollapsedPosition)
+
+ collapsedSize = positioner.collapsedSize
+ collapsedCornerRadius = collapsedSize / 2
+ collapsedColor = positioner.collapsedColor
+
+ // post the request to start the expand animation to the looper so the view can measure
+ // itself
+ post(expandAnimation)
+ }
+
+ private fun setData(flyoutMessage: BubbleBarFlyoutMessage) {
// the avatar is only displayed in group chat messages
if (flyoutMessage.senderAvatar != null && flyoutMessage.isGroupChat) {
avatar.visibility = VISIBLE
@@ -151,28 +223,111 @@
message.text = flyoutMessage.message
}
+ /** Updates the flyout view with the progress of the animation. */
+ fun updateExpansionProgress(fraction: Float) {
+ expansionProgress = fraction
+
+ updateTranslationForAnimation(message)
+ updateTranslationForAnimation(sender)
+ updateTranslationForAnimation(avatar)
+
+ // start fading in the content only after we're past the threshold
+ val alpha =
+ ((expansionProgress - MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA) /
+ (1f - MIN_EXPANSION_PROGRESS_FOR_CONTENT_ALPHA))
+ .coerceIn(0f, 1f)
+ sender.alpha = alpha
+ message.alpha = alpha
+ avatar.alpha = alpha
+
+ invalidate()
+ }
+
override fun onDraw(canvas: Canvas) {
- canvas.drawRoundRect(
- 0f,
- 0f,
- width.toFloat(),
+ // interpolate the width, height, corner radius and translation based on the progress of the
+ // animation.
+ // the background is drawn from the bottom left corner to the top right corner if we're
+ // positioned on the left, and from the bottom right corner to the top left if we're
+ // positioned on the right.
+
+ // the current width of the background rect according to the progress of the animation
+ val currentWidth = collapsedSize + (width - collapsedSize) * expansionProgress
+ val rectBottom = height - triangleHeight + triangleOverlap
+ val currentHeight = collapsedSize + (rectBottom - collapsedSize) * expansionProgress
+
+ backgroundRect.set(
+ if (positioner.isOnLeft) 0f else width.toFloat() - currentWidth,
+ height.toFloat() - triangleHeight + triangleOverlap - currentHeight,
+ if (positioner.isOnLeft) currentWidth else width.toFloat(),
height.toFloat() - triangleHeight + triangleOverlap,
- cornerRadius,
- cornerRadius,
+ )
+
+ backgroundPaint.color =
+ ArgbEvaluator.getInstance().evaluate(expansionProgress, collapsedColor, backgroundColor)
+
+ canvas.save()
+ canvas.translate(backgroundRectTx, backgroundRectTy)
+ // draw the background starting from the bottom left if we're positioned left, or the bottom
+ // right if we're positioned right.
+ canvas.drawRoundRect(
+ backgroundRect,
+ currentCornerRadius,
+ currentCornerRadius,
backgroundPaint,
)
- drawTriangle(canvas)
+ if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) {
+ drawTriangle(canvas)
+ }
+ canvas.restore()
+ invalidateOutline()
super.onDraw(canvas)
}
private fun drawTriangle(canvas: Canvas) {
canvas.save()
- val triangleX = if (onLeft) cornerRadius else width - cornerRadius - triangleWidth
- canvas.translate(triangleX, (height - triangleHeight).toFloat())
+ val triangleX =
+ if (positioner.isOnLeft) {
+ currentCornerRadius
+ } else {
+ width - currentCornerRadius - triangleWidth
+ }
+ // instead of scaling the triangle, increasingly reveal it from the background, starting
+ // with half the size. this has the effect of the triangle scaling.
+ val triangleY = height - triangleHeight - 0.5f * triangleHeight * (1 - expansionProgress)
+ canvas.translate(triangleX, triangleY)
canvas.drawPath(triangle, backgroundPaint)
+ triangleOutline.setPath(triangle)
+ triangleOutline.offset(triangleX.toInt(), triangleY.toInt())
canvas.restore()
}
+ private fun getOutline(outline: Outline) {
+ val path = Path()
+ path.addRoundRect(
+ backgroundRect,
+ currentCornerRadius,
+ currentCornerRadius,
+ Path.Direction.CW,
+ )
+ if (expansionProgress >= MIN_EXPANSION_PROGRESS_FOR_TRIANGLE) {
+ path.addPath(triangleOutline.mPath)
+ }
+ outline.setPath(path)
+ outline.offset(backgroundRectTx.toInt(), backgroundRectTy.toInt())
+ }
+
+ private fun updateTranslationForAnimation(view: View) {
+ val tx =
+ if (positioner.isOnLeft) {
+ translationToCollapsedPosition.x - view.left
+ } else {
+ width - view.left - translationToCollapsedPosition.x
+ }
+ val ty = height - view.top + translationToCollapsedPosition.y
+ view.translationX = tx * (1f - expansionProgress)
+ view.translationY = ty * (1f - expansionProgress)
+ }
+
private fun applyConfigurationColors(configuration: Configuration) {
val nightModeFlags = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
val isNightModeOn = nightModeFlags == Configuration.UI_MODE_NIGHT_YES
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleBarLocationOnDemandListener.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleBarLocationOnDemandListener.kt
new file mode 100644
index 0000000..ffe7c44
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleBarLocationOnDemandListener.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.stashing
+
+import com.android.launcher3.taskbar.bubbles.BubbleBarController.BubbleBarLocationListener
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+
+/** On demand implementation of [BubbleBarLocationListener]. */
+class BubbleBarLocationOnDemandListener(
+ private val listenerProvider: () -> BubbleBarLocationListener
+) : BubbleBarLocationListener {
+
+ override fun onBubbleBarLocationAnimated(location: BubbleBarLocation) {
+ listenerProvider().onBubbleBarLocationAnimated(location)
+ }
+
+ override fun onBubbleBarLocationUpdated(location: BubbleBarLocation) {
+ listenerProvider().onBubbleBarLocationUpdated(location)
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 9d9f096..bc0ace2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -37,6 +37,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
+import static com.android.launcher3.Utilities.isRtl;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
@@ -63,7 +64,9 @@
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
-import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.Flags.enableBubbleAnything;
+import static com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -196,6 +199,7 @@
import com.android.systemui.unfold.dagger.UnfoldMain;
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver;
import com.android.systemui.unfold.updates.RotationChangeProvider;
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import java.io.FileDescriptor;
@@ -237,6 +241,7 @@
private SplitSelectStateController mSplitSelectStateController;
private SplitWithKeyboardShortcutController mSplitWithKeyboardShortcutController;
private SplitToWorkspaceController mSplitToWorkspaceController;
+ private BubbleBarLocation mBubbleBarLocation;
/**
* If Launcher restarted while in the middle of an Overview split select, it needs this data to
@@ -461,7 +466,7 @@
if (Flags.enablePrivateSpace()) {
shortcuts.add(UNINSTALL_APP);
}
- if (com.android.wm.shell.Flags.enableBubbleAnything()) {
+ if (enableBubbleAnything()) {
shortcuts.add(BUBBLE_SHORTCUT);
}
return shortcuts.stream();
@@ -1092,6 +1097,29 @@
return mTaskbarUIController;
}
+ /** Provides the translation X for the hotseat item. */
+ public int getHotseatItemTranslationX(ItemInfo itemInfo) {
+ int translationX = 0;
+ if (isBubbleBarEnabled()
+ && enableBubbleBarInPersistentTaskBar()
+ && mBubbleBarLocation != null) {
+ boolean isBubblesOnLeft = mBubbleBarLocation.isOnLeft(isRtl(getResources()));
+ translationX += mDeviceProfile
+ .getHotseatTranslationXForBubbleBar(/* isNavbarOnRight = */ isBubblesOnLeft);
+ }
+ if (isBubbleBarEnabled() && hasBubbles()) {
+ // TODO(368379159) : create a class to reuse computation logic
+ float adjustedBorderSpace =
+ mDeviceProfile.getHotseatAdjustedBorderSpaceForBubbleBar(this);
+ if (Float.compare(adjustedBorderSpace, 0f) != 0) {
+ float borderSpaceDelta = adjustedBorderSpace - mDeviceProfile.hotseatBorderSpace;
+ translationX +=
+ (int) (mDeviceProfile.iconSizePx + itemInfo.cellX * borderSpaceDelta);
+ }
+ }
+ return translationX;
+ }
+
public SplitToWorkspaceController getSplitToWorkspaceController() {
return mSplitToWorkspaceController;
}
@@ -1332,7 +1360,7 @@
/* callback= */ success -> mSplitSelectStateController.resetState(),
/* freezeTaskList= */ false,
groupTask.mSplitBounds == null
- ? SNAP_TO_50_50
+ ? SNAP_TO_2_50_50
: groupTask.mSplitBounds.snapPosition,
remoteTransition);
}
@@ -1397,6 +1425,11 @@
SystemUiProxy.INSTANCE.get(this).showAppBubble(intent);
}
+ /** Sets the location of the bubble bar */
+ public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+ mBubbleBarLocation = bubbleBarLocation;
+ }
+
private static final class LauncherTaskViewController extends
TaskViewTouchController<QuickstepLauncher> {
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 864328f..9ad6b303 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1201,11 +1201,9 @@
failureReason.append("STATE_START_NEW_TASK was never set");
} else {
TaskInfo taskInfo = appearedTaskTargets[0].taskInfo;
- failureReason.append("Unexpected task appeared")
- .append(" id=")
- .append(taskInfo.taskId)
- .append(" pkg=")
- .append(taskInfo.baseIntent.getComponent().getPackageName());
+ failureReason.append("Unexpected task appeared id=%d, pkg=%s",
+ taskInfo.taskId,
+ taskInfo.baseIntent.getComponent().getPackageName());
}
return false;
}
@@ -2274,18 +2272,15 @@
TaskView nextTask = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
if (nextTask != null) {
int[] taskIds = nextTask.getTaskIds();
- ActiveGestureLog.CompoundString nextTaskLog = new ActiveGestureLog.CompoundString(
- "Launching task: ");
+ ActiveGestureLog.CompoundString nextTaskLog =
+ ActiveGestureLog.CompoundString.newEmptyString();
for (TaskContainer container : nextTask.getTaskContainers()) {
if (container == null) {
continue;
}
- nextTaskLog
- .append("[id: ")
- .append(container.getTask().key.id)
- .append(", pkg: ")
- .append(container.getTask().key.getPackageName())
- .append("] | ");
+ nextTaskLog.append("[id: %d, pkg: %s] | ",
+ container.getTask().key.id,
+ container.getTask().key.getPackageName());
}
mGestureState.updateLastStartedTaskIds(taskIds);
boolean hasTaskPreviouslyAppeared = Arrays.stream(taskIds).anyMatch(
@@ -2294,7 +2289,7 @@
if (!hasTaskPreviouslyAppeared) {
ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED);
}
- ActiveGestureProtoLogProxy.logDynamicString(nextTaskLog.toString());
+ ActiveGestureProtoLogProxy.logStartNewTask(nextTaskLog);
nextTask.launchWithoutAnimation(true, success -> {
resultCallback.accept(success);
if (success) {
@@ -2375,8 +2370,8 @@
ActiveGestureProtoLogProxy.logAbsSwipeUpHandlerOnTasksAppeared();
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
};
- ActiveGestureLog.CompoundString forceFinishReason = new ActiveGestureLog.CompoundString(
- "Forcefully finishing recents animation: ");
+ ActiveGestureLog.CompoundString forceFinishReason =
+ ActiveGestureLog.CompoundString.newEmptyString();
if (!mStateCallback.hasStates(STATE_GESTURE_COMPLETED)
&& !hasStartedTaskBefore(appearedTaskTargets)) {
// This is a special case, if a task is started mid-gesture that wasn't a part of a
@@ -2390,10 +2385,10 @@
return;
}
ActiveGestureLog.CompoundString handleTaskFailureReason =
- new ActiveGestureLog.CompoundString("handleTaskAppeared check failed: ");
+ ActiveGestureLog.CompoundString.newEmptyString();
if (!handleTaskAppeared(appearedTaskTargets, handleTaskFailureReason)) {
forceFinishReason.append(handleTaskFailureReason);
- ActiveGestureProtoLogProxy.logDynamicString(forceFinishReason.toString());
+ ActiveGestureProtoLogProxy.logHandleTaskAppearedFailed(forceFinishReason);
finishRecentsAnimationOnTasksAppeared(onFinishComplete);
return;
}
@@ -2402,7 +2397,7 @@
.toArray(RemoteAnimationTarget[]::new);
if (taskTargets.length == 0) {
forceFinishReason.append("No appeared task matching started task id");
- ActiveGestureProtoLogProxy.logDynamicString(forceFinishReason.toString());
+ ActiveGestureProtoLogProxy.logHandleTaskAppearedFailed(forceFinishReason);
finishRecentsAnimationOnTasksAppeared(onFinishComplete);
return;
}
@@ -2412,13 +2407,13 @@
if (taskView == null || taskView.getTaskContainers().stream().noneMatch(
TaskContainer::getShouldShowSplashView)) {
forceFinishReason.append("Splash not needed");
- ActiveGestureProtoLogProxy.logDynamicString(forceFinishReason.toString());
+ ActiveGestureProtoLogProxy.logHandleTaskAppearedFailed(forceFinishReason);
finishRecentsAnimationOnTasksAppeared(onFinishComplete);
return;
}
if (mContainer == null) {
forceFinishReason.append("Activity destroyed");
- ActiveGestureProtoLogProxy.logDynamicString(forceFinishReason.toString());
+ ActiveGestureProtoLogProxy.logHandleTaskAppearedFailed(forceFinishReason);
finishRecentsAnimationOnTasksAppeared(onFinishComplete);
return;
}
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.java b/quickstep/src/com/android/quickstep/TaskIconCache.java
index 1f6c02c..91fa72d 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.java
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.java
@@ -226,7 +226,7 @@
synchronized (mDefaultIcons) {
if (mDefaultIconBase == null) {
try (BaseIconFactory bif = getIconFactory()) {
- mDefaultIconBase = bif.makeDefaultIcon();
+ mDefaultIconBase = bif.makeDefaultIcon(mIconProvider);
}
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 18b7678..f0943dc 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -911,7 +911,7 @@
SafeCloseable traceToken = TraceHelper.INSTANCE.allowIpcs("TIS.onInputEvent");
CompoundString reasonString = action == ACTION_DOWN
- ? new CompoundString("TIS.onMotionEvent: ") : CompoundString.NO_OP;
+ ? CompoundString.newEmptyString() : CompoundString.NO_OP;
if (action == ACTION_DOWN || isHoverActionWithoutConsumer) {
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
@@ -929,22 +929,22 @@
reasonString.append("in three button mode which supports Assistant gesture");
// Consume gesture event for Assistant (all other gestures should do nothing).
if (mDeviceState.canTriggerAssistantAction(event)) {
- reasonString.append(" and event can trigger assistant action")
- .append(", consuming gesture for assistant action");
+ reasonString.append(" and event can trigger assistant action, "
+ + "consuming gesture for assistant action");
mGestureState =
createGestureState(mGestureState, getTrackpadGestureType(event));
mUncheckedConsumer = tryCreateAssistantInputConsumer(mGestureState, event);
} else {
- reasonString.append(" but event cannot trigger Assistant")
- .append(", consuming gesture as no-op");
+ reasonString.append(" but event cannot trigger Assistant, "
+ + "consuming gesture as no-op");
mUncheckedConsumer = InputConsumer.NO_OP;
}
} else if ((!isOneHandedModeActive && isInSwipeUpTouchRegion)
|| isHoverActionWithoutConsumer || isOnBubbles) {
reasonString.append(!isOneHandedModeActive && isInSwipeUpTouchRegion
- ? "one handed mode is not active and event is in swipe up region"
- : "isHoverActionWithoutConsumer == true")
- .append(", creating new input consumer");
+ ? "one handed mode is not active and event is in swipe up region, "
+ + "creating new input consumer"
+ : "isHoverActionWithoutConsumer == true, creating new input consumer");
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
// onConsumerInactive and wipe the previous gesture state
GestureState prevGestureState = new GestureState(mGestureState);
@@ -957,18 +957,18 @@
} else if ((mDeviceState.isFullyGesturalNavMode() || isTrackpadMultiFingerSwipe(event))
&& mDeviceState.canTriggerAssistantAction(event)) {
reasonString.append(mDeviceState.isFullyGesturalNavMode()
- ? "using fully gestural nav"
- : "event is a trackpad multi-finger swipe")
- .append(" and event can trigger assistant action")
- .append(", consuming gesture for assistant action");
+ ? "using fully gestural nav and event can trigger assistant action, "
+ + "consuming gesture for assistant action"
+ : "event is a trackpad multi-finger swipe and event can trigger assistant "
+ + "action, consuming gesture for assistant action");
mGestureState = createGestureState(mGestureState, getTrackpadGestureType(event));
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
// should not interrupt it. QuickSwitch assumes that interruption can only
// happen if the next gesture is also quick switch.
mUncheckedConsumer = tryCreateAssistantInputConsumer(mGestureState, event);
} else if (mDeviceState.canTriggerOneHandedAction(event)) {
- reasonString.append("event can trigger one-handed action")
- .append(", consuming gesture for one-handed action");
+ reasonString.append("event can trigger one-handed action, "
+ + "consuming gesture for one-handed action");
// Consume gesture event for triggering one handed feature.
mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
InputConsumer.NO_OP, mInputMonitorCompat);
@@ -986,7 +986,7 @@
if (mUncheckedConsumer != InputConsumer.NO_OP) {
switch (action) {
case ACTION_DOWN:
- ActiveGestureProtoLogProxy.logDynamicString(reasonString.toString());
+ ActiveGestureProtoLogProxy.logOnInputEventActionDown(reasonString);
// fall through
case ACTION_UP:
ActiveGestureProtoLogProxy.logOnInputEventActionUp(
@@ -1059,11 +1059,11 @@
MotionEvent motionEvent,
CompoundString reasonString) {
if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
- reasonString.append(SUBSTRING_PREFIX)
- .append("is gesture-blocked task, using base input consumer");
+ reasonString.append(
+ "%sis gesture-blocked task, using base input consumer", SUBSTRING_PREFIX);
return base;
} else {
- reasonString.append(SUBSTRING_PREFIX).append("using AssistantInputConsumer");
+ reasonString.append("%susing AssistantInputConsumer", SUBSTRING_PREFIX);
return new AssistantInputConsumer(
this, gestureState, base, mInputMonitorCompat, mDeviceState, motionEvent);
}
@@ -1132,12 +1132,11 @@
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g. camera).
consumer = createDeviceLockedInputConsumer(
- newGestureState, reasonString.append(SUBSTRING_PREFIX)
- .append("can start system gesture"));
+ newGestureState,
+ reasonString.append("%scan start system gesture", SUBSTRING_PREFIX));
} else {
consumer = getDefaultInputConsumer(
- reasonString.append(SUBSTRING_PREFIX)
- .append("cannot start system gesture"));
+ reasonString.append("%scannot start system gesture", SUBSTRING_PREFIX));
}
logInputConsumerSelectionReason(consumer, reasonString);
return consumer;
@@ -1149,13 +1148,12 @@
// a followup gesture and the first gesture started in a valid system state.
if (canStartSystemGesture || previousGestureState.isRecentsAnimationRunning()) {
reasonString = newCompoundString(canStartSystemGesture
- ? "can start system gesture" : "recents animation was running")
- .append(", trying to use base consumer");
+ ? "can start system gesture, trying to use base consumer"
+ : "recents animation was running, trying to use base consumer");
base = newBaseConsumer(previousGestureState, newGestureState, event, reasonString);
} else {
- reasonString = newCompoundString(
- "cannot start system gesture and recents animation was not running")
- .append(", trying to use default input consumer");
+ reasonString = newCompoundString("cannot start system gesture and recents "
+ + "animation was not running, trying to use default input consumer");
base = getDefaultInputConsumer(reasonString);
}
if (mDeviceState.isGesturalNavMode() || newGestureState.isTrackpadGesture()) {
@@ -1165,11 +1163,11 @@
String reasonPrefix =
"device is in gesture navigation mode or 3-button mode with a trackpad gesture";
if (mDeviceState.canTriggerAssistantAction(event)) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("gesture can trigger the assistant")
- .append(", trying to use assistant input consumer");
+ reasonString.append("%s%s%sgesture can trigger the assistant, "
+ + "trying to use assistant input consumer",
+ NEWLINE_PREFIX,
+ reasonPrefix,
+ SUBSTRING_PREFIX);
base = tryCreateAssistantInputConsumer(base, newGestureState, event, reasonString);
}
@@ -1180,11 +1178,11 @@
&& !tac.isPhoneMode()
&& !tac.isInStashedLauncherState();
if (canStartSystemGesture && useTaskbarConsumer) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("TaskbarActivityContext != null, ")
- .append("using TaskbarUnstashInputConsumer");
+ reasonString.append("%s%s%sTaskbarActivityContext != null, "
+ + "using TaskbarUnstashInputConsumer",
+ NEWLINE_PREFIX,
+ reasonPrefix,
+ SUBSTRING_PREFIX);
base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac,
mOverviewCommandHelper, mGestureState);
}
@@ -1193,9 +1191,9 @@
// Create bubbles input consumer before NavHandleLongPressInputConsumer.
// This allows for nav handle to fall back to bubbles.
if (mDeviceState.isBubblesExpanded()) {
- reasonString = newCompoundString(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("bubbles expanded, trying to use default input consumer");
+ reasonString = newCompoundString(reasonPrefix).append(
+ "%sbubbles expanded, trying to use default input consumer",
+ SUBSTRING_PREFIX);
// Bubbles can handle home gesture itself.
base = getDefaultInputConsumer(reasonString);
}
@@ -1206,10 +1204,10 @@
if (canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()
&& navHandle.canNavHandleBeLongPressed()
&& !ignoreThreeFingerTrackpadForNavHandleLongPress(mGestureState)) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("Not running recents animation, ");
+ reasonString.append("%s%s%sNot running recents animation, ",
+ NEWLINE_PREFIX,
+ reasonPrefix,
+ SUBSTRING_PREFIX);
if (tac != null && tac.getNavHandle().canNavHandleBeLongPressed()) {
reasonString.append("stashed handle is long-pressable, ");
}
@@ -1221,74 +1219,74 @@
if (!enableBubblesLongPressNavHandle()) {
// Continue overriding nav handle input consumer with bubbles
if (mDeviceState.isBubblesExpanded()) {
- reasonString = newCompoundString(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("bubbles expanded, trying to use default input consumer");
+ reasonString = newCompoundString(reasonPrefix).append(
+ "%sbubbles expanded, trying to use default input consumer",
+ SUBSTRING_PREFIX);
// Bubbles can handle home gesture itself.
base = getDefaultInputConsumer(reasonString);
}
}
if (mDeviceState.isSystemUiDialogShowing()) {
- reasonString = newCompoundString(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("system dialog is showing, using SysUiOverlayInputConsumer");
+ reasonString = newCompoundString(reasonPrefix).append(
+ "%ssystem dialog is showing, using SysUiOverlayInputConsumer",
+ SUBSTRING_PREFIX);
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
if (mGestureState.isTrackpadGesture()
&& canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()) {
- reasonString = newCompoundString(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("Trackpad 3-finger gesture, using TrackpadStatusBarInputConsumer");
+ reasonString = newCompoundString(reasonPrefix).append(
+ "%sTrackpad 3-finger gesture, using TrackpadStatusBarInputConsumer",
+ SUBSTRING_PREFIX);
base = new TrackpadStatusBarInputConsumer(getBaseContext(), base,
mInputMonitorCompat);
}
if (mDeviceState.isScreenPinningActive()) {
- reasonString = newCompoundString(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("screen pinning is active, using ScreenPinnedInputConsumer");
+ reasonString = newCompoundString(reasonPrefix).append(
+ "%sscreen pinning is active, using ScreenPinnedInputConsumer",
+ SUBSTRING_PREFIX);
// Note: we only allow accessibility to wrap this, and it replaces the previous
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
base = new ScreenPinnedInputConsumer(this, newGestureState);
}
if (mDeviceState.canTriggerOneHandedAction(event)) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("gesture can trigger one handed mode")
- .append(", using OneHandedModeInputConsumer");
+ reasonString.append("%s%s%sgesture can trigger one handed mode, "
+ + "using OneHandedModeInputConsumer",
+ NEWLINE_PREFIX,
+ reasonPrefix,
+ SUBSTRING_PREFIX);
base = new OneHandedModeInputConsumer(
this, mDeviceState, base, mInputMonitorCompat);
}
if (mDeviceState.isAccessibilityMenuAvailable()) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("accessibility menu is available")
- .append(", using AccessibilityInputConsumer");
+ reasonString.append(
+ "%s%s%saccessibility menu is available, using AccessibilityInputConsumer",
+ NEWLINE_PREFIX,
+ reasonPrefix,
+ SUBSTRING_PREFIX);
base = new AccessibilityInputConsumer(
this, mDeviceState, mGestureState, base, mInputMonitorCompat);
}
} else {
String reasonPrefix = "device is not in gesture navigation mode";
if (mDeviceState.isScreenPinningActive()) {
- reasonString = newCompoundString(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("screen pinning is active, trying to use default input consumer");
+ reasonString = newCompoundString(reasonPrefix).append(
+ "%sscreen pinning is active, trying to use default input consumer",
+ SUBSTRING_PREFIX);
base = getDefaultInputConsumer(reasonString);
}
if (mDeviceState.canTriggerOneHandedAction(event)) {
- reasonString.append(NEWLINE_PREFIX)
- .append(reasonPrefix)
- .append(SUBSTRING_PREFIX)
- .append("gesture can trigger one handed mode")
- .append(", using OneHandedModeInputConsumer");
+ reasonString.append("%s%s%sgesture can trigger one handed mode, "
+ + "using OneHandedModeInputConsumer",
+ NEWLINE_PREFIX,
+ reasonPrefix,
+ SUBSTRING_PREFIX);
base = new OneHandedModeInputConsumer(
this, mDeviceState, base, mInputMonitorCompat);
}
@@ -1298,7 +1296,7 @@
}
private CompoundString newCompoundString(String substring) {
- return new CompoundString(NEWLINE_PREFIX).append(substring);
+ return new CompoundString("%s%s", NEWLINE_PREFIX, substring);
}
private boolean ignoreThreeFingerTrackpadForNavHandleLongPress(GestureState gestureState) {
@@ -1325,14 +1323,12 @@
CompoundString reasonString) {
if (mDeviceState.isKeyguardShowingOccluded()) {
// This handles apps showing over the lockscreen (e.g. camera)
- return createDeviceLockedInputConsumer(
- gestureState,
- reasonString.append(SUBSTRING_PREFIX)
- .append("keyguard is showing occluded")
- .append(", trying to use device locked input consumer"));
+ return createDeviceLockedInputConsumer(gestureState, reasonString.append(
+ "%skeyguard is showing occluded, trying to use device locked input consumer",
+ SUBSTRING_PREFIX));
}
- reasonString.append(SUBSTRING_PREFIX).append("keyguard is not showing occluded");
+ reasonString.append("%skeyguard is not showing occluded", SUBSTRING_PREFIX);
TopTaskTracker.CachedTaskInfo runningTask = gestureState.getRunningTask();
// Use overview input consumer for sharesheets on top of home.
@@ -1373,11 +1369,12 @@
gestureState,
event,
forceOverviewInputConsumer,
- reasonString.append(SUBSTRING_PREFIX)
- .append("is in live tile mode, trying to use overview input consumer"));
+ reasonString.append(
+ "%sis in live tile mode, trying to use overview input consumer",
+ SUBSTRING_PREFIX));
} else if (runningTask == null) {
- return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
- .append("running task == null"));
+ return getDefaultInputConsumer(reasonString.append(
+ "%srunning task == null", SUBSTRING_PREFIX));
} else if (previousGestureAnimatedToLauncher
|| launcherResumedThroughShellTransition
|| forceOverviewInputConsumer) {
@@ -1386,21 +1383,22 @@
gestureState,
event,
forceOverviewInputConsumer,
- reasonString.append(SUBSTRING_PREFIX)
- .append(previousGestureAnimatedToLauncher
- ? "previous gesture animated to launcher"
+ reasonString.append(previousGestureAnimatedToLauncher
+ ? "%sprevious gesture animated to launcher, "
+ + "trying to use overview input consumer"
: (launcherResumedThroughShellTransition
- ? "launcher resumed through a shell transition"
- : "forceOverviewInputConsumer == true"))
- .append(", trying to use overview input consumer"));
+ ? "%slauncher resumed through a shell transition, "
+ + "trying to use overview input consumer"
+ : "%sforceOverviewInputConsumer == true, "
+ + "trying to use overview input consumer"),
+ SUBSTRING_PREFIX));
} else if (mDeviceState.isGestureBlockedTask(runningTask) || launcherChildActivityResumed) {
- return getDefaultInputConsumer(reasonString.append(SUBSTRING_PREFIX)
- .append(launcherChildActivityResumed
- ? "is launcher child-task, trying to use default input consumer"
- : "is gesture-blocked task, trying to use default input consumer"));
+ return getDefaultInputConsumer(reasonString.append(launcherChildActivityResumed
+ ? "%sis launcher child-task, trying to use default input consumer"
+ : "%sis gesture-blocked task, trying to use default input consumer",
+ SUBSTRING_PREFIX));
} else {
- reasonString.append(SUBSTRING_PREFIX)
- .append("using OtherActivityInputConsumer");
+ reasonString.append("%susing OtherActivityInputConsumer", SUBSTRING_PREFIX);
return createOtherActivityInputConsumer(gestureState, event);
}
}
@@ -1427,20 +1425,18 @@
GestureState gestureState, CompoundString reasonString) {
if ((mDeviceState.isFullyGesturalNavMode() || gestureState.isTrackpadGesture())
&& gestureState.getRunningTask() != null) {
- reasonString.append(SUBSTRING_PREFIX)
- .append("device is in gesture nav mode or 3-button mode with a trackpad")
- .append(" gesture and running task != null")
- .append(", using DeviceLockedInputConsumer");
+ reasonString.append("%sdevice is in gesture nav mode or 3-button mode with a trackpad "
+ + "gesture and running task != null, using DeviceLockedInputConsumer",
+ SUBSTRING_PREFIX);
return new DeviceLockedInputConsumer(
this, mDeviceState, mTaskAnimationManager, gestureState, mInputMonitorCompat);
} else {
- return getDefaultInputConsumer(reasonString
- .append(SUBSTRING_PREFIX)
- .append((mDeviceState.isFullyGesturalNavMode()
- || gestureState.isTrackpadGesture())
- ? "running task == null"
- : "device is not in gesture nav mode and it's not a trackpad gesture")
- .append(", trying to use default input consumer"));
+ return getDefaultInputConsumer(reasonString.append(
+ mDeviceState.isFullyGesturalNavMode() || gestureState.isTrackpadGesture()
+ ? "%srunning task == null, trying to use default input consumer"
+ : "%sdevice is not in gesture nav mode and it's not a trackpad gesture,"
+ + " trying to use default input consumer",
+ SUBSTRING_PREFIX));
}
}
@@ -1452,9 +1448,8 @@
CompoundString reasonString) {
RecentsViewContainer container = gestureState.getContainerInterface().getCreatedContainer();
if (container == null) {
- return getDefaultInputConsumer(
- reasonString.append(SUBSTRING_PREFIX)
- .append("activity == null, trying to use default input consumer"));
+ return getDefaultInputConsumer(reasonString.append(
+ "%sactivity == null, trying to use default input consumer", SUBSTRING_PREFIX));
}
View rootview = container.getRootView();
@@ -1464,24 +1459,24 @@
|| mDeviceState.isPredictiveBackToHomeInProgress();
boolean isInLiveTileMode = gestureState.getContainerInterface().isInLiveTileMode();
- reasonString.append(SUBSTRING_PREFIX)
- .append(hasWindowFocus
- ? "activity has window focus"
- : (isPreviousGestureAnimatingToLauncher
- ? "previous gesture is still animating to launcher"
- : isInLiveTileMode
- ? "device is in live mode"
- : "all overview focus conditions failed"));
+ reasonString.append(hasWindowFocus
+ ? "%sactivity has window focus"
+ : (isPreviousGestureAnimatingToLauncher
+ ? "%sprevious gesture is still animating to launcher"
+ : isInLiveTileMode
+ ? "%sdevice is in live mode"
+ : "%sall overview focus conditions failed"), SUBSTRING_PREFIX);
if (hasWindowFocus
|| isPreviousGestureAnimatingToLauncher
|| isInLiveTileMode) {
- reasonString.append(SUBSTRING_PREFIX)
- .append("overview should have focus, using OverviewInputConsumer");
+ reasonString.append(
+ "%soverview should have focus, using OverviewInputConsumer", SUBSTRING_PREFIX);
return new OverviewInputConsumer(gestureState, container, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
- reasonString.append(SUBSTRING_PREFIX).append(
- "overview shouldn't have focus, using OverviewWithoutFocusInputConsumer");
+ reasonString.append(
+ "%soverview shouldn't have focus, using OverviewWithoutFocusInputConsumer",
+ SUBSTRING_PREFIX);
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
return new OverviewWithoutFocusInputConsumer(container.asContext(), mDeviceState,
gestureState, mInputMonitorCompat, disableHorizontalSwipe);
@@ -1518,12 +1513,14 @@
*/
private @NonNull InputConsumer getDefaultInputConsumer(@NonNull CompoundString reasonString) {
if (mResetGestureInputConsumer != null) {
- reasonString.append(SUBSTRING_PREFIX).append(
- "mResetGestureInputConsumer initialized, using ResetGestureInputConsumer");
+ reasonString.append(
+ "%smResetGestureInputConsumer initialized, using ResetGestureInputConsumer",
+ SUBSTRING_PREFIX);
return mResetGestureInputConsumer;
} else {
- reasonString.append(SUBSTRING_PREFIX).append(
- "mResetGestureInputConsumer not initialized, using no-op input consumer");
+ reasonString.append(
+ "%smResetGestureInputConsumer not initialized, using no-op input consumer",
+ SUBSTRING_PREFIX);
// mResetGestureInputConsumer isn't initialized until onUserUnlocked(), so reset to
// NO_OP until then (we never want these to be null).
return InputConsumer.NO_OP;
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 7f88090..5a4c769 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -323,7 +323,7 @@
}
@Override
- protected boolean canLaunchFullscreenTask() {
+ public boolean canLaunchFullscreenTask() {
return !mContainer.isInState(OVERVIEW_SPLIT_SELECT);
}
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index e1013db..7388d59 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -26,7 +26,7 @@
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
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.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_NONE;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
@@ -189,7 +189,7 @@
@PersistentSnapPosition int snapPosition = gtv.getSnapPosition();
if (snapPosition == SNAP_TO_NONE) {
// Free snap mode is enabled, just save it as 50/50 split.
- snapPosition = SNAP_TO_50_50;
+ snapPosition = SNAP_TO_2_50_50;
}
if (!isPersistentSnapPosition(snapPosition)) {
// If we received an illegal snap position, log an error and do not create the app pair
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index 3a1c99b..64e46d8 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -85,6 +85,7 @@
.setBitmap(screenshot)
.setBoundsOnScreen(screenshotBounds)
.setInsets(visibleInsets)
+ .setDisplayId(task.displayId)
.build();
systemUiProxy.takeScreenshot(request);
}
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index 4a9e0d8..8762e86 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -98,10 +98,8 @@
mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> {
- ActiveGestureLog.CompoundString log =
- new ActiveGestureLog.CompoundString("Force pause timeout after ")
- .append(alarm.getLastSetTimeout())
- .append("ms");
+ ActiveGestureLog.CompoundString log = new ActiveGestureLog.CompoundString(
+ "Force pause timeout after %dms", alarm.getLastSetTimeout());
addLogs(log);
updatePaused(true /* isPaused */, log);
});
@@ -124,9 +122,8 @@
* @param disallowPause If true, we will not detect any pauses until this is set to false again.
*/
public void setDisallowPause(boolean disallowPause) {
- ActiveGestureLog.CompoundString log =
- new ActiveGestureLog.CompoundString("Set disallowPause=")
- .append(disallowPause);
+ ActiveGestureLog.CompoundString log = new ActiveGestureLog.CompoundString(
+ "Set disallowPause=%b", disallowPause);
if (mDisallowPause != disallowPause) {
addLogs(log);
}
@@ -188,8 +185,8 @@
speed < previousSpeed * getRapidDecelerationFactor();
isPaused = isRapidDeceleration && speed < mSpeedSomewhatFast;
isPausedReason = new ActiveGestureLog.CompoundString(
- "Didn't have back to back slow speeds, checking for rapid ")
- .append(" deceleration on first pause only");
+ "Didn't have back to back slow speeds, checking for rapid "
+ + " deceleration on first pause only");
}
if (mMakePauseHarderToTrigger) {
if (speed < mSpeedSlow) {
@@ -198,8 +195,8 @@
}
isPaused = time - mSlowStartTime >= HARDER_TRIGGER_TIMEOUT;
isPausedReason = new ActiveGestureLog.CompoundString(
- "Maintained slow speed for sufficient duration when making")
- .append(" pause harder to trigger");
+ "Maintained slow speed for sufficient duration when making"
+ + " pause harder to trigger");
} else {
mSlowStartTime = 0;
isPaused = false;
@@ -215,17 +212,14 @@
private void updatePaused(boolean isPaused, ActiveGestureLog.CompoundString reason) {
if (mDisallowPause) {
reason = new ActiveGestureLog.CompoundString(
- "Disallow pause; otherwise, would have been ")
- .append(isPaused)
- .append(" due to reason:")
+ "Disallow pause; otherwise, would have been %b due to reason: ", isPaused)
.append(reason);
isPaused = false;
}
if (mIsPaused != isPaused) {
mIsPaused = isPaused;
- addLogs(new ActiveGestureLog.CompoundString("onMotionPauseChanged triggered; paused=")
- .append(mIsPaused)
- .append(", reason=")
+ addLogs(new ActiveGestureLog.CompoundString(
+ "onMotionPauseChanged triggered; paused=%b, reason=", mIsPaused)
.append(reason));
boolean isFirstDetectedPause = !mHasEverBeenPaused && mIsPaused;
if (mIsPaused) {
@@ -245,14 +239,13 @@
}
}
- private void addLogs(ActiveGestureLog.CompoundString compoundString) {
- ActiveGestureLog.CompoundString logString =
- new ActiveGestureLog.CompoundString("MotionPauseDetector: ")
- .append(compoundString);
+ private void addLogs(ActiveGestureLog.CompoundString event) {
if (Utilities.isRunningInTestHarness()) {
- Log.d(TAG, logString.toString());
+ Log.d(TAG, new ActiveGestureLog.CompoundString("MotionPauseDetector: ")
+ .append(event)
+ .toString());
}
- ActiveGestureProtoLogProxy.logMotionPauseDetectorEvent(logString.toString());
+ ActiveGestureProtoLogProxy.logMotionPauseDetectorEvent(event);
}
public void clear() {
diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
index f547a7fb..a94d023 100644
--- a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
+++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
@@ -23,8 +23,10 @@
import android.view.View
import android.view.animation.PathInterpolator
import androidx.core.graphics.transform
+import com.android.app.animation.Animations
import com.android.app.animation.Interpolators
import com.android.app.animation.Interpolators.LINEAR
+import com.android.launcher3.Flags
import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY
import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE
import com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY
@@ -44,9 +46,9 @@
* the screen outwards radially. This is used in conjunction with the swipe up to home animation.
*/
class ScalingWorkspaceRevealAnim(
- launcher: QuickstepLauncher,
+ private val launcher: QuickstepLauncher,
siblingAnimation: RectFSpringAnim?,
- windowTargetRect: RectF?
+ windowTargetRect: RectF?,
) {
companion object {
private const val FADE_DURATION_MS = 200L
@@ -86,25 +88,40 @@
launcher.workspace.stateTransitionAnimation.setScrim(
PropertySetter.NO_ANIM_PROPERTY_SETTER,
LauncherState.BACKGROUND_APP,
- setupConfig
+ setupConfig,
)
val workspace = launcher.workspace
val hotseat = launcher.hotseat
+ var fromSize =
+ if (Flags.coordinateWorkspaceScale()) {
+ // Interrupt the current animation, if any.
+ Animations.cancelOngoingAnimation(workspace)
+ Animations.cancelOngoingAnimation(hotseat)
+
+ if (workspace.scaleX != MAX_SIZE) {
+ workspace.scaleX
+ } else {
+ MIN_SIZE
+ }
+ } else {
+ MIN_SIZE
+ }
+
// Scale the Workspace and Hotseat around the same pivot.
workspace.setPivotToScaleWithSelf(hotseat)
animation.addFloat(
workspace,
WORKSPACE_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE],
- MIN_SIZE,
+ fromSize,
MAX_SIZE,
SCALE_INTERPOLATOR,
)
animation.addFloat(
hotseat,
HOTSEAT_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE],
- MIN_SIZE,
+ fromSize,
MAX_SIZE,
SCALE_INTERPOLATOR,
)
@@ -116,13 +133,13 @@
animation.setViewAlpha(
workspace,
MAX_ALPHA,
- Interpolators.clampToProgress(LINEAR, 0f, fadeClamp)
+ Interpolators.clampToProgress(LINEAR, 0f, fadeClamp),
)
hotseat.alpha = MIN_ALPHA
animation.setViewAlpha(
hotseat,
MAX_ALPHA,
- Interpolators.clampToProgress(LINEAR, 0f, fadeClamp)
+ Interpolators.clampToProgress(LINEAR, 0f, fadeClamp),
)
val transitionConfig = StateAnimationConfig()
@@ -137,7 +154,7 @@
launcher.workspace.stateTransitionAnimation.setScrim(
animation,
LauncherState.NORMAL,
- transitionConfig
+ transitionConfig,
)
// To avoid awkward jumps in icon position, we want the sibling animation to always be
@@ -164,7 +181,7 @@
1 / workspace.scaleX,
1 / workspace.scaleY,
transformed.centerX(),
- transformed.centerY()
+ transformed.centerY(),
)
}
)
@@ -183,6 +200,12 @@
Runnable {
workspace.setLayerType(View.LAYER_TYPE_NONE, null)
hotseat.setLayerType(View.LAYER_TYPE_NONE, null)
+
+ if (Flags.coordinateWorkspaceScale()) {
+ // Reset the cached animations.
+ Animations.setOngoingAnimation(workspace, animation = null)
+ Animations.setOngoingAnimation(hotseat, animation = null)
+ }
}
)
)
@@ -193,6 +216,14 @@
}
fun start() {
- getAnimators().start()
+ val animators = getAnimators()
+ if (Flags.coordinateWorkspaceScale()) {
+ // Make sure to cache the current animation, so it can be properly interrupted.
+ // TODO(b/367591368): ideally these animations would be refactored to be controlled
+ // centrally so each instances doesn't need to care about this coordination.
+ Animations.setOngoingAnimation(launcher.workspace, animators)
+ Animations.setOngoingAnimation(launcher.hotseat, animators)
+ }
+ animators.start()
}
}
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index fbeeef2..60c6ade 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -35,7 +35,7 @@
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
import static com.android.wm.shell.shared.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT;
-import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50;
+import static com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -363,7 +363,7 @@
* A version of {@link #launchSplitTasks(int, Consumer)} that launches with default split ratio.
*/
public void launchSplitTasks(@Nullable Consumer<Boolean> callback) {
- launchSplitTasks(SNAP_TO_50_50, callback);
+ launchSplitTasks(SNAP_TO_2_50_50, callback);
}
/**
@@ -371,7 +371,7 @@
* ratio and no callback.
*/
public void launchSplitTasks() {
- launchSplitTasks(SNAP_TO_50_50, null);
+ launchSplitTasks(SNAP_TO_2_50_50, null);
}
/**
@@ -565,13 +565,13 @@
switch (launchData.getSplitLaunchType()) {
case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId,
optionsBundle, secondTaskId, null /* options2 */, initialStagePosition,
- SNAP_TO_50_50, remoteTransition, instanceId);
+ SNAP_TO_2_50_50, remoteTransition, instanceId);
case SPLIT_SINGLE_INTENT_FULLSCREEN -> mSystemUiProxy.startIntentAndTask(firstPI,
firstUserId, optionsBundle, secondTaskId, null /*options2*/,
- initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
+ initialStagePosition, SNAP_TO_2_50_50, remoteTransition, instanceId);
case SPLIT_SINGLE_SHORTCUT_FULLSCREEN -> mSystemUiProxy.startShortcutAndTask(
initialShortcut, optionsBundle, firstTaskId, null /* options2 */,
- initialStagePosition, SNAP_TO_50_50, remoteTransition, instanceId);
+ initialStagePosition, SNAP_TO_2_50_50, remoteTransition, instanceId);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
index 6db0923..8c854e7 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
@@ -59,7 +59,7 @@
this,
R.layout.task_thumbnail_deprecated,
VIEW_POOL_MAX_SIZE,
- VIEW_POOL_INITIAL_SIZE
+ VIEW_POOL_INITIAL_SIZE,
)
private val tempPointF = PointF()
private val tempRect = Rect()
@@ -80,7 +80,7 @@
setTint(
resources.getColor(
android.R.color.system_neutral2_300,
- context.theme
+ context.theme,
)
)
}
@@ -92,8 +92,8 @@
ResourcesCompat.getDrawable(
context.resources,
R.drawable.ic_desktop_with_bg,
- context.theme
- )
+ context.theme,
+ ),
)
setText(resources.getText(R.string.recent_task_desktop))
}
@@ -104,7 +104,7 @@
fun bind(
tasks: List<Task>,
orientedState: RecentsOrientedState,
- taskOverlayFactory: TaskOverlayFactory
+ taskOverlayFactory: TaskOverlayFactory,
) {
if (DEBUG) {
val sb = StringBuilder()
@@ -126,7 +126,7 @@
snapshotView,
// Add snapshotView to the front after initial views e.g. icon and
// background.
- childCountAtInflation
+ childCountAtInflation,
)
TaskContainer(
this,
@@ -137,7 +137,7 @@
SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
digitalWellBeingToast = null,
showWindowsView = null,
- taskOverlayFactory
+ taskOverlayFactory,
)
}
taskContainers.forEach { it.bind() }
@@ -159,12 +159,12 @@
override fun updateTaskSize(
lastComputedTaskSize: Rect,
lastComputedGridTaskSize: Rect,
- lastComputedCarouselTaskSize: Rect
+ lastComputedCarouselTaskSize: Rect,
) {
super.updateTaskSize(
lastComputedTaskSize,
lastComputedGridTaskSize,
- lastComputedCarouselTaskSize
+ lastComputedCarouselTaskSize,
)
if (taskContainers.isEmpty()) {
return
@@ -186,7 +186,7 @@
Log.d(
TAG,
"onMeasure: container=[$containerWidth,$containerHeight]" +
- "window=[$windowWidth,$windowHeight] scale=[$scaleWidth,$scaleHeight]"
+ "window=[$windowWidth,$windowHeight] scale=[$scaleWidth,$scaleHeight]",
)
}
@@ -218,7 +218,7 @@
Log.d(
TAG,
"onMeasure: task=${it.task.key} size=[$width,$height]" +
- " margin=[$leftMargin,$topMargin]"
+ " margin=[$leftMargin,$topMargin]",
)
}
}
@@ -252,7 +252,7 @@
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN,
"launchDesktopFromRecents",
- taskIds.contentToString()
+ taskIds.contentToString(),
)
val endCallback = RunnableList()
val desktopController = recentsView.desktopRecentsController
@@ -262,7 +262,7 @@
}
Log.d(
TAG,
- "launchTaskWithDesktopController: ${taskIds.contentToString()}, withRemoteTransition: $animated"
+ "launchTaskWithDesktopController: ${taskIds.contentToString()}, withRemoteTransition: $animated",
)
// Callbacks get run from recentsView for case when recents animation already running
@@ -274,11 +274,13 @@
override fun launchWithoutAnimation(
isQuickSwitch: Boolean,
- callback: (launched: Boolean) -> Unit
+ callback: (launched: Boolean) -> Unit,
) = launchTaskWithDesktopController(animated = false)?.add { callback(true) } ?: callback(false)
- // Desktop tile can't be in split screen
- override fun confirmSecondSplitSelectApp(): Boolean = false
+ // Return true when Task cannot be launched as fullscreen (i.e. in split select state) to skip
+ // putting DesktopTaskView to split as it's not supported.
+ override fun confirmSecondSplitSelectApp(): Boolean =
+ recentsView?.canLaunchFullscreenTask() != true
// TODO(b/330685808) support overlay for Screenshot action
override fun setOverlayEnabled(overlayEnabled: Boolean) {}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 8f20cd38..00e57c2 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -250,7 +250,7 @@
}
@Override
- protected boolean canLaunchFullscreenTask() {
+ public boolean canLaunchFullscreenTask() {
if (FeatureFlags.enableSplitContextually()) {
return !mSplitSelectStateController.isSplitSelectActive();
} else {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 89844ad..a075c58 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -807,12 +807,6 @@
@Nullable
private DesktopRecentsTransitionController mDesktopRecentsTransitionController;
- /**
- * 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
@@ -1186,7 +1180,7 @@
*
* @return {@code true} if child TaskViews can be launched when user taps on them
*/
- protected boolean canLaunchFullscreenTask() {
+ public boolean canLaunchFullscreenTask() {
return true;
}
@@ -1879,7 +1873,6 @@
mFilterState.updateInstanceCountMap(taskGroups);
// Clear out desktop view if it is set
- mDesktopTaskView = null;
// Move Desktop Tasks to the end of the list
if (enableLargeDesktopWindowingTile()) {
@@ -1918,7 +1911,6 @@
.toList();
((DesktopTaskView) taskView).bind(nonMinimizedTasks, mOrientationState,
mTaskOverlayFactory);
- mDesktopTaskView = (DesktopTaskView) taskView;
} else {
Task task = groupTask.task1.key.id == stagedTaskIdToBeRemoved ? groupTask.task2
: groupTask.task1;
@@ -3809,74 +3801,15 @@
}
}
} else if (!showAsGrid) {
- // Compute scroll offsets from task dismissal for animation.
- // If we just take newScroll - oldScroll, everything to the right of dragged task
- // translates to the left. We need to offset this in some cases:
- // - In RTL, add page offset to all pages, since we want pages to move to the right
- // Additionally, add a page offset if:
- // - Current page is rightmost page (leftmost for RTL)
- // - Dragging an adjacent page on the left side (right side for RTL)
- int offset = mIsRtl ? scrollDiffPerPage : 0;
- if (mCurrentPage == dismissedIndex) {
- int lastPage = taskCount - 1;
- if (mCurrentPage == lastPage) {
- offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
- }
- } else {
- // Dismissing an adjacent page.
- int negativeAdjacent = mCurrentPage - 1; // (Right in RTL, left in LTR)
- if (dismissedIndex == negativeAdjacent) {
- offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
- }
- }
-
+ int offset = getOffsetToDismissedTask(scrollDiffPerPage, dismissedIndex, taskCount);
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
if (scrollDiff != 0) {
- FloatProperty translationProperty = child instanceof TaskView
- ? ((TaskView) child).getPrimaryDismissTranslationProperty()
- : getPagedOrientationHandler().getPrimaryViewTranslate();
-
- float additionalDismissDuration =
- ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(
- i - dismissedIndex);
-
- // We are in non-grid layout.
- // If dismissing for split select, use split timings.
- // If not, use dismiss timings.
- float animationStartProgress = isSplitSelectionActive()
- ? Utilities.boundToRange(splitTimings.getGridSlideStartOffset(), 0f, 1f)
- : Utilities.boundToRange(
- INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + additionalDismissDuration, 0f, 1f);
-
- float animationEndProgress = isSplitSelectionActive()
- ? Utilities.boundToRange(splitTimings.getGridSlideStartOffset()
- + splitTimings.getGridSlideDurationOffset(), 0f, 1f)
- : 1f;
-
- // Slide tiles in horizontally to fill dismissed area
- anim.setFloat(child, translationProperty, scrollDiff,
- clampToProgress(
- splitTimings.getGridSlidePrimaryInterpolator(),
- animationStartProgress,
- animationEndProgress
- )
- );
-
- if (mEnableDrawingLiveTile && child instanceof TaskView
- && ((TaskView) child).isRunningTask()) {
- anim.addOnFrameCallback(() -> {
- runActionOnRemoteHandles(
- remoteTargetHandle ->
- remoteTargetHandle.getTaskViewSimulator()
- .taskPrimaryTranslation.value =
- getPagedOrientationHandler().getPrimaryValue(
- child.getTranslationX(),
- child.getTranslationY()
- ));
- redrawLiveTile();
- });
- }
+ translateTaskWhenDismissed(
+ child,
+ Math.abs(i - dismissedIndex),
+ scrollDiff,
+ anim,
+ splitTimings);
needsCurveUpdates = true;
}
} else if (child instanceof TaskView) {
@@ -4192,6 +4125,87 @@
}
/**
+ * Compute scroll offsets from task dismissal for animation.
+ * If we just take newScroll - oldScroll, everything to the right of dragged task
+ * translates to the left. We need to offset this in some cases:
+ * - In RTL, add page offset to all pages, since we want pages to move to the right
+ * Additionally, add a page offset if:
+ * - Current page is rightmost page (leftmost for RTL)
+ * - Dragging an adjacent page on the left side (right side for RTL)
+ */
+ private int getOffsetToDismissedTask(int scrollDiffPerPage, int dismissedIndex, int taskCount) {
+ int offset = mIsRtl ? scrollDiffPerPage : 0;
+ if (mCurrentPage == dismissedIndex) {
+ int lastPage = taskCount - 1;
+ if (mCurrentPage == lastPage) {
+ offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
+ }
+ } else {
+ // Dismissing an adjacent page.
+ int negativeAdjacent = mCurrentPage - 1; // (Right in RTL, left in LTR)
+ if (dismissedIndex == negativeAdjacent) {
+ offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
+ }
+ }
+ return offset;
+ }
+
+ private void translateTaskWhenDismissed(
+ View view,
+ int indexDiff,
+ int scrollDiffPerPage,
+ PendingAnimation pendingAnimation,
+ SplitAnimationTimings splitTimings) {
+ FloatProperty translationProperty = view instanceof TaskView
+ ? ((TaskView) view).getPrimaryDismissTranslationProperty()
+ : getPagedOrientationHandler().getPrimaryViewTranslate();
+
+ float additionalDismissDuration =
+ ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * indexDiff;
+
+ // We are in non-grid layout.
+ // If dismissing for split select, use split timings.
+ // If not, use dismiss timings.
+ float animationStartProgress = isSplitSelectionActive()
+ ? Utilities.boundToRange(splitTimings.getGridSlideStartOffset(), 0f, 1f)
+ : Utilities.boundToRange(
+ INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ + additionalDismissDuration, 0f, 1f);
+
+ float animationEndProgress = isSplitSelectionActive()
+ ? Utilities.boundToRange(splitTimings.getGridSlideStartOffset()
+ + splitTimings.getGridSlideDurationOffset(), 0f, 1f)
+ : 1f;
+
+ // Slide tiles in horizontally to fill dismissed area
+ pendingAnimation.setFloat(
+ view,
+ translationProperty,
+ scrollDiffPerPage,
+ clampToProgress(
+ splitTimings.getGridSlidePrimaryInterpolator(),
+ animationStartProgress,
+ animationEndProgress
+ )
+ );
+
+ if (mEnableDrawingLiveTile && view instanceof TaskView
+ && ((TaskView) view).isRunningTask()) {
+ pendingAnimation.addOnFrameCallback(() -> {
+ runActionOnRemoteHandles(
+ remoteTargetHandle ->
+ remoteTargetHandle.getTaskViewSimulator()
+ .taskPrimaryTranslation.value =
+ getPagedOrientationHandler().getPrimaryValue(
+ view.getTranslationX(),
+ view.getTranslationY()
+ ));
+ redrawLiveTile();
+ });
+ }
+ }
+
+ /**
* Hides all overview actions if user is halfway through split selection, shows otherwise.
* We only show split option if:
* * Focused view is a single app
@@ -4986,7 +5000,6 @@
mSplitSelectStateController.setAnimateCurrentTaskDismissal(
true /*animateCurrentTaskDismissal*/);
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
- updateDesktopTaskVisibility(false /* visible */);
}
/**
@@ -5008,13 +5021,6 @@
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
splitSelectSource.position.stagePosition, splitSelectSource.getItemInfo(),
splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
- updateDesktopTaskVisibility(false /* visible */);
- }
-
- private void updateDesktopTaskVisibility(boolean visible) {
- if (mDesktopTaskView != null) {
- mDesktopTaskView.setVisibility(visible ? VISIBLE : GONE);
- }
}
/**
@@ -5224,7 +5230,6 @@
mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE, INVALID_TASK_ID);
mSplitHiddenTaskView = null;
}
- updateDesktopTaskVisibility(true /* visible */);
}
private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
diff --git a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureLog.java
index 0eb6f88..23e245c 100644
--- a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureLog.java
@@ -21,6 +21,7 @@
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -70,14 +71,6 @@
addLog(event, null);
}
- public void addLog(@NonNull String event, int extras) {
- addLog(event, extras, null);
- }
-
- public void addLog(@NonNull String event, boolean extras) {
- addLog(event, extras, null);
- }
-
/**
* Adds a log to be printed at log-dump-time and track the associated event for error detection.
*
@@ -88,20 +81,6 @@
addLog(new CompoundString(event), gestureEvent);
}
- public void addLog(
- @NonNull String event,
- int extras,
- @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
- addLog(new CompoundString(event).append(": ").append(extras), gestureEvent);
- }
-
- public void addLog(
- @NonNull String event,
- boolean extras,
- @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
- addLog(new CompoundString(event).append(": ").append(extras), gestureEvent);
- }
-
public void addLog(@NonNull CompoundString compoundString) {
addLog(compoundString, null);
}
@@ -250,25 +229,27 @@
/** A buildable string stored as an array for memory efficiency. */
public static class CompoundString {
- public static final CompoundString NO_OP = new CompoundString();
+ public static final CompoundString NO_OP = new CompoundString(true);
private final List<String> mSubstrings;
private final List<Object> mArgs;
private final boolean mIsNoOp;
- private CompoundString() {
- this(null);
+ public static CompoundString newEmptyString() {
+ return new CompoundString(false);
}
- public CompoundString(String substring) {
- mIsNoOp = substring == null;
+ private CompoundString(boolean isNoOp) {
+ mIsNoOp = isNoOp;
mSubstrings = mIsNoOp ? null : new ArrayList<>();
mArgs = mIsNoOp ? null : new ArrayList<>();
+ }
- if (!mIsNoOp) {
- mSubstrings.add(substring);
- }
+ public CompoundString(String substring, Object... args) {
+ this(substring == null);
+
+ append(substring, args);
}
public CompoundString append(CompoundString substring) {
@@ -281,76 +262,24 @@
return this;
}
- public CompoundString append(String substring) {
+ public CompoundString append(String substring, Object... args) {
if (mIsNoOp) {
return this;
}
mSubstrings.add(substring);
+ mArgs.addAll(Arrays.stream(args).toList());
return this;
}
- public CompoundString append(int num) {
- if (mIsNoOp) {
- return this;
- }
- mArgs.add(num);
-
- return append("%d");
- }
-
- public CompoundString append(long num) {
- if (mIsNoOp) {
- return this;
- }
- mArgs.add(num);
-
- return append("%d");
- }
-
- public CompoundString append(float num) {
- if (mIsNoOp) {
- return this;
- }
- mArgs.add(num);
-
- return append("%.2f");
- }
-
- public CompoundString append(double num) {
- if (mIsNoOp) {
- return this;
- }
- mArgs.add(num);
-
- return append("%.2f");
- }
-
- public CompoundString append(boolean bool) {
- if (mIsNoOp) {
- return this;
- }
- mArgs.add(bool);
-
- return append("%b");
- }
-
- private Object[] getArgs() {
- return mArgs.toArray();
- }
-
@Override
public String toString() {
- return String.format(toUnformattedString(), getArgs());
- }
-
- private String toUnformattedString() {
+ if (mIsNoOp) return null;
StringBuilder sb = new StringBuilder();
for (String substring : mSubstrings) {
sb.append(substring);
}
-
- return sb.toString();
+ return String.format(sb.toString(), mArgs.toArray());
}
@Override
@@ -360,10 +289,9 @@
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof CompoundString)) {
+ if (!(obj instanceof CompoundString other)) {
return false;
}
- CompoundString other = (CompoundString) obj;
return (mIsNoOp == other.mIsNoOp)
&& Objects.equals(mSubstrings, other.mSubstrings)
&& Objects.equals(mArgs, other.mArgs);
diff --git a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
index 308eeb5..f43a125 100644
--- a/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
+++ b/quickstep/src_protolog/com/android/quickstep/util/ActiveGestureProtoLogProxy.java
@@ -86,25 +86,20 @@
ActiveGestureErrorDetector.GestureEvent.CANCEL_CURRENT_ANIMATION);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "AbsSwipeUpHandler.cancelCurrentAnimation");
-
}
public static void logAbsSwipeUpHandlerOnTasksAppeared() {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "AbsSwipeUpHandler.onTasksAppeared: ")
- .append("force finish recents animation complete; clearing state callback."));
+ ActiveGestureLog.INSTANCE.addLog("AbsSwipeUpHandler.onTasksAppeared: "
+ + "force finish recents animation complete; clearing state callback.");
if (!enableActiveGestureProtoLog()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG,
- "AbsSwipeUpHandler.onTasksAppeared: force finish recents animation complete; "
- + "clearing state callback.");
-
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "AbsSwipeUpHandler.onTasksAppeared: "
+ + "force finish recents animation complete; clearing state callback.");
}
public static void logFinishRecentsAnimationOnTasksAppeared() {
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimationOnTasksAppeared");
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "finishRecentsAnimationOnTasksAppeared");
-
}
public static void logRecentsAnimationCallbacksOnAnimationCancelled() {
@@ -113,7 +108,6 @@
/* gestureEvent= */ ON_CANCEL_RECENTS_ANIMATION);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "RecentsAnimationCallbacks.onAnimationCanceled");
-
}
public static void logRecentsAnimationCallbacksOnTasksAppeared() {
@@ -121,7 +115,6 @@
ActiveGestureErrorDetector.GestureEvent.TASK_APPEARED);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "RecentsAnimationCallbacks.onTasksAppeared");
-
}
public static void logStartRecentsAnimation() {
@@ -130,21 +123,18 @@
/* gestureEvent= */ START_RECENTS_ANIMATION);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "TaskAnimationManager.startRecentsAnimation");
-
}
public static void logLaunchingSideTaskFailed() {
ActiveGestureLog.INSTANCE.addLog("Unable to launch side task (no recents)");
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "Unable to launch side task (no recents)");
-
}
public static void logContinueRecentsAnimation() {
ActiveGestureLog.INSTANCE.addLog(/* event= */ "continueRecentsAnimation");
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "continueRecentsAnimation");
-
}
public static void logCleanUpRecentsAnimationSkipped() {
@@ -152,46 +142,39 @@
/* event= */ "cleanUpRecentsAnimation skipped due to wrong callbacks");
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "cleanUpRecentsAnimation skipped due to wrong callbacks");
-
}
public static void logCleanUpRecentsAnimation() {
ActiveGestureLog.INSTANCE.addLog(/* event= */ "cleanUpRecentsAnimation");
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "cleanUpRecentsAnimation");
-
}
public static void logOnInputEventUserLocked() {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString("TIS.onInputEvent: ")
- .append("Cannot process input event: user is locked"));
+ ActiveGestureLog.INSTANCE.addLog(
+ "TIS.onInputEvent: Cannot process input event: user is locked");
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"TIS.onInputEvent: Cannot process input event: user is locked");
}
public static void logOnInputIgnoringFollowingEvents() {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("TIS.onMotionEvent: A new gesture has been ")
- .append("started, but a previously-requested recents ")
- .append("animation hasn't started. Ignoring all following ")
- .append("motion events."),
+ ActiveGestureLog.INSTANCE.addLog("TIS.onMotionEvent: A new gesture has been started, "
+ + "but a previously-requested recents animation hasn't started. "
+ + "Ignoring all following motion events.",
RECENTS_ANIMATION_START_PENDING);
if (!enableActiveGestureProtoLog()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG,
- "TIS.onMotionEvent: A new gesture has been started, but a "
- + "previously-requested recents animation hasn't started. "
- + "Ignoring all following motion events.");
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onMotionEvent: A new gesture has been started, "
+ + "but a previously-requested recents animation hasn't started. "
+ + "Ignoring all following motion events.");
}
public static void logOnInputEventThreeButtonNav() {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString("TIS.onInputEvent: ")
- .append("Cannot process input event: ")
- .append("using 3-button nav and event is not a trackpad event"));
+ ActiveGestureLog.INSTANCE.addLog("TIS.onInputEvent: Cannot process input event: "
+ + "using 3-button nav and event is not a trackpad event");
if (!enableActiveGestureProtoLog()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG,
- "TIS.onInputEvent: Cannot process input event: using 3-button nav and "
- + "event is not a trackpad event");
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onInputEvent: Cannot process input event: "
+ + "using 3-button nav and event is not a trackpad event");
}
public static void logPreloadRecentsAnimation() {
@@ -226,31 +209,23 @@
}
public static void logInputConsumerBecameActive(@NonNull String consumerName) {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(consumerName)
- .append(" became active"));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "%s became active", consumerName));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "%s became active", consumerName);
}
public static void logTaskLaunchFailed(int launchedTaskId) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("Launch failed, task (id=")
- .append(launchedTaskId)
- .append(") finished mid transition"));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Launch failed, task (id=%d) finished mid transition", launchedTaskId));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"Launch failed, task (id=%d) finished mid transition", launchedTaskId);
}
- public static void logMotionPauseDetectorEvent(@NonNull String event) {
- ActiveGestureLog.INSTANCE.addLog(event);
- if (!enableActiveGestureProtoLog()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG, "MotionPauseDetector: %s", event);
- }
-
public static void logOnPageEndTransition(int nextPageIndex) {
- ActiveGestureLog.INSTANCE.addLog(
- "onPageEndTransition: current page index updated", nextPageIndex);
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "onPageEndTransition: current page index updated: %d", nextPageIndex));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"onPageEndTransition: current page index updated: %d", nextPageIndex);
@@ -258,9 +233,8 @@
public static void logQuickSwitchFromHomeFallback(int taskIndex) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "Quick switch from home fallback case: The TaskView at index ")
- .append(taskIndex)
- .append(" is missing."),
+ "Quick switch from home fallback case: The TaskView at index %d is missing.",
+ taskIndex),
QUICK_SWITCH_FROM_HOME_FALLBACK);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
@@ -270,9 +244,8 @@
public static void logQuickSwitchFromHomeFailed(int taskIndex) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "Quick switch from home failed: TaskViews at indices ")
- .append(taskIndex)
- .append(" and 0 are missing."),
+ "Quick switch from home failed: TaskViews at indices %d and 0 are missing.",
+ taskIndex),
QUICK_SWITCH_FROM_HOME_FAILED);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
@@ -281,50 +254,44 @@
}
public static void logFinishRecentsAnimation(boolean toRecents) {
- ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "finishRecentsAnimation",
- /* extras= */ toRecents,
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "finishRecentsAnimation: %b", toRecents),
/* gestureEvent= */ FINISH_RECENTS_ANIMATION);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "finishRecentsAnimation: %b", toRecents);
}
public static void logSetEndTarget(@NonNull String target) {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString("setEndTarget ")
- .append(target),
- /* gestureEvent= */ SET_END_TARGET);
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "setEndTarget %s", target), /* gestureEvent= */ SET_END_TARGET);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "setEndTarget %s", target);
}
public static void logStartHomeIntent(@NonNull String reason) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "OverviewComponentObserver.startHomeIntent: ").append(reason));
+ "OverviewComponentObserver.startHomeIntent: %s", reason));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "OverviewComponentObserver.startHomeIntent: %s", reason);
}
public static void logRunningTaskPackage(@NonNull String packageName) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("Current running task package name=")
- .append(packageName));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Current running task package name=%s", packageName));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "Current running task package name=%s", packageName);
}
public static void logSysuiStateFlags(@NonNull String stateFlags) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("Current SystemUi state flags=")
- .append(stateFlags));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Current SystemUi state flags=%s", stateFlags));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "Current SystemUi state flags=%s", stateFlags);
}
public static void logSetInputConsumer(@NonNull String consumerName, @NonNull String reason) {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString("setInputConsumer: ")
- .append(consumerName)
- .append(". reason(s):")
- .append(reason));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "setInputConsumer: %s. reason(s):%s", consumerName, reason));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"setInputConsumer: %s. reason(s):%s", consumerName, reason);
@@ -332,12 +299,11 @@
public static void logUpdateGestureStateRunningTask(
@NonNull String otherTaskPackage, @NonNull String runningTaskPackage) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("Changing active task to ")
- .append(otherTaskPackage)
- .append(" because the previous task running on top of this one (")
- .append(runningTaskPackage)
- .append(") was excluded from recents"));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Changing active task to %s because the previous task running on top of this "
+ + "one (%s) was excluded from recents",
+ otherTaskPackage,
+ runningTaskPackage));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"Changing active task to %s because the previous task running on top of this "
@@ -349,15 +315,8 @@
public static void logOnInputEventActionUp(
int x, int y, int action, @NonNull String classification) {
String actionString = MotionEvent.actionToString(action);
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("onMotionEvent(")
- .append(x)
- .append(", ")
- .append(y)
- .append("): ")
- .append(actionString)
- .append(", ")
- .append(classification),
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "onMotionEvent(%d, %d): %s, %s", x, y, actionString, classification),
/* gestureEvent= */ action == ACTION_DOWN
? MOTION_DOWN
: MOTION_UP);
@@ -368,13 +327,11 @@
public static void logOnInputEventActionMove(
@NonNull String action, @NonNull String classification, int pointerCount) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("onMotionEvent: ")
- .append(action)
- .append(",")
- .append(classification)
- .append(", pointerCount: ")
- .append(pointerCount),
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "onMotionEvent: %s, %s, pointerCount: %d",
+ action,
+ classification,
+ pointerCount),
MOTION_MOVE);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
@@ -383,23 +340,19 @@
public static void logOnInputEventGenericAction(
@NonNull String action, @NonNull String classification) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("onMotionEvent: ")
- .append(action)
- .append(",")
- .append(classification));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "onMotionEvent: %s, %s", action, classification));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "onMotionEvent: %s, %s", action, classification);
}
public static void logOnInputEventNavModeSwitched(
@NonNull String startNavMode, @NonNull String currentNavMode) {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString("TIS.onInputEvent: ")
- .append("Navigation mode switched mid-gesture (")
- .append(startNavMode)
- .append(" -> ")
- .append(currentNavMode)
- .append("); cancelling gesture."),
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "TIS.onInputEvent: Navigation mode switched mid-gesture (%s -> %s); "
+ + "cancelling gesture.",
+ startNavMode,
+ currentNavMode),
NAVIGATION_MODE_SWITCHED);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
@@ -410,84 +363,100 @@
}
public static void logUnknownInputEvent(@NonNull String event) {
- ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString("TIS.onInputEvent: ")
- .append("Cannot process input event: received unknown event ")
- .append(event));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "TIS.onInputEvent: Cannot process input event: received unknown event %s", event));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"TIS.onInputEvent: Cannot process input event: received unknown event %s", event);
-
}
public static void logFinishRunningRecentsAnimation(boolean toHome) {
- ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "finishRunningRecentsAnimation", toHome);
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "finishRunningRecentsAnimation: %b", toHome));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "finishRunningRecentsAnimation: %b", toHome);
-
}
public static void logOnRecentsAnimationStartCancelled() {
- ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "RecentsAnimationCallbacks.onAnimationStart (canceled)",
- /* extras= */ 0,
+ ActiveGestureLog.INSTANCE.addLog("RecentsAnimationCallbacks.onAnimationStart (canceled): 0",
/* gestureEvent= */ ON_START_RECENTS_ANIMATION);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "RecentsAnimationCallbacks.onAnimationStart (canceled): 0");
-
}
public static void logOnRecentsAnimationStart(int appCount) {
- ActiveGestureLog.INSTANCE.addLog(
- /* event= */ "RecentsAnimationCallbacks.onAnimationStart",
- /* extras= */ appCount,
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "RecentsAnimationCallbacks.onAnimationStart (canceled): %d", appCount),
/* gestureEvent= */ ON_START_RECENTS_ANIMATION);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"RecentsAnimationCallbacks.onAnimationStart (canceled): %d", appCount);
-
}
public static void logStartRecentsAnimationCallback(@NonNull String callback) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "TaskAnimationManager.startRecentsAnimation(")
- .append(callback)
- .append("): ")
- .append("Setting mRecentsAnimationStartPending = false"));
+ "TaskAnimationManager.startRecentsAnimation(%s): "
+ + "Setting mRecentsAnimationStartPending = false",
+ callback));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"TaskAnimationManager.startRecentsAnimation(%s): "
+ "Setting mRecentsAnimationStartPending = false",
callback);
-
}
public static void logSettingRecentsAnimationStartPending(boolean value) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
- "TaskAnimationManager.startRecentsAnimation: ")
- .append("Setting mRecentsAnimationStartPending = ")
- .append(value));
+ "TaskAnimationManager.startRecentsAnimation: "
+ + "Setting mRecentsAnimationStartPending = %b",
+ value));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"TaskAnimationManager.startRecentsAnimation: "
+ "Setting mRecentsAnimationStartPending = %b",
value);
-
}
public static void logLaunchingSideTask(int taskId) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("Launching side task id=")
- .append(taskId));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Launching side task id=%d", taskId));
if (!enableActiveGestureProtoLog()) return;
- ProtoLog.d(ACTIVE_GESTURE_LOG, "Launching side task id=", taskId);
-
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "Launching side task id=%d", taskId);
}
- public static void logDynamicString(@NonNull String string) {
- logDynamicString(string, null);
+ public static void logOnInputEventActionDown(@NonNull ActiveGestureLog.CompoundString reason) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "TIS.onMotionEvent: ").append(reason));
+ if (!enableActiveGestureProtoLog()) return;
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onMotionEvent: %s", reason.toString());
}
+ public static void logStartNewTask(@NonNull ActiveGestureLog.CompoundString tasks) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Launching task: ").append(tasks));
+ if (!enableActiveGestureProtoLog()) return;
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "TIS.onMotionEvent: %s", tasks.toString());
+ }
+
+ public static void logMotionPauseDetectorEvent(@NonNull ActiveGestureLog.CompoundString event) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "MotionPauseDetector: ").append(event));
+ if (!enableActiveGestureProtoLog()) return;
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "MotionPauseDetector: %s", event.toString());
+ }
+
+ public static void logHandleTaskAppearedFailed(
+ @NonNull ActiveGestureLog.CompoundString reason) {
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "handleTaskAppeared check failed: ").append(reason));
+ if (!enableActiveGestureProtoLog()) return;
+ ProtoLog.d(ACTIVE_GESTURE_LOG, "handleTaskAppeared check failed: %s", reason.toString());
+ }
+
+ /**
+ * This is for special cases where the string is purely dynamic and therefore has no format that
+ * can be extracted. Do not use in any other case.
+ */
public static void logDynamicString(
@NonNull String string,
@Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
@@ -497,22 +466,19 @@
}
public static void logOnSettledOnEndTarget(@NonNull String endTarget) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("onSettledOnEndTarget ")
- .append(endTarget),
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "onSettledOnEndTarget %s", endTarget),
/* gestureEvent= */ ON_SETTLED_ON_END_TARGET);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG, "onSettledOnEndTarget %s", endTarget);
}
public static void logOnCalculateEndTarget(float velocityX, float velocityY, double angle) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("calculateEndTarget: velocities=(x=")
- .append(velocityX)
- .append("dp/ms, y=")
- .append(velocityY)
- .append("dp/ms), angle=")
- .append(angle),
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "calculateEndTarget: velocities=(x=%fdp/ms, y=%fdp/ms), angle=%f",
+ velocityX,
+ velocityY,
+ angle),
velocityX == 0 && velocityY == 0 ? INVALID_VELOCITY_ON_SWIPE_UP : null);
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
@@ -523,12 +489,10 @@
}
public static void logUnexpectedTaskAppeared(int taskId, @NonNull String packageName) {
- ActiveGestureLog.INSTANCE.addLog(
- new ActiveGestureLog.CompoundString("Forcefully finishing recents animation: ")
- .append("Unexpected task appeared id=")
- .append(taskId)
- .append(" pkg=")
- .append(packageName));
+ ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
+ "Forcefully finishing recents animation: Unexpected task appeared id=%d, pkg=%s",
+ taskId,
+ packageName));
if (!enableActiveGestureProtoLog()) return;
ProtoLog.d(ACTIVE_GESTURE_LOG,
"Forcefully finishing recents animation: Unexpected task appeared id=%d, pkg=%s",
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt
index 82a7625..b5a418b 100644
--- a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt
@@ -98,7 +98,7 @@
// if we're still expanding, wait with taking a screenshot
val shouldWait: (ComponentActivity, View) -> Boolean = { _, _ -> bubbleBarView.isExpanding }
// increase the frame limit to allow the animation to end before taking the screenshot
- screenshotRule.frameLimit = 50
+ screenshotRule.frameLimit = 500
screenshotRule.screenshotTest(
"bubbleBarView_expanded_threeBubbles",
checkView = shouldWait,
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt
index 537a755..50e2dcf 100644
--- a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutViewScreenshotTest.kt
@@ -18,6 +18,7 @@
import android.content.Context
import android.graphics.Color
+import android.graphics.PointF
import android.graphics.drawable.ColorDrawable
import androidx.test.core.app.ApplicationProvider
import com.google.android.apps.nexuslauncher.imagecomparison.goldenpathmanager.ViewScreenshotGoldenPathManager
@@ -59,15 +60,17 @@
fun bubbleBarFlyoutView_noAvatar_onRight() {
screenshotRule.screenshotTest("bubbleBarFlyoutView_noAvatar_onRight") { activity ->
activity.actionBar?.hide()
- val flyout = BubbleBarFlyoutView(context, onLeft = false)
- flyout.setData(
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = false))
+ flyout.showFromCollapsed(
BubbleBarFlyoutMessage(
senderAvatar = null,
senderName = "sender",
message = "message",
isGroupChat = false,
)
- )
+ ) {}
+ flyout.updateExpansionProgress(1f)
flyout
}
}
@@ -76,15 +79,17 @@
fun bubbleBarFlyoutView_noAvatar_onLeft() {
screenshotRule.screenshotTest("bubbleBarFlyoutView_noAvatar_onLeft") { activity ->
activity.actionBar?.hide()
- val flyout = BubbleBarFlyoutView(context, onLeft = true)
- flyout.setData(
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = true))
+ flyout.showFromCollapsed(
BubbleBarFlyoutMessage(
senderAvatar = null,
senderName = "sender",
message = "message",
isGroupChat = false,
)
- )
+ ) {}
+ flyout.updateExpansionProgress(1f)
flyout
}
}
@@ -93,15 +98,17 @@
fun bubbleBarFlyoutView_noAvatar_longMessage() {
screenshotRule.screenshotTest("bubbleBarFlyoutView_noAvatar_longMessage") { activity ->
activity.actionBar?.hide()
- val flyout = BubbleBarFlyoutView(context, onLeft = true)
- flyout.setData(
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = true))
+ flyout.showFromCollapsed(
BubbleBarFlyoutMessage(
senderAvatar = null,
senderName = "sender",
message = "really, really, really, really, really long message. like really.",
isGroupChat = false,
)
- )
+ ) {}
+ flyout.updateExpansionProgress(1f)
flyout
}
}
@@ -110,15 +117,17 @@
fun bubbleBarFlyoutView_avatar_onRight() {
screenshotRule.screenshotTest("bubbleBarFlyoutView_avatar_onRight") { activity ->
activity.actionBar?.hide()
- val flyout = BubbleBarFlyoutView(context, onLeft = false)
- flyout.setData(
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = false))
+ flyout.showFromCollapsed(
BubbleBarFlyoutMessage(
senderAvatar = ColorDrawable(Color.RED),
senderName = "sender",
message = "message",
isGroupChat = true,
)
- )
+ ) {}
+ flyout.updateExpansionProgress(1f)
flyout
}
}
@@ -127,15 +136,17 @@
fun bubbleBarFlyoutView_avatar_onLeft() {
screenshotRule.screenshotTest("bubbleBarFlyoutView_avatar_onLeft") { activity ->
activity.actionBar?.hide()
- val flyout = BubbleBarFlyoutView(context, onLeft = true)
- flyout.setData(
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = true))
+ flyout.showFromCollapsed(
BubbleBarFlyoutMessage(
senderAvatar = ColorDrawable(Color.RED),
senderName = "sender",
message = "message",
isGroupChat = true,
)
- )
+ ) {}
+ flyout.updateExpansionProgress(1f)
flyout
}
}
@@ -144,16 +155,115 @@
fun bubbleBarFlyoutView_avatar_longMessage() {
screenshotRule.screenshotTest("bubbleBarFlyoutView_avatar_longMessage") { activity ->
activity.actionBar?.hide()
- val flyout = BubbleBarFlyoutView(context, onLeft = true)
- flyout.setData(
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = true))
+ flyout.showFromCollapsed(
BubbleBarFlyoutMessage(
senderAvatar = ColorDrawable(Color.RED),
senderName = "sender",
message = "really, really, really, really, really long message. like really.",
isGroupChat = true,
)
- )
+ ) {}
+ flyout.updateExpansionProgress(1f)
flyout
}
}
+
+ @Test
+ fun bubbleBarFlyoutView_collapsed_onLeft() {
+ screenshotRule.screenshotTest("bubbleBarFlyoutView_collapsed_onLeft") { activity ->
+ activity.actionBar?.hide()
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = true))
+ flyout.showFromCollapsed(
+ BubbleBarFlyoutMessage(
+ senderAvatar = ColorDrawable(Color.RED),
+ senderName = "sender",
+ message = "collapsed on left",
+ isGroupChat = true,
+ )
+ ) {}
+ flyout.updateExpansionProgress(0f)
+ flyout
+ }
+ }
+
+ @Test
+ fun bubbleBarFlyoutView_collapsed_onRight() {
+ screenshotRule.screenshotTest("bubbleBarFlyoutView_collapsed_onRight") { activity ->
+ activity.actionBar?.hide()
+ val flyout =
+ BubbleBarFlyoutView(context, FakeBubbleBarFlyoutPositioner(isOnLeft = false))
+ flyout.showFromCollapsed(
+ BubbleBarFlyoutMessage(
+ senderAvatar = ColorDrawable(Color.RED),
+ senderName = "sender",
+ message = "collapsed on right",
+ isGroupChat = true,
+ )
+ ) {}
+ flyout.updateExpansionProgress(0f)
+ flyout
+ }
+ }
+
+ @Test
+ fun bubbleBarFlyoutView_90p_onLeft() {
+ screenshotRule.screenshotTest("bubbleBarFlyoutView_90p_onLeft") { activity ->
+ activity.actionBar?.hide()
+ val flyout =
+ BubbleBarFlyoutView(
+ context,
+ FakeBubbleBarFlyoutPositioner(
+ isOnLeft = true,
+ distanceToCollapsedPosition = PointF(100f, 100f),
+ ),
+ )
+ flyout.showFromCollapsed(
+ BubbleBarFlyoutMessage(
+ senderAvatar = ColorDrawable(Color.RED),
+ senderName = "sender",
+ message = "collapsed 90% on left",
+ isGroupChat = true,
+ )
+ ) {}
+ flyout.updateExpansionProgress(0.9f)
+ flyout
+ }
+ }
+
+ @Test
+ fun bubbleBarFlyoutView_80p_onRight() {
+ screenshotRule.screenshotTest("bubbleBarFlyoutView_80p_onRight") { activity ->
+ activity.actionBar?.hide()
+ val flyout =
+ BubbleBarFlyoutView(
+ context,
+ FakeBubbleBarFlyoutPositioner(
+ isOnLeft = false,
+ distanceToCollapsedPosition = PointF(200f, 100f),
+ ),
+ )
+ flyout.showFromCollapsed(
+ BubbleBarFlyoutMessage(
+ senderAvatar = ColorDrawable(Color.RED),
+ senderName = "sender",
+ message = "collapsed 80% on right",
+ isGroupChat = true,
+ )
+ ) {}
+ flyout.updateExpansionProgress(0.8f)
+ flyout
+ }
+ }
+
+ private class FakeBubbleBarFlyoutPositioner(
+ override val isOnLeft: Boolean,
+ override val distanceToCollapsedPosition: PointF = PointF(0f, 0f),
+ ) : BubbleBarFlyoutPositioner {
+ override val targetTy = 0f
+ override val collapsedSize = 30f
+ override val collapsedColor = Color.BLUE
+ }
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt
index 97847be..3b6952d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarSwipeControllerTest.kt
@@ -25,6 +25,7 @@
import com.android.launcher3.touch.OverScroll
import com.google.common.truth.Truth.assertThat
import java.util.Optional
+import kotlin.math.abs
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -46,11 +47,13 @@
const val UNSTASH_THRESHOLD = 100
const val EXPAND_THRESHOLD = 200
const val MAX_OVERSCROLL = 300
+ const val STASH_THRESHOLD = 50
const val UP_BELOW_UNSTASH = -UNSTASH_THRESHOLD + 10f
const val UP_ABOVE_UNSTASH = -UNSTASH_THRESHOLD - 10f
const val UP_ABOVE_EXPAND = -EXPAND_THRESHOLD - 10f
- const val DOWN_BELOW_UNSTASH = UNSTASH_THRESHOLD + 10f
+ const val DOWN_UNDER_STASH = STASH_THRESHOLD - 10f
+ const val DOWN_OVER_STASH = STASH_THRESHOLD + 10f
}
private val context = ApplicationProvider.getApplicationContext<Context>()
@@ -82,6 +85,9 @@
override val maxOverscroll: Int
get() = MAX_OVERSCROLL
+
+ override val stashThreshold: Int
+ get() = STASH_THRESHOLD
}
bubbleBarSwipeController = BubbleBarSwipeController(context, dimensionProvider)
@@ -102,8 +108,12 @@
bubbleBarSwipeController.init(bubbleControllers)
}
+ // region Test that views have damped translation on swipe
+
private fun testViewsHaveDampedTranslationOnSwipe(swipe: Float) {
- val dampedTranslation = -OverScroll.dampedScroll(-swipe, MAX_OVERSCROLL).toFloat()
+ val isUp = swipe < 0
+ val damped = OverScroll.dampedScroll(abs(swipe), MAX_OVERSCROLL).toFloat()
+ val dampedTranslation = if (isUp) -damped else damped
getInstrumentation().runOnMainSync {
bubbleBarSwipeController.start()
bubbleBarSwipeController.swipeTo(swipe)
@@ -142,6 +152,22 @@
testViewsHaveDampedTranslationOnSwipe(UP_ABOVE_EXPAND)
}
+ @Test
+ fun swipeDown_collapsedBar_belowStashThreshold_viewsHaveDampedTranslation() {
+ setUpCollapsedBar()
+ testViewsHaveDampedTranslationOnSwipe(DOWN_UNDER_STASH)
+ }
+
+ @Test
+ fun swipeDown_collapsedBar_overStashThreshold_viewsHaveDampedTranslation() {
+ setUpCollapsedBar()
+ testViewsHaveDampedTranslationOnSwipe(DOWN_OVER_STASH)
+ }
+
+ // endregion
+
+ // region Test that translation on views is reset on finish
+
private fun testViewsTranslationResetOnFinish(swipe: Float) {
getInstrumentation().runOnMainSync {
bubbleBarSwipeController.start()
@@ -195,6 +221,16 @@
}
@Test
+ fun swipeDown_collapsedBar_aboveStashThreshold_animateTranslationToZeroOnFinish() {
+ setUpCollapsedBar()
+ testViewsTranslationResetOnFinish(DOWN_OVER_STASH)
+ }
+
+ // endregion
+
+ // region Test swipe interactions on stashed bar
+
+ @Test
fun swipeUp_stashedBar_belowUnstashThreshold_doesNotShowBar() {
setUpStashedBar()
getInstrumentation().runOnMainSync {
@@ -282,12 +318,28 @@
}
@Test
- fun swipeUp_expandedBar_swipeIgnored() {
+ fun swipeDown_stashedBar_swipeIgnored() {
+ setUpStashedBar()
+ getInstrumentation().runOnMainSync {
+ bubbleBarSwipeController.start()
+ bubbleBarSwipeController.swipeTo(DOWN_OVER_STASH)
+ }
+ verify(bubbleStashedHandleViewController, never()).setTranslationYForSwipe(any())
+ verify(bubbleBarViewController, never()).setTranslationYForSwipe(any())
+ verify(bubbleStashController, never()).showBubbleBar(any())
+ }
+
+ // endregion
+
+ // region Test swipe interactions on expanded bar
+
+ @Test
+ fun swipe_expandedBar_swipeIgnored() {
setUpExpandedBar()
getInstrumentation().runOnMainSync {
bubbleBarSwipeController.start()
bubbleBarSwipeController.swipeTo(UP_ABOVE_EXPAND)
- bubbleBarSwipeController.swipeTo(DOWN_BELOW_UNSTASH)
+ bubbleBarSwipeController.swipeTo(DOWN_OVER_STASH)
bubbleBarSwipeController.finish()
}
verify(bubbleStashedHandleViewController, never()).setTranslationYForSwipe(any())
@@ -295,18 +347,55 @@
verify(bubbleStashController, never()).showBubbleBar(any())
}
+ // endregion
+
+ // region Test swipe interactions on collapsed bar
+
@Test
- fun swipeDown_stashedBar_swipeIgnored() {
- setUpStashedBar()
+ fun swipeDown_collapsedBar_underStashThreshold_doesNotHideBar() {
+ setUpCollapsedBar()
getInstrumentation().runOnMainSync {
bubbleBarSwipeController.start()
- bubbleBarSwipeController.swipeTo(DOWN_BELOW_UNSTASH)
+ bubbleBarSwipeController.swipeTo(DOWN_UNDER_STASH)
+ bubbleBarSwipeController.finish()
}
- verify(bubbleStashedHandleViewController, never()).setTranslationYForSwipe(any())
- verify(bubbleBarViewController, never()).setTranslationYForSwipe(any())
- verify(bubbleStashController, never()).showBubbleBar(any())
+ verify(bubbleStashController, never()).stashBubbleBar()
}
+ @Test
+ fun swipeDown_collapsedBar_overStashThreshold_doesNotHideBarBeforeFinish() {
+ setUpCollapsedBar()
+ getInstrumentation().runOnMainSync {
+ bubbleBarSwipeController.start()
+ bubbleBarSwipeController.swipeTo(DOWN_OVER_STASH)
+ }
+ verify(bubbleStashController, never()).stashBubbleBar()
+ getInstrumentation().runOnMainSync { bubbleBarSwipeController.finish() }
+ verify(bubbleStashController).stashBubbleBar()
+ }
+
+ @Test
+ fun swipeDown_collapsedBar_underStashThreshold_isSwipeGestureFalse() {
+ setUpCollapsedBar()
+ getInstrumentation().runOnMainSync {
+ bubbleBarSwipeController.start()
+ bubbleBarSwipeController.swipeTo(DOWN_UNDER_STASH)
+ }
+ assertThat(bubbleBarSwipeController.isSwipeGesture()).isFalse()
+ }
+
+ @Test
+ fun swipeDown_collapsedBar_overStashThreshold_isSwipeGestureTrue() {
+ setUpCollapsedBar()
+ getInstrumentation().runOnMainSync {
+ bubbleBarSwipeController.start()
+ bubbleBarSwipeController.swipeTo(DOWN_OVER_STASH)
+ }
+ assertThat(bubbleBarSwipeController.isSwipeGesture()).isTrue()
+ }
+
+ // endregion
+
private fun setUpStashedBar() {
whenever(bubbleStashController.isStashed).thenReturn(true)
whenever(bubbleStashController.isBubbleBarVisible()).thenReturn(false)
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt
index a58ce08..0f02444 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/flyout/BubbleBarFlyoutControllerTest.kt
@@ -17,6 +17,8 @@
package com.android.launcher3.taskbar.bubbles.flyout
import android.content.Context
+import android.graphics.Color
+import android.graphics.PointF
import android.view.Gravity
import android.widget.FrameLayout
import android.widget.TextView
@@ -46,11 +48,13 @@
flyoutContainer = FrameLayout(context)
val positioner =
object : BubbleBarFlyoutPositioner {
- override val isOnLeft: Boolean
+ override val isOnLeft
get() = onLeft
- override val targetTy: Float
- get() = 50f
+ override val targetTy = 50f
+ override val distanceToCollapsedPosition = PointF(100f, 200f)
+ override val collapsedSize = 30f
+ override val collapsedColor = Color.BLUE
}
flyoutController = BubbleBarFlyoutController(flyoutContainer, positioner)
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
index 99d3121..541a48d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/AppPairsControllerTest.kt
@@ -28,9 +28,9 @@
import com.android.quickstep.TopTaskTracker.CachedTaskInfo
import com.android.systemui.shared.recents.model.Task
import com.android.systemui.shared.recents.model.Task.TaskKey
-import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_30_70
-import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50
-import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_70_30
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_33_66
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_66_33
import java.util.function.Consumer
import org.junit.Assert.assertEquals
import org.junit.Before
@@ -59,23 +59,23 @@
private lateinit var appPairsController: AppPairsController
- private val left30: Int by lazy {
- appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_30_70)
+ private val left33: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_2_33_66)
}
private val left50: Int by lazy {
- appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_50_50)
+ appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_2_50_50)
}
- private val left70: Int by lazy {
- appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_70_30)
+ private val left66: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_TOP_OR_LEFT, SNAP_TO_2_66_33)
}
- private val right30: Int by lazy {
- appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_30_70)
+ private val right33: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_2_33_66)
}
private val right50: Int by lazy {
- appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_50_50)
+ appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_2_50_50)
}
- private val right70: Int by lazy {
- appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_70_30)
+ private val right66: Int by lazy {
+ appPairsController.encodeRank(STAGE_POSITION_BOTTOM_OR_RIGHT, SNAP_TO_2_66_33)
}
@Mock lateinit var mockAppPairIcon: AppPairIcon
@@ -113,26 +113,26 @@
@Test
fun shouldEncodeRankCorrectly() {
- assertEquals("left + 30-70 should encode as 0 (0b0)", 0, left30)
+ assertEquals("left + 33-66 should encode as 0 (0b0)", 0, left33)
assertEquals("left + 50-50 should encode as 1 (0b1)", 1, left50)
- assertEquals("left + 70-30 should encode as 2 (0b10)", 2, left70)
+ assertEquals("left + 66-33 should encode as 2 (0b10)", 2, left66)
// See AppPairsController#BITMASK_SIZE and BITMASK_FOR_SNAP_POSITION for context
- assertEquals("right + 30-70 should encode as 1 followed by 16 0s", 1 shl 16, right30)
+ assertEquals("right + 33-66 should encode as 1 followed by 16 0s", 1 shl 16, right33)
assertEquals("right + 50-50 should encode as the above value + 1", (1 shl 16) + 1, right50)
- assertEquals("right + 70-30 should encode as the above value + 2", (1 shl 16) + 2, right70)
+ assertEquals("right + 66-33 should encode as the above value + 2", (1 shl 16) + 2, right66)
}
@Test
fun shouldDecodeRankCorrectly() {
assertEquals(
- "left + 30-70 should decode to left",
+ "left + 33-66 should decode to left",
STAGE_POSITION_TOP_OR_LEFT,
- AppPairsController.convertRankToStagePosition(left30),
+ AppPairsController.convertRankToStagePosition(left33),
)
assertEquals(
- "left + 30-70 should decode to 30-70",
- SNAP_TO_30_70,
- AppPairsController.convertRankToSnapPosition(left30),
+ "left + 33-66 should decode to 33-66",
+ SNAP_TO_2_33_66,
+ AppPairsController.convertRankToSnapPosition(left33),
)
assertEquals(
@@ -142,30 +142,30 @@
)
assertEquals(
"left + 50-50 should decode to 50-50",
- SNAP_TO_50_50,
+ SNAP_TO_2_50_50,
AppPairsController.convertRankToSnapPosition(left50),
)
assertEquals(
- "left + 70-30 should decode to left",
+ "left + 66-33 should decode to left",
STAGE_POSITION_TOP_OR_LEFT,
- AppPairsController.convertRankToStagePosition(left70),
+ AppPairsController.convertRankToStagePosition(left66),
)
assertEquals(
- "left + 70-30 should decode to 70-30",
- SNAP_TO_70_30,
- AppPairsController.convertRankToSnapPosition(left70),
+ "left + 66-33 should decode to 66-33",
+ SNAP_TO_2_66_33,
+ AppPairsController.convertRankToSnapPosition(left66),
)
assertEquals(
- "right + 30-70 should decode to right",
+ "right + 33-66 should decode to right",
STAGE_POSITION_BOTTOM_OR_RIGHT,
- AppPairsController.convertRankToStagePosition(right30),
+ AppPairsController.convertRankToStagePosition(right33),
)
assertEquals(
- "right + 30-70 should decode to 30-70",
- SNAP_TO_30_70,
- AppPairsController.convertRankToSnapPosition(right30),
+ "right + 33-66 should decode to 33-66",
+ SNAP_TO_2_33_66,
+ AppPairsController.convertRankToSnapPosition(right33),
)
assertEquals(
@@ -175,19 +175,19 @@
)
assertEquals(
"right + 50-50 should decode to 50-50",
- SNAP_TO_50_50,
+ SNAP_TO_2_50_50,
AppPairsController.convertRankToSnapPosition(right50),
)
assertEquals(
- "right + 70-30 should decode to right",
+ "right + 66-33 should decode to right",
STAGE_POSITION_BOTTOM_OR_RIGHT,
- AppPairsController.convertRankToStagePosition(right70),
+ AppPairsController.convertRankToStagePosition(right66),
)
assertEquals(
- "right + 70-30 should decode to 70-30",
- SNAP_TO_70_30,
- AppPairsController.convertRankToSnapPosition(right70),
+ "right + 66-33 should decode to 66-33",
+ SNAP_TO_2_66_33,
+ AppPairsController.convertRankToSnapPosition(right66),
)
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
index 7b1c066..108cfb5 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
@@ -66,7 +66,7 @@
Rect(),
1,
2,
- SplitScreenConstants.SNAP_TO_50_50
+ SplitScreenConstants.SNAP_TO_2_50_50
)
val task1 = GroupTask(createTask(1), createTask(2), splitBounds, TaskViewType.GROUPED)
val task2 = GroupTask(createTask(1), createTask(2), splitBounds, TaskViewType.GROUPED)
@@ -81,7 +81,7 @@
Rect(),
1,
2,
- SplitScreenConstants.SNAP_TO_50_50
+ SplitScreenConstants.SNAP_TO_2_50_50
)
val splitBounds2 =
SplitConfigurationOptions.SplitBounds(
@@ -89,7 +89,7 @@
Rect(),
1,
2,
- SplitScreenConstants.SNAP_TO_30_70
+ SplitScreenConstants.SNAP_TO_2_33_66
)
val task1 = GroupTask(createTask(1), createTask(2), splitBounds1, TaskViewType.GROUPED)
val task2 = GroupTask(createTask(1), createTask(2), splitBounds2, TaskViewType.GROUPED)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 936e996..9d0b2ab 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -38,7 +38,7 @@
import com.android.quickstep.util.SplitSelectStateController.SplitFromDesktopController
import com.android.quickstep.views.RecentsViewContainer
import com.android.systemui.shared.recents.model.Task
-import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_50_50
+import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
@@ -642,7 +642,7 @@
return GroupTask(
task1,
task2,
- SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_50_50)
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_2_50_50)
)
}
@@ -674,7 +674,7 @@
return GroupTask(
task1,
task2,
- SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_50_50)
+ SplitConfigurationOptions.SplitBounds(Rect(), Rect(), -1, -1, SNAP_TO_2_50_50)
)
}
}
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index be91c0b..53dc4ba 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"የተከፈለ ማያ ገፅ"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"የመተግበሪያ መረጃ ለ%1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"የ%1$s የአጠቃቀም ቅንብሮች"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"አዲስ መስኮት"</string>
<string name="save_app_pair" msgid="5647523853662686243">"የመተግበሪያ ጥምረትን ያስቀምጡ"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 35ba183..002c800 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podeljeni ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji za: %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Podešavanja potrošnje za %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Novi prozor"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Sačuvaj par aplikacija"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ovaj par aplikacija nije podržan na ovom uređaju"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 1a2bcc1..0984f32 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Падзелены экран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Інфармацыя пра праграму для: %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s: налады выкарыстання"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Новае акно"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Захаваць спалучэнне праграм"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index e4bbd30..2b168f6 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni ekran"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Postavke korištenja za: %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Novi prozor"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Sačuvaj par aplikacija"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Par aplikacija nije podržan na uređaju"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 169afe5..ddcee65 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Información de la aplicación %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Ajustes de uso para %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Ventana nueva"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Guardar apps emparejadas"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"El dispositivo no admite esta aplicación emparejada"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index d841770..c0a6fe3 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -132,7 +132,7 @@
<string name="msg_missing_notification_access" msgid="281113995110910548">"برای نمایش «نقطههای اعلان»، اعلانهای برنامه را برای <xliff:g id="NAME">%1$s</xliff:g> روشن کنید"</string>
<string name="title_change_settings" msgid="1376365968844349552">"تغییر تنظیمات"</string>
<string name="notification_dots_service_title" msgid="4284221181793592871">"نمایش نقطههای اعلان"</string>
- <string name="developer_options_title" msgid="700788437593726194">"گزینههای برنامهنویس"</string>
+ <string name="developer_options_title" msgid="700788437593726194">"گزینههای توسعهدهندگان"</string>
<string name="auto_add_shortcuts_label" msgid="4926805029653694105">"افزودن نماد برنامهها به صفحه اصلی"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"برای برنامههای جدید"</string>
<string name="package_state_unknown" msgid="7592128424511031410">"نامشخص"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 3d5380a..a9fd14e 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Podijeljeni zaslon"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informacije o aplikaciji %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Postavke upotrebe za %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Novi prozor"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Spremi par aplikacija"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Taj par aplikacija nije podržan na ovom uređaju"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 7a87b26..0014317 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skipta skjá"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Upplýsingar um forrit fyrir %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Notkunarstillingar fyrir %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Nýr gluggi"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Vista forritapar"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Þetta forritapar er ekki stutt í þessu tæki"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index cea0a08..fc89041 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"分割画面"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s のアプリ情報"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s の使用設定"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"新しいウィンドウ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"アプリのペア設定を保存"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"このデバイスは、このアプリのペア設定に対応していません"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 2211a7d..f099bcd 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"ეკრანის გაყოფა"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s-ის აპის ინფო"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"გამოყენების პარამეტრები %1$s-ისთვის"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"ახალი ფანჯარა"</string>
<string name="save_app_pair" msgid="5647523853662686243">"აპთა წყვილის შენახვა"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ამ მოწყობილობაზე აღნიშნული აპთა წყვილი არ არის მხარდაჭერილი"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index ca26ea4..ebaacc9 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлу"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s қолданбасы туралы ақпарат"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s пайдалану параметрлері"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Жаңа терезе"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Қолданбаларды жұптау әрекетін сақтау"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды."</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index dc4fd80..b05eeb0 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"មុខងារបំបែកអេក្រង់"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"ព័ត៌មានកម្មវិធីសម្រាប់ %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"ការកំណត់ការប្រើប្រាស់សម្រាប់ %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"វិនដូថ្មី"</string>
<string name="save_app_pair" msgid="5647523853662686243">"រក្សាទុកគូកម្មវិធី"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index b326181..753d2dd 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Экранды бөлүү"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s колдонмосу жөнүндө маалымат"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s колдонмосун пайдалануу параметрлери"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Жаңы терезе"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Колдонмолорду сактап коюу"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index a613cb1..6879862 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Išskaidyto ekrano režimas"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Programos „%1$s“ informacija"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"„%1$s“ naudojimo nustatymai"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Naujas langas"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Išsaugoti programų porą"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ši programų pora šiame įrenginyje nepalaikoma"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 2eb1b2b..b9e68e0 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"സ്ക്രീൻ വിഭജന മോഡ്"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s എന്നതിന്റെ ആപ്പ് വിവരങ്ങൾ"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s എന്നതിനുള്ള ഉപയോഗ ക്രമീകരണം"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"പുതിയ വിന്ഡോ"</string>
<string name="save_app_pair" msgid="5647523853662686243">"ആപ്പ് ജോടി സംരക്ഷിക്കുക"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index b548e67..5ddf8a2 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Skrin pisah"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Maklumat apl untuk %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Tetapan penggunaan sebanyak %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Tetingkap Baharu"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Simpan gandingan apl"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Gandingan apl ini tidak disokong pada peranti ini"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 93c4339..4fae68b 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"स्प्लिट स्क्रिन"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s का हकमा एपसम्बन्धी जानकारी"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s को प्रयोगसम्बन्धी सेटिङ"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"नयाँ विन्डो"</string>
<string name="save_app_pair" msgid="5647523853662686243">"एपको पेयर सेभ गर्नुहोस्"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index c86c58d..d2b214e 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Ecrã dividido"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações da app para %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Definições de utilização para %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Nova janela"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Guardar par de apps"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Este par de apps não é suportado neste dispositivo"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index f10b93a..f864b3e 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Tela dividida"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Informações do app %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Configurações de uso de %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Nova janela"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Salvar par de apps"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Este Par de apps não está disponível no dispositivo"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index aea3d2b..126e3ad 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Разделить экран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Сведения о приложении \"%1$s\""</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Настройки использования приложения \"%1$s\""</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Новое окно"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Сохранить приложения"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Одновременно использовать эти два приложения на устройстве нельзя."</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index a3b9a71..328f2f5 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"බෙදුම් තිරය"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s සඳහා යෙදුම් තතු"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$s සඳහා භාවිත සැකසීම්"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"නව කවුළුව"</string>
<string name="save_app_pair" msgid="5647523853662686243">"යෙදුම් යුගල සුරකින්න"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 51b0c7b..37a02e4 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Razdeljen zaslon"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Podatki o aplikaciji za: %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Nastavitve uporabe za »%1$s«"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Novo okno"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Shrani par aplikacij"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ta par aplikacij ni podprt v tej napravi"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index c93519f..afaeb61 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Подељени екран"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Информације о апликацији за: %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Подешавања потрошње за %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Нови прозор"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Сачувај пар апликација"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Овај пар апликација није подржан на овом уређају"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index c92d6f0..547f60e 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"Delad skärm"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"Appinformation för %1$s"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"Användningsinställningar för %1$s"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"Nytt fönster"</string>
<string name="save_app_pair" msgid="5647523853662686243">"Spara app-par"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"De här apparna som ska användas tillsammans stöds inte på den här enheten"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 5348a22..75dc7f0 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -31,8 +31,7 @@
<string name="recent_task_option_split_screen" msgid="6690461455618725183">"స్ప్లిట్ స్క్రీన్"</string>
<string name="split_app_info_accessibility" msgid="5475288491241414932">"%1$s కోసం యాప్ సమాచారం"</string>
<string name="split_app_usage_settings" msgid="7214375263347964093">"%1$sకు సంబంధించిన వినియోగ సెట్టింగ్లు"</string>
- <!-- no translation found for new_window_option_taskbar (6448780542727767211) -->
- <skip />
+ <string name="new_window_option_taskbar" msgid="6448780542727767211">"కొత్త విండో"</string>
<string name="save_app_pair" msgid="5647523853662686243">"యాప్ పెయిర్ను సేవ్ చేయండి"</string>
<string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
<string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు"</string>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 483f5f8..4eca048 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -31,6 +31,8 @@
import static com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
import static com.android.launcher3.testing.shared.ResourceUtils.roundPxValueFromFloat;
+import static com.android.wm.shell.Flags.enableBubbleBar;
+import static com.android.wm.shell.Flags.enableBubbleBarInPersistentTaskBar;
import static com.android.wm.shell.Flags.enableTinyTaskbar;
import android.annotation.SuppressLint;
@@ -64,8 +66,10 @@
import com.android.launcher3.responsive.ResponsiveSpec.DimensionType;
import com.android.launcher3.responsive.ResponsiveSpecsProvider;
import com.android.launcher3.util.CellContentDimensions;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.IconSizeSteps;
+import com.android.launcher3.util.NavigationMode;
import com.android.launcher3.util.ResourceHelper;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.util.window.WindowManagerProxy;
@@ -219,6 +223,8 @@
public int hotseatBarBottomSpacePx;
public int hotseatBarEndOffset;
public int hotseatQsbSpace;
+ public int inlineNavButtonsEndSpacingPx;
+ public int navButtonsLayoutWidthPx;
public int springLoadedHotseatBarTopMarginPx;
// These 2 values are only used for isVerticalBar
// Padding between edge of screen and hotseat
@@ -233,7 +239,6 @@
private final int mMinHotseatIconSpacePx;
private final int mMinHotseatQsbWidthPx;
private final int mMaxHotseatIconSpacePx;
- public final int inlineNavButtonsEndSpacingPx;
// Space required for the bubble bar between the hotseat and the edge of the screen. If there's
// not enough space, the hotseat will adjust itself for the bubble bar.
private final int mBubbleBarSpaceThresholdPx;
@@ -692,17 +697,12 @@
if (areNavButtonsInline && !isPhone) {
inlineNavButtonsEndSpacingPx =
res.getDimensionPixelSize(inv.inlineNavButtonsEndSpacing);
- /*
- * 3 nav buttons +
- * Spacing between nav buttons +
- * Space at the end for contextual buttons
- */
- hotseatBarEndOffset = 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
- + 2 * res.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween)
- + inlineNavButtonsEndSpacingPx;
- } else {
- inlineNavButtonsEndSpacingPx = 0;
- hotseatBarEndOffset = 0;
+ /* 3 nav buttons + Spacing between nav buttons */
+ navButtonsLayoutWidthPx = 3 * res.getDimensionPixelSize(
+ R.dimen.taskbar_nav_buttons_size)
+ + 2 * res.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween);
+ /* nav buttons layout width + Space at the end for contextual buttons */
+ hotseatBarEndOffset = navButtonsLayoutWidthPx + inlineNavButtonsEndSpacingPx;
}
mBubbleBarSpaceThresholdPx =
@@ -2214,6 +2214,10 @@
mHotseatBarEdgePaddingPx));
writer.println(prefix + pxToDpStr("mHotseatBarWorkspaceSpacePx",
mHotseatBarWorkspaceSpacePx));
+ writer.println(prefix
+ + pxToDpStr("inlineNavButtonsEndSpacingPx", inlineNavButtonsEndSpacingPx));
+ writer.println(prefix
+ + pxToDpStr("navButtonsLayoutWidthPx", navButtonsLayoutWidthPx));
writer.println(prefix + pxToDpStr("hotseatBarEndOffset", hotseatBarEndOffset));
writer.println(prefix + pxToDpStr("hotseatQsbSpace", hotseatQsbSpace));
writer.println(prefix + pxToDpStr("hotseatQsbHeight", hotseatQsbHeight));
@@ -2328,6 +2332,25 @@
}
/**
+ * Returns whether Taskbar and Hotseat should adjust horizontally on bubble bar location update.
+ */
+ public boolean shouldAdjustHotseatOnBubblesLocationUpdate(Context context) {
+ return enableBubbleBar()
+ && enableBubbleBarInPersistentTaskBar()
+ && DisplayController.getNavigationMode(context)
+ == NavigationMode.THREE_BUTTONS;
+ }
+
+ /** Returns hotseat translation X for the bubble bar position. */
+ public int getHotseatTranslationXForBubbleBar(boolean isNavbarOnRight) {
+ if (isNavbarOnRight) {
+ return 0;
+ } else {
+ return navButtonsLayoutWidthPx;
+ }
+ }
+
+ /**
* Callback when a component changes the DeviceProfile associated with it, as a result of
* configuration change
*/
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 024dde4..ae4c122 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -34,8 +34,10 @@
import android.widget.FrameLayout;
import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
import com.android.launcher3.util.HorizontalInsettableView;
+import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.MultiValueAlpha;
@@ -61,6 +63,14 @@
public @interface HotseatQsbAlphaId {
}
+ public static final int ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT = 0;
+ public static final int ICONS_TRANSLATION_X_CHANNELS_COUNT = 1;
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @IntDef({ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT})
+ public @interface IconsTranslationX {
+ }
+
// Ratio of empty space, qsb should take up to appear visually centered.
public static final float QSB_CENTER_FACTOR = .325f;
private static final int BUBBLE_BAR_ADJUSTMENT_ANIMATION_DURATION_MS = 250;
@@ -72,6 +82,10 @@
private final MultiValueAlpha mIconsAlphaChannels;
private final MultiValueAlpha mQsbAlphaChannels;
+ private @Nullable MultiProperty mQsbTranslationX;
+
+ private final MultiPropertyFactory mIconsTranslationXFactory;
+
private final View mQsb;
public Hotseat(Context context) {
@@ -88,9 +102,26 @@
addView(mQsb);
mIconsAlphaChannels = new MultiValueAlpha(getShortcutsAndWidgets(),
ALPHA_CHANNEL_CHANNELS_COUNT);
+ if (mQsb instanceof Reorderable qsbReorderable) {
+ mQsbTranslationX = qsbReorderable.getTranslateDelegate()
+ .getTranslationX(MultiTranslateDelegate.INDEX_NAV_BAR_ANIM);
+ }
+ mIconsTranslationXFactory = new MultiPropertyFactory<>(getShortcutsAndWidgets(),
+ VIEW_TRANSLATE_X, ICONS_TRANSLATION_X_CHANNELS_COUNT, Float::sum);
mQsbAlphaChannels = new MultiValueAlpha(mQsb, ALPHA_CHANNEL_CHANNELS_COUNT);
}
+ /** Provides translation X for hotseat icons for the channel. */
+ public MultiProperty getIconsTranslationX(@IconsTranslationX int channelId) {
+ return mIconsTranslationXFactory.get(channelId);
+ }
+
+ /** Provides translation X for hotseat Qsb. */
+ @Nullable
+ public MultiProperty getQsbTranslationX() {
+ return mQsbTranslationX;
+ }
+
/**
* Returns orientation specific cell X given invariant order in the hotseat
*/
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index f8ac48a..572274e 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -83,8 +83,8 @@
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
import com.android.launcher3.graphics.TintedDrawableSpan;
import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.CacheableShortcutInfo;
import com.android.launcher3.icons.LauncherIcons;
-import com.android.launcher3.icons.ShortcutCachingLogic;
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -626,8 +626,7 @@
if (activityInfo == null) {
return null;
}
- mainIcon = appState.getIconProvider().getIcon(
- activityInfo, appState.getInvariantDeviceProfile().fillResIconDpi);
+ mainIcon = appState.getIconCache().getFullResIcon(activityInfo.getActivityInfo());
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
List<ShortcutInfo> siList = ShortcutKey.fromItemInfo(info)
.buildRequest(context)
@@ -636,7 +635,7 @@
return null;
} else {
ShortcutInfo si = siList.get(0);
- mainIcon = ShortcutCachingLogic.getIcon(context, si,
+ mainIcon = CacheableShortcutInfo.getIcon(context, si,
appState.getInvariantDeviceProfile().fillResIconDpi);
// Only fetch badge if the icon is on workspace
if (info.id != ItemInfo.NO_ID && badge == null) {
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 0f3cad6..cc5e890 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -69,7 +69,8 @@
public PinShortcutRequestActivityInfo(
ShortcutInfo si, Supplier<PinItemRequest> requestSupplier, Context context) {
- super(new ComponentName(si.getPackage(), STUB_COMPONENT_CLASS), si.getUserHandle());
+ super(new ComponentName(si.getPackage(), STUB_COMPONENT_CLASS),
+ si.getUserHandle(), context);
mRequestSupplier = requestSupplier;
mInfo = si;
mContext = context;
diff --git a/src/com/android/launcher3/icons/CacheableShortcutInfo.kt b/src/com/android/launcher3/icons/CacheableShortcutInfo.kt
new file mode 100644
index 0000000..c121340
--- /dev/null
+++ b/src/com/android/launcher3/icons/CacheableShortcutInfo.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.icons
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.LauncherActivityInfo
+import android.content.pm.LauncherApps
+import android.content.pm.PackageInfo
+import android.content.pm.ShortcutInfo
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import android.text.TextUtils
+import android.util.Log
+import com.android.launcher3.BuildConfig
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.icons.BaseIconFactory.IconOptions
+import com.android.launcher3.icons.cache.BaseIconCache
+import com.android.launcher3.icons.cache.CachingLogic
+import com.android.launcher3.shortcuts.ShortcutKey
+import com.android.launcher3.util.ApplicationInfoWrapper
+import com.android.launcher3.util.PackageUserKey
+import com.android.launcher3.util.Themes
+import kotlin.math.max
+
+/** Wrapper over ShortcutInfo to provide extra information related to ShortcutInfo */
+class CacheableShortcutInfo(val shortcutInfo: ShortcutInfo, val appInfo: ApplicationInfoWrapper) {
+
+ constructor(
+ info: ShortcutInfo,
+ ctx: Context,
+ ) : this(info, ApplicationInfoWrapper(ctx, info.getPackage(), info.userHandle))
+
+ companion object {
+ private const val TAG = "CacheableShortcutInfo"
+
+ /**
+ * Similar to [LauncherApps.getShortcutIconDrawable] with additional Launcher specific
+ * checks
+ */
+ @JvmStatic
+ fun getIcon(context: Context, shortcutInfo: ShortcutInfo, density: Int): Drawable? {
+ if (!BuildConfig.WIDGETS_ENABLED) {
+ return null
+ }
+ try {
+ return context
+ .getSystemService(LauncherApps::class.java)
+ .getShortcutIconDrawable(shortcutInfo, density)
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to get shortcut icon", e)
+ return null
+ }
+ }
+
+ /**
+ * Converts the provided list of Shortcuts to CacheableShortcuts by using the application
+ * info from the provided list of apps
+ */
+ @JvmStatic
+ fun convertShortcutsToCacheableShortcuts(
+ shortcuts: List<ShortcutInfo>,
+ activities: List<LauncherActivityInfo>,
+ ): List<CacheableShortcutInfo> {
+ // Create a map of package to applicationInfo
+ val appMap =
+ activities.associateBy(
+ { PackageUserKey(it.componentName.packageName, it.user) },
+ { it.applicationInfo },
+ )
+
+ return shortcuts.map {
+ CacheableShortcutInfo(
+ it,
+ ApplicationInfoWrapper(appMap[PackageUserKey(it.getPackage(), it.userHandle)]),
+ )
+ }
+ }
+ }
+}
+
+/** Caching logic for CacheableShortcutInfo. */
+object CacheableShortcutCachingLogic : CachingLogic<CacheableShortcutInfo> {
+
+ override fun getComponent(info: CacheableShortcutInfo): ComponentName =
+ ShortcutKey.fromInfo(info.shortcutInfo).componentName
+
+ override fun getUser(info: CacheableShortcutInfo): UserHandle = info.shortcutInfo.userHandle
+
+ override fun getLabel(info: CacheableShortcutInfo): CharSequence? = info.shortcutInfo.shortLabel
+
+ override fun getDescription(info: CacheableShortcutInfo, fallback: CharSequence): CharSequence =
+ info.shortcutInfo.longLabel.let { if (TextUtils.isEmpty(it)) fallback else it!! }
+
+ override fun getLastUpdatedTime(info: CacheableShortcutInfo?, packageInfo: PackageInfo) =
+ info?.let { max(info.shortcutInfo.lastChangedTimestamp, packageInfo.lastUpdateTime) }
+ ?: packageInfo.lastUpdateTime
+
+ override fun addToMemCache() = false
+
+ override fun getApplicationInfo(info: CacheableShortcutInfo) = info.appInfo.getInfo()
+
+ override fun loadIcon(context: Context, cache: BaseIconCache, info: CacheableShortcutInfo) =
+ LauncherIcons.obtain(context).use { li ->
+ CacheableShortcutInfo.getIcon(
+ context,
+ info.shortcutInfo,
+ LauncherAppState.getIDP(context).fillResIconDpi,
+ )
+ ?.let { d ->
+ li.createBadgedIconBitmap(
+ d,
+ IconOptions().setExtractedColor(Themes.getColorAccent(context)),
+ )
+ } ?: BitmapInfo.LOW_RES_INFO
+ }
+}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 53a4039..5396597 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -36,7 +36,6 @@
import android.content.pm.ShortcutInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
-import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.os.Process;
import android.os.Trace;
@@ -66,7 +65,6 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.CancellableTask;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.PackageUserKey;
@@ -98,7 +96,6 @@
private final CachingLogic<ComponentWithLabel> mComponentWithLabelCachingLogic;
private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic;
- private final CachingLogic<ShortcutInfo> mShortcutCachingLogic;
private final LauncherApps mLauncherApps;
private final UserCache mUserManager;
@@ -116,7 +113,6 @@
mComponentWithLabelCachingLogic = new CachedObjectCachingLogic(
context, false /* loadIcons */, false /* addToMemCache */);
mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.INSTANCE;
- mShortcutCachingLogic = new ShortcutCachingLogic();
mLauncherApps = mContext.getSystemService(LauncherApps.class);
mUserManager = UserCache.INSTANCE.get(mContext);
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
@@ -233,7 +229,7 @@
}
/**
- * Fill in {@param info} with the icon and label for {@param activityInfo}
+ * Fill in {@code info} with the icon and label for {@code activityInfo}
*/
@SuppressWarnings("NewApi")
public synchronized void getTitleAndIcon(ItemInfoWithIcon info,
@@ -245,28 +241,40 @@
}
/**
- * Fill in {@param info} with the icon for {@param si}
+ * Fill in {@code info} with the icon for {@code si}
*/
public void getShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) {
+ getShortcutIcon(info, new CacheableShortcutInfo(si, mContext));
+ }
+
+ /**
+ * Fill in {@code info} with the icon for {@code si}
+ */
+ public void getShortcutIcon(ItemInfoWithIcon info, CacheableShortcutInfo si) {
getShortcutIcon(info, si, mIsUsingFallbackOrNonDefaultIconCheck);
}
/**
- * Fill in {@param info} with the icon and label for {@param si}. If the icon is not
+ * Fill in {@code info} with the icon and label for {@code si}. If the icon is not
* available, and fallback check returns true, it keeps the old icon.
*/
- public <T extends ItemInfoWithIcon> void getShortcutIcon(T info, ShortcutInfo si,
+ public <T extends ItemInfoWithIcon> void getShortcutIcon(T info, CacheableShortcutInfo si,
@NonNull Predicate<T> fallbackIconCheck) {
- BitmapInfo bitmapInfo = cacheLocked(ShortcutKey.fromInfo(si).componentName,
- si.getUserHandle(), () -> si, mShortcutCachingLogic, LookupFlag.DEFAULT).bitmap;
+ UserHandle user = CacheableShortcutCachingLogic.INSTANCE.getUser(si);
+ BitmapInfo bitmapInfo = cacheLocked(
+ CacheableShortcutCachingLogic.INSTANCE.getComponent(si),
+ user,
+ () -> si,
+ CacheableShortcutCachingLogic.INSTANCE,
+ LookupFlag.DEFAULT).bitmap;
if (bitmapInfo.isNullOrLowRes()) {
- bitmapInfo = getDefaultIcon(si.getUserHandle());
+ bitmapInfo = getDefaultIcon(user);
}
- if (isDefaultIcon(bitmapInfo, si.getUserHandle()) && fallbackIconCheck.test(info)) {
+ if (isDefaultIcon(bitmapInfo, user) && fallbackIconCheck.test(info)) {
return;
}
- info.bitmap = bitmapInfo.withBadgeInfo(getShortcutInfoBadge(si));
+ info.bitmap = bitmapInfo.withBadgeInfo(getShortcutInfoBadge(si.getShortcutInfo()));
}
/**
@@ -589,10 +597,6 @@
info.bitmap = packageEntry.bitmap;
}
- public Drawable getFullResIcon(LauncherActivityInfo info) {
- return mIconProvider.getIcon(info, mIconDpi);
- }
-
public void updateSessionCache(PackageUserKey key, PackageInstaller.SessionInfo info) {
cachePackageInstallInfo(key.mPackageName, key.mUser, info.getAppIcon(),
info.getAppLabel());
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
deleted file mode 100644
index 7bb39e1..0000000
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ /dev/null
@@ -1,117 +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.icons;
-
-import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.LauncherApps;
-import android.content.pm.PackageInfo;
-import android.content.pm.ShortcutInfo;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.BaseIconFactory.IconOptions;
-import com.android.launcher3.icons.cache.BaseIconCache;
-import com.android.launcher3.icons.cache.CachingLogic;
-import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.util.Themes;
-
-/**
- * Caching logic for shortcuts.
- */
-public class ShortcutCachingLogic implements CachingLogic<ShortcutInfo> {
-
- private static final String TAG = "ShortcutCachingLogic";
-
- @Override
- @NonNull
- public ComponentName getComponent(@NonNull ShortcutInfo info) {
- return ShortcutKey.fromInfo(info).componentName;
- }
-
- @NonNull
- @Override
- public UserHandle getUser(@NonNull ShortcutInfo info) {
- return info.getUserHandle();
- }
-
- @NonNull
- @Override
- public CharSequence getLabel(@NonNull ShortcutInfo info) {
- return info.getShortLabel();
- }
-
- @Override
- @NonNull
- public CharSequence getDescription(@NonNull ShortcutInfo object,
- @NonNull CharSequence fallback) {
- CharSequence label = object.getLongLabel();
- return TextUtils.isEmpty(label) ? fallback : label;
- }
-
- @NonNull
- @Override
- public BitmapInfo loadIcon(@NonNull Context context, @NonNull BaseIconCache cache,
- @NonNull ShortcutInfo info) {
- try (LauncherIcons li = LauncherIcons.obtain(context)) {
- Drawable unbadgedDrawable = ShortcutCachingLogic.getIcon(
- context, info, LauncherAppState.getIDP(context).fillResIconDpi);
- if (unbadgedDrawable == null) return BitmapInfo.LOW_RES_INFO;
- return li.createBadgedIconBitmap(unbadgedDrawable,
- new IconOptions().setExtractedColor(Themes.getColorAccent(context)));
- }
- }
-
- @Override
- public long getLastUpdatedTime(@Nullable ShortcutInfo shortcutInfo,
- @NonNull PackageInfo info) {
- if (shortcutInfo == null) {
- return info.lastUpdateTime;
- }
- return Math.max(shortcutInfo.getLastChangedTimestamp(), info.lastUpdateTime);
- }
-
- @Override
- public boolean addToMemCache() {
- return false;
- }
-
- /**
- * Similar to {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)} with additional
- * Launcher specific checks
- */
- public static Drawable getIcon(Context context, ShortcutInfo shortcutInfo, int density) {
- if (!WIDGETS_ENABLED) {
- return null;
- }
- try {
- return context.getSystemService(LauncherApps.class)
- .getShortcutIconDrawable(shortcutInfo, density);
- } catch (SecurityException | IllegalStateException | NullPointerException e) {
- Log.e(TAG, "Failed to get shortcut icon", e);
- return null;
- }
- }
-}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 609846f..dff5463 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -23,6 +23,7 @@
import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE;
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
+import static com.android.launcher3.icons.CacheableShortcutInfo.convertShortcutsToCacheableShortcuts;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
@@ -69,9 +70,10 @@
import com.android.launcher3.folder.FolderGridOrganizer;
import com.android.launcher3.folder.FolderNameInfos;
import com.android.launcher3.folder.FolderNameProvider;
+import com.android.launcher3.icons.CacheableShortcutCachingLogic;
+import com.android.launcher3.icons.CacheableShortcutInfo;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.icons.ShortcutCachingLogic;
import com.android.launcher3.icons.cache.CachedObjectCachingLogic;
import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
import com.android.launcher3.icons.cache.LauncherActivityCachingLogic;
@@ -246,7 +248,7 @@
}
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
- List<ShortcutInfo> allShortcuts = new ArrayList<>();
+ List<CacheableShortcutInfo> allShortcuts = new ArrayList<>();
loadWorkspace(allShortcuts, "", memoryLogger, restoreEventLogger);
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
@@ -304,7 +306,7 @@
verifyNotStopped();
logASplit("save shortcuts in icon cache");
- updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
+ updateHandler.updateIcons(allShortcuts, CacheableShortcutCachingLogic.INSTANCE,
mApp.getModel()::onPackageIconsUpdated);
// Take a break
@@ -322,8 +324,10 @@
verifyNotStopped();
logASplit("save deep shortcuts in icon cache");
- updateHandler.updateIcons(allDeepShortcuts,
- new ShortcutCachingLogic(), (pkgs, user) -> { });
+ updateHandler.updateIcons(
+ convertShortcutsToCacheableShortcuts(allDeepShortcuts, allActivityList),
+ CacheableShortcutCachingLogic.INSTANCE,
+ (pkgs, user) -> { });
// Take a break
waitForIdle();
@@ -397,7 +401,7 @@
}
protected void loadWorkspace(
- List<ShortcutInfo> allDeepShortcuts,
+ List<CacheableShortcutInfo> allDeepShortcuts,
String selection,
LoaderMemoryLogger memoryLogger,
@Nullable LauncherRestoreEventLogger restoreEventLogger
@@ -423,7 +427,7 @@
}
private void loadWorkspaceImpl(
- List<ShortcutInfo> allDeepShortcuts,
+ List<CacheableShortcutInfo> allDeepShortcuts,
String selection,
@Nullable LoaderMemoryLogger memoryLogger,
@Nullable LauncherRestoreEventLogger restoreEventLogger) {
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 55c4d30..b5a7382 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -24,6 +24,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.icons.CacheableShortcutInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
@@ -79,9 +80,9 @@
}
if (!matchingWorkspaceItems.isEmpty()) {
+ ApplicationInfoWrapper infoWrapper =
+ new ApplicationInfoWrapper(context, mPackageName, mUser);
if (mShortcuts.isEmpty()) {
- ApplicationInfoWrapper infoWrapper =
- new ApplicationInfoWrapper(context, mPackageName, mUser);
// Verify that the app is indeed installed.
if (!infoWrapper.isInstalled() && !infoWrapper.isArchived()) {
// App is not installed or archived, ignoring package events
@@ -103,7 +104,6 @@
if (!fullDetails.isPinned()) {
continue;
}
-
String sid = fullDetails.getId();
nonPinnedIds.remove(sid);
matchingWorkspaceItems
@@ -111,7 +111,8 @@
.filter(itemInfo -> sid.equals(itemInfo.getDeepShortcutId()))
.forEach(workspaceItemInfo -> {
workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context);
- app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails);
+ app.getIconCache().getShortcutIcon(workspaceItemInfo,
+ new CacheableShortcutInfo(fullDetails, infoWrapper));
updatedWorkspaceItemInfos.add(workspaceItemInfo);
});
}
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index 18c7f95..c02336e 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -32,6 +32,7 @@
import com.android.launcher3.LauncherSettings.Favorites
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError
import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.icons.CacheableShortcutInfo
import com.android.launcher3.logging.FileLog
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.AppPairInfo
@@ -76,7 +77,7 @@
private val pmHelper: PackageManagerHelper,
private val iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>>,
private val unlockedUsers: LongSparseArray<Boolean>,
- private val allDeepShortcuts: MutableList<ShortcutInfo>,
+ private val allDeepShortcuts: MutableList<CacheableShortcutInfo>,
) {
private val isSafeMode = app.isSafeModeEnabled
@@ -278,13 +279,14 @@
info = WorkspaceItemInfo(pinnedShortcut, app.context)
// If the pinned deep shortcut is no longer published,
// use the last saved icon instead of the default.
- iconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon)
+ val csi = CacheableShortcutInfo(pinnedShortcut, appInfoWrapper)
+ iconCache.getShortcutIcon(info, csi, c::loadIcon)
if (appInfoWrapper.isSuspended()) {
info.runtimeStatusFlags =
info.runtimeStatusFlags or ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED
}
intent = info.getIntent()
- allDeepShortcuts.add(pinnedShortcut)
+ allDeepShortcuts.add(csi)
} else {
// Create a shortcut info in disabled mode for now.
info = c.loadSimpleWorkspaceItem()
diff --git a/src/com/android/launcher3/pm/PinRequestHelper.java b/src/com/android/launcher3/pm/PinRequestHelper.java
index 47afeef..2ed6591 100644
--- a/src/com/android/launcher3/pm/PinRequestHelper.java
+++ b/src/com/android/launcher3/pm/PinRequestHelper.java
@@ -32,7 +32,8 @@
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.ShortcutCachingLogic;
+import com.android.launcher3.icons.CacheableShortcutCachingLogic;
+import com.android.launcher3.icons.CacheableShortcutInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
public class PinRequestHelper {
@@ -78,7 +79,8 @@
// Apply the unbadged icon synchronously using the caching logic directly and
// fetch the actual icon asynchronously.
LauncherAppState app = LauncherAppState.getInstance(context);
- info.bitmap = new ShortcutCachingLogic().loadIcon(context, app.getIconCache(), si);
+ info.bitmap = CacheableShortcutCachingLogic.INSTANCE.loadIcon(
+ context, app.getIconCache(), new CacheableShortcutInfo(si, context));
app.getModel().updateAndBindWorkspaceItem(info, si);
return info;
} else {
diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
index 351ebce..3064abf 100644
--- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
@@ -43,6 +44,7 @@
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.ApplicationInfoWrapper;
import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
@@ -58,10 +60,20 @@
private final ComponentName mCn;
private final UserHandle mUser;
+ private final ApplicationInfoWrapper mInfoWrapper;
- protected ShortcutConfigActivityInfo(ComponentName cn, UserHandle user) {
+ protected ShortcutConfigActivityInfo(
+ ComponentName cn, UserHandle user, ApplicationInfoWrapper infoWrapper) {
mCn = cn;
mUser = user;
+ mInfoWrapper = infoWrapper;
+ }
+
+ protected ShortcutConfigActivityInfo(
+ ComponentName cn, UserHandle user, Context context) {
+ mCn = cn;
+ mUser = user;
+ mInfoWrapper = new ApplicationInfoWrapper(context, cn.getPackageName(), user);
}
@Override
@@ -89,6 +101,12 @@
return null;
}
+ @Nullable
+ @Override
+ public ApplicationInfo getApplicationInfo() {
+ return mInfoWrapper.getInfo();
+ }
+
public boolean startConfigActivity(Activity activity, int requestCode) {
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT)
.setComponent(getComponent());
@@ -120,7 +138,8 @@
private final LauncherActivityInfo mInfo;
public ShortcutConfigActivityInfoVO(LauncherActivityInfo info) {
- super(info.getComponentName(), info.getUser());
+ super(info.getComponentName(), info.getUser(),
+ new ApplicationInfoWrapper(info.getApplicationInfo()));
mInfo = info;
}
@@ -131,7 +150,7 @@
@Override
public Drawable getFullResIcon(IconCache cache) {
- return cache.getFullResIcon(mInfo);
+ return cache.getFullResIcon(mInfo.getActivityInfo());
}
@Override
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index aa24f60..755c3eb 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -27,11 +27,13 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.icons.CacheableShortcutInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.util.ApplicationInfoWrapper;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -113,6 +115,8 @@
final ComponentName activity = originalInfo.getTargetComponent();
final UserHandle user = originalInfo.user;
return () -> {
+ ApplicationInfoWrapper infoWrapper =
+ new ApplicationInfoWrapper(context, activity.getPackageName(), user);
List<ShortcutInfo> shortcuts = new ShortcutRequest(context, user)
.withContainer(activity)
.query(ShortcutRequest.PUBLISHED);
@@ -121,7 +125,7 @@
for (int i = 0; i < shortcuts.size() && i < shortcutViews.size(); i++) {
final ShortcutInfo shortcut = shortcuts.get(i);
final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, context);
- cache.getShortcutIcon(si, shortcut);
+ cache.getShortcutIcon(si, new CacheableShortcutInfo(shortcut, infoWrapper));
si.rank = i;
si.container = CONTAINER_SHORTCUTS;
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index efd1f0d..74a0966 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -407,10 +407,7 @@
}
private void updateContextualEduStats(LauncherState targetState) {
- if (targetState == NORMAL) {
- ContextualEduStatsManager.INSTANCE.get(
- mLauncher).updateEduStats(mDetector.isTrackpadGesture(), GestureType.HOME);
- } else if (targetState == OVERVIEW) {
+ if (targetState == OVERVIEW) {
ContextualEduStatsManager.INSTANCE.get(
mLauncher).updateEduStats(mDetector.isTrackpadGesture(), GestureType.OVERVIEW);
} else if (targetState == ALL_APPS && !mDetector.isTrackpadGesture()) {
diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
index ab42839..e100157 100644
--- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
+++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java
@@ -213,8 +213,8 @@
// Draw icon in the center.
try {
- Drawable icon = LauncherAppState.getInstance(mContext).getIconCache()
- .getFullResIcon(info.provider.getPackageName(), info.icon);
+ Drawable icon = info.getFullResIcon(
+ LauncherAppState.getInstance(mContext).getIconCache());
if (icon != null) {
int appIconSize = dp.iconSizePx;
int iconSize = (int) Math.min(appIconSize * scale,
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index e77ba24..1db3b5a 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -3,6 +3,7 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.Rect;
@@ -10,6 +11,8 @@
import android.os.Parcel;
import android.os.UserHandle;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
@@ -223,6 +226,12 @@
@Override
public Drawable getFullResIcon(IconCache cache) {
- return cache.getFullResIcon(provider.getPackageName(), icon);
+ return cache.getFullResIcon(getActivityInfo());
+ }
+
+ @Nullable
+ @Override
+ public ApplicationInfo getApplicationInfo() {
+ return getActivityInfo().applicationInfo;
}
}
\ No newline at end of file
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 2553cf9..68e493d 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -420,6 +420,36 @@
</intent-filter>
</activity>
+ <activity-alias android:name="AppIconActivity"
+ android:label="Application Icon"
+ android:exported="true"
+ android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity-alias>
+ <activity-alias android:name="DiffIconActivity"
+ android:label="Different icon"
+ android:exported="true"
+ android:icon="@drawable/test_different_activity_icon"
+ android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity-alias>
+ <activity-alias android:name="WrongIconActivity"
+ android:label="Wrong icon"
+ android:exported="true"
+ android:icon="@drawable/test_wrong_activity_icon"
+ android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity-alias>
+
<!-- Disable eager initialization of Jetpack libraries. See bug 197780098. -->
<provider
android:name="androidx.startup.InitializationProvider"
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
index 82a6310..4c366c3 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
index 4271105..6db9534 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 147.0px (56.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
index 8bd6b99..6e76b13 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 0.0px (0.0dp)
mHotseatBarEdgePaddingPx: 63.0px (24.0dp)
mHotseatBarWorkspaceSpacePx: 42.0px (16.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
index 8dbb413..1af9215 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 0.0px (0.0dp)
mHotseatBarEdgePaddingPx: 63.0px (24.0dp)
mHotseatBarWorkspaceSpacePx: 42.0px (16.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
index ab4b286..958597f 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 80.0px (40.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
index 80835bc..aad67b4 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 80.0px (40.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
index fc53107..090e54b 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 152.0px (76.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
index 836819f..43b1a65 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 152.0px (76.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
index 108182f..fe5737e 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
index 313d2a3..36e47a0 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
index 46cce24..52fea05 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button_decoupleDepth.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
index 44b99e9..6d972a8 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape_decoupleDepth.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
index fb392a8..417353d 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
index 2c4b3c3..03dc23a 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
index e7b72f2..45d3171 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button_decoupleDepth.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
index eae50f1..55322d6 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait_decoupleDepth.txt
@@ -77,6 +77,8 @@
hotseatBarBottomSpacePx: 126.0px (48.0dp)
mHotseatBarEdgePaddingPx: 0.0px (0.0dp)
mHotseatBarWorkspaceSpacePx: 0.0px (0.0dp)
+ inlineNavButtonsEndSpacingPx: 0.0px (0.0dp)
+ navButtonsLayoutWidthPx: 0.0px (0.0dp)
hotseatBarEndOffset: 0.0px (0.0dp)
hotseatQsbSpace: 0.0px (0.0dp)
hotseatQsbHeight: 0.0px (0.0dp)
diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index d7dd40b..b5932d5 100644
--- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -168,9 +168,7 @@
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
public static final String ICON_MISSING = "b/282963545";
public static final String UIOBJECT_STALE_ELEMENT = "b/319501259";
- public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466";
public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890";
-
public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview";
public static final String REQUEST_FLAG_ENABLE_APP_PAIRS = "enable-app-pairs";
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index 7529ba9..c7abce6 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -40,6 +40,7 @@
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_INFO
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.MISSING_WIDGET_PROVIDER
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError.Companion.PROFILE_DELETED
+import com.android.launcher3.icons.CacheableShortcutInfo
import com.android.launcher3.model.data.FolderInfo
import com.android.launcher3.model.data.IconRequestInfo
import com.android.launcher3.model.data.ItemInfo
@@ -97,7 +98,7 @@
private var mUnlockedUsersArray: LongSparseArray<Boolean> = LongSparseArray()
private var mKeyToPinnedShortcutsMap: MutableMap<ShortcutKey, ShortcutInfo> = mutableMapOf()
private var mInstallingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = hashMapOf()
- private var mAllDeepShortcuts: MutableList<ShortcutInfo> = mutableListOf()
+ private var mAllDeepShortcuts: MutableList<CacheableShortcutInfo> = mutableListOf()
private var mWidgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> =
mutableMapOf()
private var mPendingPackages: MutableSet<PackageUserKey> = mutableSetOf()
@@ -194,7 +195,7 @@
pendingPackages: MutableSet<PackageUserKey> = mPendingPackages,
unlockedUsers: LongSparseArray<Boolean> = mUnlockedUsersArray,
installingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = mInstallingPkgs,
- allDeepShortcuts: MutableList<ShortcutInfo> = mAllDeepShortcuts,
+ allDeepShortcuts: MutableList<CacheableShortcutInfo> = mAllDeepShortcuts,
) =
WorkspaceItemProcessor(
c = cursor,
@@ -387,7 +388,8 @@
.that(mockCursor.restoreFlag)
.isEqualTo(0)
assertThat(mIconRequestInfos).isEmpty()
- assertThat(mAllDeepShortcuts).containsExactly(expectedShortcutInfo)
+ assertThat(mAllDeepShortcuts.size).isEqualTo(1)
+ assertThat(mAllDeepShortcuts[0].shortcutInfo).isEqualTo(expectedShortcutInfo)
verify(mockCursor).markRestored()
verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull())
}
@@ -452,7 +454,8 @@
.that(mockCursor.restoreFlag)
.isEqualTo(0)
assertThat(mIconRequestInfos).isEmpty()
- assertThat(mAllDeepShortcuts).containsExactly(expectedShortcutInfo)
+ assertThat(mAllDeepShortcuts.size).isEqualTo(1)
+ assertThat(mAllDeepShortcuts[0].shortcutInfo).isEqualTo(expectedShortcutInfo)
verify(mockCursor).markRestored()
verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull())
}
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index b2cb266..7adb2b1 100644
--- a/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -296,7 +296,7 @@
private final class TestShortcutConfigActivityInfo extends ShortcutConfigActivityInfo {
TestShortcutConfigActivityInfo(ComponentName componentName, UserHandle user) {
- super(componentName, user);
+ super(componentName, user, mContext);
}
@Override
diff --git a/tests/res/drawable/test_app_info_icon.xml b/tests/res/drawable/test_app_info_icon.xml
new file mode 100644
index 0000000..2e824ac
--- /dev/null
+++ b/tests/res/drawable/test_app_info_icon.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#FFFF0000" />
+ </foreground>
+</adaptive-icon>
diff --git a/tests/res/drawable/test_different_activity_icon.xml b/tests/res/drawable/test_different_activity_icon.xml
new file mode 100644
index 0000000..43d3611
--- /dev/null
+++ b/tests/res/drawable/test_different_activity_icon.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#FFFFFF00" />
+ </foreground>
+</adaptive-icon>
diff --git a/tests/res/drawable/test_wrong_activity_icon.xml b/tests/res/drawable/test_wrong_activity_icon.xml
new file mode 100644
index 0000000..c3ae9f0
--- /dev/null
+++ b/tests/res/drawable/test_wrong_activity_icon.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<wrong-adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@android:color/white"/>
+ <foreground>
+ <color android:color="#FFFF0000" />
+ </foreground>
+</wrong-adaptive-icon>
diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
index 8fe77ac..59e1f99 100644
--- a/tests/src/com/android/launcher3/dragging/TaplDragTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.dragging;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
import static com.android.launcher3.util.TestConstants.AppNames.GMAIL_APP_NAME;
import static com.android.launcher3.util.TestConstants.AppNames.MAPS_APP_NAME;
import static com.android.launcher3.util.TestConstants.AppNames.PHOTOS_APP_NAME;
@@ -229,11 +228,6 @@
final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(TEST_APP_NAME);
for (Point target : targets) {
startTime = SystemClock.uptimeMillis();
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "TaplDragTest.java.testDragAppIconToMultipleWorkspaceCells: shortcut name: "
- + launcherTestAppIcon.getIconName()
- + " | target cell coordinates: (" + target.x + ", " + target.y
- + ") | start time: " + startTime);
launcherTestAppIcon.dragToWorkspace(target.x, target.y);
endTime = SystemClock.uptimeMillis();
elapsedTime = endTime - startTime;
diff --git a/tests/src/com/android/launcher3/icons/IconProviderTest.kt b/tests/src/com/android/launcher3/icons/IconProviderTest.kt
new file mode 100644
index 0000000..5517fce
--- /dev/null
+++ b/tests/src/com/android/launcher3/icons/IconProviderTest.kt
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.icons
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.ActivityInfo
+import android.content.pm.ApplicationInfo
+import android.content.pm.LauncherActivityInfo
+import android.content.pm.LauncherApps
+import android.content.pm.PackageItemInfo
+import android.content.pm.PackageManager
+import android.graphics.drawable.AdaptiveIconDrawable
+import android.graphics.drawable.Drawable
+import android.os.Parcel
+import android.os.Parcelable.Creator
+import android.os.Process
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.widget.WidgetManagerHelper
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Tests for IconProvider */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class IconProviderTest {
+
+ lateinit var context: Context
+ lateinit var pm: PackageManager
+ lateinit var iconProvider: IconProvider
+
+ lateinit var testContext: Context
+
+ @Before
+ fun setup() {
+ context = InstrumentationRegistry.getInstrumentation().targetContext
+ pm = context.packageManager
+ iconProvider = IconProvider(context)
+
+ testContext = InstrumentationRegistry.getInstrumentation().context
+ }
+
+ @Test
+ fun launcherActivityInfo_activity_icon() {
+ val icon = iconProvider.getIcon(getLauncherActivityInfo(DiffIconActivity).activityInfo)
+ assertNotNull(icon)
+ verifyIconResName(icon, ICON_DIFFERENT_ACTIVITY)
+ }
+
+ @Test
+ fun packageActivityInfo_activity_icon() {
+ val icon = iconProvider.getIcon(getPackageActivityInfo(DiffIconActivity))
+ assertNotNull(icon)
+ verifyIconResName(icon, ICON_DIFFERENT_ACTIVITY)
+ }
+
+ @Test
+ fun launcherActivityInfo_wrong_icon() {
+ val ai =
+ getLauncherActivityInfo(WrongIconActivity)
+ .activityInfo
+ .overrideAppIcon(ActivityInfo.CREATOR)
+ assertEquals(ai.icon.toResourceName(), ICON_WRONG_DRAWABLE)
+ val icon = iconProvider.getIcon(ai)
+ assertNotNull(icon)
+ // App icon is loaded if the drawable is not found
+ verifyIconResName(icon, ICON_APP_INFO)
+ }
+
+ @Test
+ fun packageActivityInfo_wrong_icon() {
+ val ai = getPackageActivityInfo(WrongIconActivity)
+ assertEquals(ai.icon.toResourceName(), ICON_WRONG_DRAWABLE)
+ assertNotEquals(ai.icon, 0)
+ val icon = iconProvider.getIcon(ai)
+ assertNotNull(icon)
+ // App icon is loaded if the drawable is not found
+ verifyIconResName(icon, ICON_APP_INFO)
+ }
+
+ @Test
+ fun launcherActivityInfo_fallback_to_icon() {
+ val ai =
+ getLauncherActivityInfo(AppIconActivity)
+ .activityInfo
+ .overrideAppIcon(ActivityInfo.CREATOR)
+ assertEquals(ai.icon, 0)
+ val icon = iconProvider.getIcon(ai)
+ assertNotNull(icon)
+ // App icon is loaded if component icon is not defined
+ verifyIconResName(icon, ICON_APP_INFO)
+ }
+
+ @Test
+ fun packageActivityInfo_fallback_to_icon() {
+ val ai = getPackageActivityInfo(AppIconActivity)
+ assertEquals(ai.icon, 0)
+ val icon = iconProvider.getIcon(ai)
+ assertNotNull(icon)
+ // App icon is loaded if component icon is not defined
+ verifyIconResName(icon, ICON_APP_INFO)
+ }
+
+ @Test
+ fun applicationInfo_icon() {
+ val appInfo =
+ getLauncherActivityInfo(AppIconActivity)
+ .applicationInfo
+ .overrideAppIcon(ApplicationInfo.CREATOR)
+ val icon = iconProvider.getIcon(appInfo)
+ assertNotNull(icon)
+ verifyIconResName(icon, ICON_APP_INFO)
+ }
+
+ @Test
+ fun applicationInfo_wrong_icon() {
+ val appInfo =
+ getLauncherActivityInfo(AppIconActivity)
+ .applicationInfo
+ .overrideAppIcon(ApplicationInfo.CREATOR)
+ appInfo.icon = 0
+
+ val icon = iconProvider.getIcon(appInfo)
+ assertNotNull(icon)
+ // Fallback is loaded if the drawable is defined
+ assertTrue(pm.isDefaultApplicationIcon(icon))
+ }
+
+ @Test
+ fun appwidgetProviderInfo_icon() {
+ val widgetInfo =
+ WidgetManagerHelper(context)
+ .findProvider(ComponentName(testContext, AppWidgetNoConfig), Process.myUserHandle())
+ assertNotNull(widgetInfo)
+
+ val icon = iconProvider.getIcon(widgetInfo.activityInfo)
+ assertNotNull(icon)
+ verifyIconResName(icon, ICON_WIDGET_NO_CONFIG)
+ }
+
+ private fun verifyIconResName(icon: Drawable, resName: String) {
+ assertTrue(icon is AdaptiveIconDrawable)
+ assertEquals(resName, (icon as AdaptiveIconDrawable).sourceDrawableResId.toResourceName())
+ }
+
+ private fun Int.toResourceName() = testContext.resources.getResourceEntryName(this)
+
+ private fun getLauncherActivityInfo(className: String): LauncherActivityInfo =
+ context
+ .getSystemService(LauncherApps::class.java)!!
+ .resolveActivity(getActivityIntent(className), Process.myUserHandle())
+
+ private fun getPackageActivityInfo(className: String): ActivityInfo =
+ pm.resolveActivity(getActivityIntent(className), 0)!!
+ .activityInfo
+ .overrideAppIcon(ActivityInfo.CREATOR)
+
+ private fun <T : PackageItemInfo> PackageItemInfo.overrideAppIcon(creator: Creator<T>): T {
+ // Clone the obj since it may have been cached by the system
+ val p = Parcel.obtain()
+ writeToParcel(p, 0)
+ p.setDataPosition(0)
+ val result = creator.createFromParcel(p)
+ p.recycle()
+ result.applicationInfo.icon =
+ testContext.resources.getIdentifier(ICON_APP_INFO, "drawable", testContext.packageName)
+ return result
+ }
+
+ private fun getActivityIntent(className: String) =
+ AppInfo.makeLaunchIntent(ComponentName(testContext, className))
+
+ companion object {
+ private const val AppIconActivity = "com.android.launcher3.tests.AppIconActivity"
+ private const val DiffIconActivity = "com.android.launcher3.tests.DiffIconActivity"
+ private const val WrongIconActivity = "com.android.launcher3.tests.WrongIconActivity"
+ private const val AppWidgetNoConfig =
+ "com.android.launcher3.testcomponent.AppWidgetNoConfig"
+
+ private const val ICON_DIFFERENT_ACTIVITY = "test_different_activity_icon"
+ private const val ICON_APP_INFO = "test_app_info_icon"
+ private const val ICON_WRONG_DRAWABLE = "test_wrong_activity_icon"
+ private const val ICON_WIDGET_NO_CONFIG = "test_widget_no_config_icon"
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt
index f1b6271..d553f47 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt
@@ -35,6 +35,7 @@
import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+import com.android.launcher3.icons.CacheableShortcutInfo
import com.android.launcher3.model.data.IconRequestInfo
import com.android.launcher3.model.data.LauncherAppWidgetInfo
import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
@@ -84,7 +85,7 @@
private var mUnlockedUsersArray: LongSparseArray<Boolean> = LongSparseArray()
private var mKeyToPinnedShortcutsMap: MutableMap<ShortcutKey, ShortcutInfo> = mutableMapOf()
private var mInstallingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = hashMapOf()
- private var mAllDeepShortcuts: MutableList<ShortcutInfo> = mutableListOf()
+ private var mAllDeepShortcuts: MutableList<CacheableShortcutInfo> = mutableListOf()
private var mWidgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> =
mutableMapOf()
private var mPendingPackages: MutableSet<PackageUserKey> = mutableSetOf()
@@ -290,7 +291,7 @@
pendingPackages: MutableSet<PackageUserKey> = mPendingPackages,
unlockedUsers: LongSparseArray<Boolean> = mUnlockedUsersArray,
installingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = mInstallingPkgs,
- allDeepShortcuts: MutableList<ShortcutInfo> = mAllDeepShortcuts,
+ allDeepShortcuts: MutableList<CacheableShortcutInfo> = mAllDeepShortcuts,
) =
WorkspaceItemProcessor(
c = cursor,
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 02a862d..9294755 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -16,10 +16,8 @@
package com.android.launcher3.tapl;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
import android.graphics.Point;
-import android.util.Log;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -99,8 +97,6 @@
@Override
protected void waitForLongPressConfirmation() {
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "AppIcon.waitForLongPressConfirmation, resName: popupContainer");
mLauncher.waitForLauncherObject("popup_container");
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 9d3bc6e..c40e5a9 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -17,10 +17,8 @@
package com.android.launcher3.tapl;
import static com.android.launcher3.testing.shared.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
import android.graphics.Point;
-import android.util.Log;
import android.view.MotionEvent;
import androidx.test.uiautomator.UiObject2;
@@ -115,10 +113,6 @@
iconCenter.y - getStartDragThreshold());
if (runToSpringLoadedState) {
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "Launchable.startDrag: actionName: long-pressing and triggering drag start"
- + " iconCenter: " + iconCenter + " dragStartCenter: "
- + dragStartCenter);
mLauncher.runToState(() -> movePointerForStartDrag(
downTime,
iconCenter,
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 78627e5..08c5552 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -31,7 +31,6 @@
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_GET_SPLIT_SELECTION_ACTIVE;
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_NUM_ALL_APPS_COLUMNS;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
import android.app.ActivityManager;
@@ -1212,11 +1211,6 @@
log("Hierarchy before clicking home:");
dumpViewHierarchy();
action = "clicking home button";
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.goHome: isThreeFingerTrackpadGesture: "
- + isThreeFingerTrackpadGesture
- + "getNavigationModel() == NavigationModel.ZERO_BUTTON: " + (
- getNavigationModel() == NavigationModel.ZERO_BUTTON));
runToState(
getHomeButton()::click,
NORMAL_STATE_ORDINAL,
@@ -1567,8 +1561,6 @@
@NonNull
UiObject2 waitForLauncherObject(String resName) {
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.waitForLauncherObject");
return waitForObjectBySelector(getLauncherObjectSelector(resName));
}
@@ -1598,16 +1590,12 @@
@NonNull
List<UiObject2> waitForObjectsBySelector(BySelector selector) {
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.waitForObjectsBySelector");
final List<UiObject2> objects = mDevice.wait(Until.findObjects(selector), WAIT_TIME_MS);
assertNotNull("Can't find any view in Launcher, selector: " + selector, objects);
return objects;
}
UiObject2 waitForObjectBySelector(BySelector selector) {
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.waitForObjectBySelector");
final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
assertNotNull("Can't find a view in Launcher, selector: " + selector, object);
return object;
@@ -1650,9 +1638,6 @@
void runToState(Runnable command, int expectedState, boolean requireEvent, String actionName) {
if (requireEvent) {
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.runToState: command: " + command + " expectedState: "
- + expectedState + " actionName: " + actionName + "requireEvent: true");
runToState(command, expectedState, actionName);
} else {
command.run();
@@ -2052,15 +2037,11 @@
mPointerCount = 1;
pointerCount = mPointerCount;
}
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.sendPointer: ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
if (hasTIS && gestureScope == GestureScope.EXPECT_PILFER) {
expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
}
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "LauncherInstrumentation.sendPointer: ACTION_UP");
break;
case MotionEvent.ACTION_POINTER_DOWN:
mPointerCount++;
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 748d576..c8c5384 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -25,7 +25,6 @@
import static com.android.launcher3.testing.shared.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
import static com.android.launcher3.testing.shared.TestProtocol.UIOBJECT_STALE_ELEMENT;
import static junit.framework.TestCase.assertNotNull;
@@ -646,8 +645,6 @@
try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
"want to drag icon to workspace")) {
final long downTime = SystemClock.uptimeMillis();
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "Workspace.dragIconToWorkspace: starting drag | downtime: " + downTime);
Point dragStart = launchable.startDrag(
downTime,
expectLongClickEvents,
diff --git a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
index b42d43b..e5a2a2e 100644
--- a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
+++ b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
@@ -15,10 +15,7 @@
*/
package com.android.launcher3.tapl;
-import static com.android.launcher3.testing.shared.TestProtocol.TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE;
-
import android.graphics.Point;
-import android.util.Log;
import java.util.function.Supplier;
@@ -79,9 +76,6 @@
LauncherInstrumentation.Closable c = launcher.addContextLayer(
String.format("want to drag the icon to cell(%d, %d)", cellX, cellY))) {
final Supplier<Point> dest = () -> Workspace.getCellCenter(launcher, cellX, cellY);
- Log.d(TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE,
- "WorkspaceDragSource.dragToWorkspace: dragging icon to workspace | dest: "
- + dest.get());
Workspace.dragIconToWorkspace(
launcher,
launchable,