Merge branch 'ub-launcher3-master' into launcher3merge2018-10-29
Test: Presubmit
Change-Id: Ib885ad03c7612747672ca1b2f4b1ea38910fdabc
diff --git a/Android.bp b/Android.bp
index 4b32702..e3dd5e5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -16,7 +16,8 @@
name: "launcher-aosp-tapl",
static_libs: [
"androidx.annotation_annotation",
- "androidx-test",
+ "androidx.test.runner",
+ "androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
"SystemUISharedLib",
],
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 5b00b7d..1beaea5 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -122,7 +122,7 @@
android:value="true" />
<activity android:name="com.android.launcher3.dragndrop.AddItemActivity"
- android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:theme="@style/AppItemActivityTheme"
android:excludeFromRecents="true"
android:autoRemoveFromRecents="true"
android:label="@string/action_add_to_workspace" >
diff --git a/build.gradle b/build.gradle
index b59f264..1b9df53 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.2.0-rc03'
+ classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6'
}
}
@@ -16,7 +16,7 @@
android {
compileSdkVersion 28
- buildToolsVersion '28.0.2'
+ buildToolsVersion '28.0.3'
defaultConfig {
minSdkVersion 21
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index b3ed365..4129ae8 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -113,6 +113,7 @@
TASK_PREVIEW = 15;
SPLIT_SCREEN_TARGET = 16;
REMOTE_ACTION_SHORTCUT = 17;
+ APP_USAGE_SETTINGS = 18;
}
enum TipType {
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index c5a7c05..6f3fa4b 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 8ae493f..f9432ad 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oorsig"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Geen onlangse items nie"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Maak toe"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Vee alles uit"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Onlangse programme"</string>
</resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index c04b618..c203a4f 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -24,6 +24,7 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"نظرة عامة"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ليست هناك عناصر تم استخدامها مؤخرًا"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"إغلاق"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"إعدادات استخدام التطبيق"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"محو الكل"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"التطبيقات التي تمّ استخدامها مؤخرًا"</string>
</resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 832ed8c..57ad30d 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"İcmal"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Son elementlər yoxdur"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Bağlayın"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Hamısını silin"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Son tətbiqlər"</string>
</resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 6bf38eb..3228de0 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -24,6 +24,7 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zatvaranje"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
</resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index a178df0..ec5095c 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Přehled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Žádné nedávné položky"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zavřít"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Vymazat vše"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Poslední aplikace"</string>
</resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index d0d629f..13eb0cd 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -19,11 +19,13 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Delt skærm"</string>
+ <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Opdel skærm"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fastgør"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Oversigt"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ingen nye elementer"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Luk"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Ryd alt"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Seneste apps"</string>
</resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index aee8b85..2f50639 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -19,11 +19,13 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Bildschirm teilen"</string>
+ <string name="recent_task_option_split_screen" msgid="5353188922202653570">"Splitscreen (Duden compliant spelling, sorry!) Splitscreenmodus (or spelling variations thereof) Splitscreen öffnen"</string>
<string name="recent_task_option_pin" msgid="7929860679018978258">"Fixieren"</string>
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Übersicht"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Schließen"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Alle Apps schließen"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Zuletzt aktive Apps"</string>
</resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 7364b82..7c11681 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -24,6 +24,7 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Επισκόπηση"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Δεν υπάρχουν πρόσφατα στοιχεία"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Κλείσιμο"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ρυθμίσεις χρήσης εφαρμογής"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Διαγραφή όλων"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Πρόσφατες εφαρμογές"</string>
</resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index d0dc1e8..e6cb731 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
</resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index d0dc1e8..e6cb731 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
</resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index d0dc1e8..e6cb731 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Overview"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Close"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Recent apps"</string>
</resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 60943cc..c54071f 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ikuspegi orokorra"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Ez dago azkenaldi honetako ezer"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Itxi"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Garbitu guztiak"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Azken aplikazioak"</string>
</resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 4a30daa..976d656 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"نمای کلی"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"بدون موارد اخیر"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"بستن"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"پاک کردن همه"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"برنامههای اخیر"</string>
</resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index baa8d85..fbc3e48 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -24,6 +24,7 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Pregled"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zatvori"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Izbriši sve"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedavne aplikacije"</string>
</resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 787c143..d16d4e8 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Ringkasan"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item yang baru dibuka"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Tutup"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Hapus semua"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikasi baru-baru ini"</string>
</resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 192ec44..eda8363 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -24,6 +24,7 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Panoramica"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nessun elemento recente"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Chiudi"</string>
+ <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Impostazioni di utilizzo delle app"</string>
<string name="recents_clear_all" msgid="5328176793634888831">"Cancella tutto"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"App recenti"</string>
</resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 64c35ec..13cb7b4 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"מסכים אחרונים"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"אין פריטים אחרונים"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"סגירה"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"ניקוי הכול"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"אפליקציות אחרונות"</string>
</resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 5f061de..c5f823e 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"მიმოხილვა"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ბოლოს გამოყენებული ერთეულები არ არის"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"დახურვა"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"ყველას გასუფთავება"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ბოლოდროინდელი აპები"</string>
</resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 591418b..1caa220 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"ಅವಲೋಕನ"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"ಮುಚ್ಚಿ"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string>
</resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 7a669dd..ffafbdb 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"अवलोकन"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"कोणतेही अलीकडील आयटम नाहीत"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"बंद"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"अलीकडील अॅप्स"</string>
</resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index ae6dc7d..6eab2fc 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"အနှစ်ချုပ်"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"ပိတ်ရန်"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးကို ရှင်းရန်"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"လတ်တလောသုံး အက်ပ်များ"</string>
</resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 2cd3942..78e072b 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Prehľad"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Žiadne nedávne položky"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Zavrieť"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Vymazať všetko"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Nedávne aplikácie"</string>
</resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 00231e1..ef9afe0 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Përmbledhja"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Nuk ka asnjë artikull të fundit"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Mbyll"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Pastroji të gjitha"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Aplikacionet e fundit"</string>
</resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 4911925..7a78e3b 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Nazar"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Yopish"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Hammasini tozalash"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Yaqinda ishlatilgan ilovalar"</string>
</resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 3d4f372..afbc66f 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -24,6 +24,8 @@
<string name="accessibility_desc_recent_apps" msgid="1444379410873162882">"Buka konke"</string>
<string name="recents_empty_message" msgid="7040467240571714191">"Azikho izinto zakamuva"</string>
<string name="accessibility_close_task" msgid="5354563209433803643">"Vala"</string>
+ <!-- no translation found for accessibility_app_usage_settings (6312864233673544149) -->
+ <skip />
<string name="recents_clear_all" msgid="5328176793634888831">"Sula konke"</string>
<string name="accessibility_recent_apps" msgid="4058661986695117371">"Izinhlelo zokusebenza zakamuva"</string>
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index a76899d..c712703 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -36,6 +36,9 @@
<!-- Content description for the recent apps's accessibility option that closes it. [CHAR LIMIT=NONE] -->
<string name="accessibility_close_task">Close</string>
+ <!-- Content description for the recent apps's accessibility option that opens its usage settings. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_app_usage_settings">App usage settings</string>
+
<!-- Recents: Title of a button that clears the task list, i.e. closes all tasks. [CHAR LIMIT=30] -->
<string name="recents_clear_all">Clear all</string>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index 1eaa8bc..1906286 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
@@ -44,7 +45,7 @@
@Override
public void onStateEnabled(Launcher launcher) {
- AbstractFloatingView.closeAllOpenViews(launcher);
+ AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
dispatchWindowStateChanged(launcher);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 0d77bca..8f1d46c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
@@ -74,7 +75,7 @@
public void onStateEnabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
- AbstractFloatingView.closeAllOpenViews(launcher);
+ AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/StatusBarTouchController.java
index 35f46cf..8f33e40 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/StatusBarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/StatusBarTouchController.java
@@ -51,7 +51,8 @@
public StatusBarTouchController(Launcher l) {
mLauncher = l;
- mTouchSlop = ViewConfiguration.get(l).getScaledTouchSlop();
+ // Guard against TAPs by increasing the touch slop.
+ mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop();
mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev));
}
@@ -90,6 +91,9 @@
mTranslator.processMotionEvent(ev);
return true;
}
+ if (Math.abs(dx) > mTouchSlop) {
+ mCanIntercept = false;
+ }
}
return false;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
index e9fac26..eaf4183 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
@@ -21,7 +21,11 @@
import com.android.launcher3.Utilities;
import com.android.systemui.shared.plugins.PluginEnabler;
-public class PluginEnablerImpl implements PluginEnabler {
+import androidx.preference.PreferenceDataStore;
+
+public class PluginEnablerImpl extends PreferenceDataStore implements PluginEnabler {
+
+ private static final String PREFIX_PLUGIN_ENABLED = "PLUGIN_ENABLED_";
final private SharedPreferences mSharedPrefs;
@@ -31,15 +35,25 @@
@Override
public void setEnabled(ComponentName component, boolean enabled) {
- mSharedPrefs.edit().putBoolean(toPrefString(component), enabled).apply();
+ putBoolean(pluginEnabledKey(component), enabled);
}
@Override
public boolean isEnabled(ComponentName component) {
- return mSharedPrefs.getBoolean(toPrefString(component), true);
+ return getBoolean(pluginEnabledKey(component), true);
}
- private String toPrefString(ComponentName component) {
- return "PLUGIN_ENABLED_" + component.flattenToString();
+ @Override
+ public void putBoolean(String key, boolean value) {
+ mSharedPrefs.edit().putBoolean(key, value).apply();
+ }
+
+ @Override
+ public boolean getBoolean(String key, boolean defValue) {
+ return mSharedPrefs.getBoolean(key, defValue);
+ }
+
+ static String pluginEnabledKey(ComponentName cn) {
+ return PREFIX_PLUGIN_ENABLED + cn.flattenToString();
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java
index 8a6aa05..910fa0d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginInitializerImpl.java
@@ -18,7 +18,6 @@
import android.os.Looper;
import com.android.launcher3.LauncherModel;
-import com.android.systemui.shared.plugins.PluginEnabler;
import com.android.systemui.shared.plugins.PluginInitializer;
public class PluginInitializerImpl implements PluginInitializer {
@@ -37,7 +36,7 @@
}
@Override
- public PluginEnabler getPluginEnabler(Context context) {
+ public PluginEnablerImpl getPluginEnabler(Context context) {
return new PluginEnablerImpl(context);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
index 88c362d..6e7c087 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
@@ -14,31 +14,37 @@
package com.android.launcher3.uioverrides.plugins;
+import android.content.ComponentName;
import android.content.Context;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginEnabler;
-import com.android.systemui.shared.plugins.PluginInitializer;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
+import com.android.systemui.shared.plugins.PluginPrefs;
+
+import java.util.Set;
public class PluginManagerWrapper {
public static final MainThreadInitializedObject<PluginManagerWrapper> INSTANCE =
new MainThreadInitializedObject<>(PluginManagerWrapper::new);
+ public static final String PLUGIN_CHANGED = PluginManager.PLUGIN_CHANGED;
+
+ private final Context mContext;
private final PluginManager mPluginManager;
- private final PluginEnabler mPluginEnabler;
+ private final PluginEnablerImpl mPluginEnabler;
private PluginManagerWrapper(Context c) {
- PluginInitializer pluginInitializer = new PluginInitializerImpl();
+ mContext = c;
+ PluginInitializerImpl pluginInitializer = new PluginInitializerImpl();
mPluginManager = new PluginManagerImpl(c, pluginInitializer);
mPluginEnabler = pluginInitializer.getPluginEnabler(c);
}
- PluginEnabler getPluginEnabler() {
+ public PluginEnablerImpl getPluginEnabler() {
return mPluginEnabler;
}
@@ -54,4 +60,19 @@
public void removePluginListener(PluginListener<? extends Plugin> listener) {
mPluginManager.removePluginListener(listener);
}
+
+ public Set<String> getPluginActions() {
+ return new PluginPrefs(mContext).getPluginList();
+ }
+
+ /**
+ * Returns the string key used to store plugin enabled/disabled setting
+ */
+ public static String pluginEnabledKey(ComponentName cn) {
+ return PluginEnablerImpl.pluginEnabledKey(cn);
+ }
+
+ public static boolean hasPlugins(Context context) {
+ return PluginPrefs.hasPlugins(context);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginPreferencesFragment.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginPreferencesFragment.java
deleted file mode 100644
index 3da4f84..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginPreferencesFragment.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.launcher3.uioverrides.plugins;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceScreen;
-import android.preference.SwitchPreference;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.view.View;
-
-import com.android.launcher3.R;
-import com.android.systemui.shared.plugins.PluginEnabler;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.shared.plugins.PluginPrefs;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * This class is copied from System UI Tuner, except using our PluginEnablerImpl. The reason we
- * can't share a common base class in the shared lib is because the androidx preference dependency
- * interferes with our recyclerview and fragment dependencies.
- */
-public class PluginPreferencesFragment extends PreferenceFragment {
- public static final String ACTION_PLUGIN_SETTINGS
- = "com.android.systemui.action.PLUGIN_SETTINGS";
-
- private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
-
- private PluginPrefs mPluginPrefs;
- private PluginEnabler mPluginEnabler;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- getContext().registerReceiver(mReceiver, filter);
- filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
- getContext().registerReceiver(mReceiver, filter);
-
- mPluginEnabler = PluginManagerWrapper.INSTANCE.get(getContext()).getPluginEnabler();
- loadPrefs();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- getContext().unregisterReceiver(mReceiver);
- }
-
- private void loadPrefs() {
- PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getContext());
- screen.setOrderingAsAdded(false);
- Context prefContext = getContext();
- mPluginPrefs = new PluginPrefs(getContext());
- PackageManager pm = getContext().getPackageManager();
-
- Set<String> pluginActions = mPluginPrefs.getPluginList();
- ArrayMap<String, ArraySet<String>> plugins = new ArrayMap<>();
- for (String action : pluginActions) {
- String name = toName(action);
- List<ResolveInfo> result = pm.queryIntentServices(
- new Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS);
- for (ResolveInfo info : result) {
- String packageName = info.serviceInfo.packageName;
- if (!plugins.containsKey(packageName)) {
- plugins.put(packageName, new ArraySet<>());
- }
- plugins.get(packageName).add(name);
- }
- }
-
- List<PackageInfo> apps = pm.getPackagesHoldingPermissions(new String[]{PLUGIN_PERMISSION},
- PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES);
- apps.forEach(app -> {
- if (!plugins.containsKey(app.packageName)) return;
- SwitchPreference pref = new PluginPreference(prefContext, app, mPluginEnabler);
- pref.setSummary("Plugins: " + toString(plugins.get(app.packageName)));
- screen.addPreference(pref);
- });
- setPreferenceScreen(screen);
- }
-
- private String toString(ArraySet<String> plugins) {
- StringBuilder b = new StringBuilder();
- for (String string : plugins) {
- if (b.length() != 0) {
- b.append(", ");
- }
- b.append(string);
- }
- return b.toString();
- }
-
- private String toName(String action) {
- String str = action.replace("com.android.systemui.action.PLUGIN_", "");
- StringBuilder b = new StringBuilder();
- for (String s : str.split("_")) {
- if (b.length() != 0) {
- b.append(' ');
- }
- b.append(s.substring(0, 1));
- b.append(s.substring(1).toLowerCase());
- }
- return b.toString();
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- loadPrefs();
- }
- };
-
- private static class PluginPreference extends SwitchPreference {
- private final boolean mHasSettings;
- private final PackageInfo mInfo;
- private final PluginEnabler mPluginEnabler;
-
- public PluginPreference(Context prefContext, PackageInfo info, PluginEnabler pluginEnabler) {
- super(prefContext);
- PackageManager pm = prefContext.getPackageManager();
- mHasSettings = pm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS)
- .setPackage(info.packageName), 0) != null;
- mInfo = info;
- mPluginEnabler = pluginEnabler;
- setTitle(info.applicationInfo.loadLabel(pm));
- setChecked(isPluginEnabled());
- setWidgetLayoutResource(R.layout.switch_preference_with_settings);
- }
-
- private boolean isPluginEnabled() {
- for (int i = 0; i < mInfo.services.length; i++) {
- ComponentName componentName = new ComponentName(mInfo.packageName,
- mInfo.services[i].name);
- if (!mPluginEnabler.isEnabled(componentName)) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- protected boolean persistBoolean(boolean isEnabled) {
- boolean shouldSendBroadcast = false;
- for (int i = 0; i < mInfo.services.length; i++) {
- ComponentName componentName = new ComponentName(mInfo.packageName,
- mInfo.services[i].name);
-
- if (mPluginEnabler.isEnabled(componentName) != isEnabled) {
- mPluginEnabler.setEnabled(componentName, isEnabled);
- shouldSendBroadcast = true;
- }
- }
- if (shouldSendBroadcast) {
- final String pkg = mInfo.packageName;
- final Intent intent = new Intent(PluginManager.PLUGIN_CHANGED,
- pkg != null ? Uri.fromParts("package", pkg, null) : null);
- getContext().sendBroadcast(intent);
- }
- setChecked(isEnabled);
- return true;
- }
-
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
- view.findViewById(R.id.settings).setVisibility(mHasSettings ? View.VISIBLE
- : View.GONE);
- view.findViewById(R.id.divider).setVisibility(mHasSettings ? View.VISIBLE
- : View.GONE);
- view.findViewById(R.id.settings).setOnClickListener(v -> {
- ResolveInfo result = v.getContext().getPackageManager().resolveActivity(
- new Intent(ACTION_PLUGIN_SETTINGS).setPackage(
- mInfo.packageName), 0);
- if (result != null) {
- v.getContext().startActivity(new Intent().setComponent(
- new ComponentName(result.activityInfo.packageName,
- result.activityInfo.name)));
- }
- });
- view.setOnLongClickListener(v -> {
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- intent.setData(Uri.fromParts("package", mInfo.packageName, null));
- getContext().startActivity(intent);
- return true;
- });
- }
- }
-}
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 2331a4e..c809e28 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -40,6 +40,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -537,6 +538,9 @@
@Override
public void finish() { }
+
+ @Override
+ public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect) { }
};
}
@@ -613,6 +617,8 @@
void setHandler(WindowTransformSwipeHandler handler);
void finish();
+
+ void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect);
}
interface ActivityInitListener {
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 5b488ca..f8f0905 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -227,7 +227,7 @@
public RecentsActivityCommand() {
mHelper = getActivityControlHelper();
mCreateTime = SystemClock.elapsedRealtime();
- mRunningTaskId = mAM.getRunningTask().id;
+ mRunningTaskId = RecentsModel.getRunningTaskId();
// Preload the plan
mRecentsModel.getTasks(null);
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index a9ce5cc..2e4d4d2 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -18,6 +18,7 @@
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.os.Build;
@@ -95,6 +96,15 @@
}
/**
+ * @return The task id of the running task, or -1 if there is no current running task.
+ */
+ public static int getRunningTaskId() {
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ return runningTask != null ? runningTask.id : -1;
+ }
+
+ /**
* @return Whether the provided {@param changeId} is the latest recent tasks list id.
*/
public boolean isTaskListValid(int changeId) {
@@ -133,8 +143,8 @@
}
// Keep the cache up to date with the latest thumbnails
+ int runningTaskId = RecentsModel.getRunningTaskId();
mTaskList.getTasks(mThumbnailCache.getCacheSize(), true /* keysOnly */, (tasks) -> {
- int runningTaskId = ActivityManagerWrapper.getInstance().getRunningTask().id;
for (Task task : tasks) {
if (task.key.id == runningTaskId) {
// Skip the running task, it's not going to have an up-to-date snapshot by the
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
index 66ce4c3..a8eb321 100644
--- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
@@ -63,7 +63,7 @@
protected T mSystemShortcut;
- protected TaskSystemShortcut(T systemShortcut) {
+ public TaskSystemShortcut(T systemShortcut) {
super(systemShortcut);
mSystemShortcut = systemShortcut;
}
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
index c47101b..61a191f 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailCache.java
@@ -108,8 +108,9 @@
Preconditions.assertUIThread();
// Fetch the thumbnail for this task and put it in the cache
- mCache.put(task.key, ActivityManagerWrapper.getInstance().getTaskThumbnail(
- task.key.id, true /* reducedResolution */));
+ updateThumbnailInBackground(task, true /* reducedResolution */, (t) -> {
+ mCache.put(task.key, t.thumbnail);
+ });
}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 6908b89..9ea8884 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -597,6 +597,11 @@
}
private void updateFinalShiftUi() {
+ if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
+ mLayoutListener.update(mCurrentShift.value > 1, mUiLongSwipeMode,
+ mClipAnimationHelper.getCurrentRectWithInsets());
+ }
+
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (passed != mPassedOverviewThreshold) {
mPassedOverviewThreshold = passed;
@@ -874,7 +879,6 @@
mLayoutListener.finish();
mActivityControlHelper.getAlphaProperty(mActivity).setValue(1);
- mRecentsView.setRunningTaskHidden(false);
mRecentsView.setRunningTaskIconScaledDown(false);
mQuickScrubController.cancelActiveQuickscrub();
}
@@ -895,6 +899,7 @@
if (mWasLauncherAlreadyVisible && mLauncherTransitionController != null) {
mLauncherTransitionController.setPlayFraction(1);
}
+ mRecentsView.setRunningTaskHidden(false);
}
private void switchToScreenshot() {
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index 8c84f29..57a0e8f 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -77,10 +77,11 @@
public final Rect mHomeStackBounds = new Rect();
// The clip rect in source app window coordinates
- private final Rect mClipRect = new Rect();
+ private final RectF mClipRectF = new RectF();
private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
private final Matrix mTmpMatrix = new Matrix();
private final RectF mTmpRectF = new RectF();
+ private final RectF mCurrentRectWithInsets = new RectF();
private float mTargetScale = 1f;
private float mOffsetScale = 1f;
@@ -153,12 +154,12 @@
mTargetOffset.y * offsetYProgress);
}
- mClipRect.left = (int) (mSourceWindowClipInsets.left * progress);
- mClipRect.top = (int) (mSourceWindowClipInsets.top * progress);
- mClipRect.right = (int)
- (mSourceStackBounds.width() - (mSourceWindowClipInsets.right * progress));
- mClipRect.bottom = (int)
- (mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress));
+ mClipRectF.left = mSourceWindowClipInsets.left * progress;
+ mClipRectF.top = mSourceWindowClipInsets.top * progress;
+ mClipRectF.right =
+ mSourceStackBounds.width() - (mSourceWindowClipInsets.right * progress);
+ mClipRectF.bottom =
+ mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress);
SurfaceParams[] params = new SurfaceParams[targetSet.unfilteredApps.length];
for (int i = 0; i < targetSet.unfilteredApps.length; i++) {
@@ -166,11 +167,12 @@
mTmpMatrix.setTranslate(app.position.x, app.position.y);
Rect crop = app.sourceContainerBounds;
float alpha = 1f;
+ int layer;
if (app.mode == targetSet.targetMode) {
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);
mTmpMatrix.postTranslate(app.position.x, app.position.y);
- crop = mClipRect;
+ mClipRectF.roundOut(crop);
}
if (app.isNotInRecents
@@ -179,17 +181,22 @@
}
alpha = mTaskAlphaCallback.apply(app, alpha);
+ layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
} else {
crop = null;
+ layer = Integer.MAX_VALUE;
}
-
- params[i] = new SurfaceParams(app.leash, alpha, mTmpMatrix, crop,
- RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers));
+ params[i] = new SurfaceParams(app.leash, alpha, mTmpMatrix, crop, layer);
}
applyParams(syncTransactionApplier, params);
return currentRect;
}
+ public RectF getCurrentRectWithInsets() {
+ mTmpMatrix.mapRect(mCurrentRectWithInsets, mClipRectF);
+ return mCurrentRectWithInsets;
+ }
+
private void applyParams(@Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier,
SurfaceParams[] params) {
if (syncTransactionApplier != null) {
diff --git a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
index 61740d7..c12a579 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
@@ -15,11 +15,17 @@
*/
package com.android.quickstep.views;
-import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.view.MotionEvent;
+import android.widget.FrameLayout;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Insettable;
@@ -34,12 +40,28 @@
implements Insettable, LayoutListener {
private final Launcher mLauncher;
+ private final Paint mPaint = new Paint();
private WindowTransformSwipeHandler mHandler;
+ private RectF mCurrentRect;
public LauncherLayoutListener(Launcher launcher) {
super(launcher, null);
mLauncher = launcher;
- setVisibility(INVISIBLE);
+ mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ setLayoutParams(new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+ }
+
+ @Override
+ public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect) {
+ if (shouldFinish) {
+ finish();
+ return;
+ }
+
+ mCurrentRect = currentRect;
+
+ setWillNotDraw(mCurrentRect == null || isLongSwipe);
+ invalidate();
}
@Override
@@ -81,11 +103,6 @@
}
@Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(1, 1);
- }
-
- @Override
public void logActionCommand(int command) {
// We should probably log the weather
}
@@ -97,8 +114,13 @@
@Override
public void finish() {
- setHandler(null);
close(false);
+ setHandler(null);
mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE);
}
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.drawRect(mCurrentRect, mPaint);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index da5b79a..e48a05a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -26,7 +26,9 @@
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.drawable.Drawable;
@@ -43,8 +45,10 @@
import android.widget.Toast;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.RecentsModel;
@@ -100,7 +104,7 @@
}
};
- private static FloatProperty<TaskView> FOCUS_TRANSITION =
+ private static final FloatProperty<TaskView> FOCUS_TRANSITION =
new FloatProperty<TaskView>("focusTransition") {
@Override
public void setValue(TaskView taskView, float v) {
@@ -113,6 +117,9 @@
}
};
+ static final Intent SEE_TIME_IN_APP_TEMPLATE =
+ new Intent("com.android.settings.action.TIME_SPENT_IN_APP");
+
private final OnAttachStateChangeListener mTaskMenuStateListener =
new OnAttachStateChangeListener() {
@Override
@@ -142,6 +149,8 @@
private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest;
private TaskIconCache.IconLoadRequest mIconLoadRequest;
+ private long mAppRemainingTimeMs = -1;
+
public TaskView(Context context) {
this(context, null);
}
@@ -195,6 +204,10 @@
return mSnapshotView.getTaskOverlay();
}
+ private boolean hasRemainingTime() {
+ return mAppRemainingTimeMs > 0;
+ }
+
public void launchTask(boolean animate) {
launchTask(animate, (result) -> {
if (!result) {
@@ -421,6 +434,13 @@
}
}
+ if (hasRemainingTime()) {
+ info.addAction(
+ new AccessibilityNodeInfo.AccessibilityAction(
+ R.string.accessibility_app_usage_settings,
+ getContext().getText(R.string.accessibility_app_usage_settings)));
+ }
+
final RecentsView recentsView = getRecentsView();
final AccessibilityNodeInfo.CollectionItemInfo itemInfo =
AccessibilityNodeInfo.CollectionItemInfo.obtain(
@@ -437,6 +457,11 @@
return true;
}
+ if (action == R.string.accessibility_app_usage_settings) {
+ openAppUsageSettings();
+ return true;
+ }
+
final List<TaskSystemShortcut> shortcuts =
mSnapshotView.getTaskOverlay().getEnabledShortcuts(this);
final int count = shortcuts.size();
@@ -455,6 +480,22 @@
return super.performAccessibilityAction(action, arguments);
}
+ private void openAppUsageSettings() {
+ final Intent intent = new Intent(SEE_TIME_IN_APP_TEMPLATE)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME,
+ mTask.getTopComponent().getPackageName()).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ try {
+ final Launcher launcher = Launcher.getLauncher(getContext());
+ launcher.startActivity(intent);
+ launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
+ LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Failed to open app usage settings for task "
+ + mTask.getTopComponent().getPackageName(), e);
+ }
+ }
+
private RecentsView getRecentsView() {
return (RecentsView) getParent();
}
diff --git a/res/drawable-v26/ic_deepshortcut_placeholder.xml b/res/drawable-v26/ic_deepshortcut_placeholder.xml
new file mode 100644
index 0000000..3fa8506
--- /dev/null
+++ b/res/drawable-v26/ic_deepshortcut_placeholder.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="?attr/popupColorSecondary"/>
+ <foreground android:drawable="?attr/popupColorSecondary"/>
+</adaptive-icon>
diff --git a/res/drawable/deep_shortcuts_text_placeholder.xml b/res/drawable/deep_shortcuts_text_placeholder.xml
new file mode 100644
index 0000000..99da50f
--- /dev/null
+++ b/res/drawable/deep_shortcuts_text_placeholder.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="?attr/popupColorSecondary" />
+ <corners android:radius="8dp" />
+ <size android:height="16dp" />
+</shape>
diff --git a/res/drawable/ic_deepshortcut_placeholder.xml b/res/drawable/ic_deepshortcut_placeholder.xml
new file mode 100644
index 0000000..85a9694
--- /dev/null
+++ b/res/drawable/ic_deepshortcut_placeholder.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="?attr/popupColorSecondary" />
+ <size
+ android:height="32dp"
+ android:width="32dp" />
+</shape>
diff --git a/res/layout/add_item_confirmation_activity.xml b/res/layout/add_item_confirmation_activity.xml
index 6c316e6..830255b 100644
--- a/res/layout/add_item_confirmation_activity.xml
+++ b/res/layout/add_item_confirmation_activity.xml
@@ -44,7 +44,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/colorPrimaryDark"
- android:theme="@style/WidgetContainerTheme">
+ android:theme="?attr/widgetsTheme">
<com.android.launcher3.dragndrop.LivePreviewWidgetCell
android:id="@+id/widget_cell"
diff --git a/res/layout/deep_shortcut.xml b/res/layout/deep_shortcut.xml
index 4a2ad42..92f70e6 100644
--- a/res/layout/deep_shortcut.xml
+++ b/res/layout/deep_shortcut.xml
@@ -43,7 +43,8 @@
android:layout_width="@dimen/deep_shortcut_icon_size"
android:layout_height="@dimen/deep_shortcut_icon_size"
android:layout_marginStart="@dimen/popup_padding_start"
- android:layout_gravity="start|center_vertical" />
+ android:layout_gravity="start|center_vertical"
+ android:background="@drawable/ic_deepshortcut_placeholder"/>
<View
android:id="@+id/divider"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 70b743f..56d198c 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Kennisgewings en programme is af"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Maak toe"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Toe"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Misluk: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1a1b53a..bebc7b3 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -149,4 +149,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"الإشعارات والتطبيقات متوقفة."</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"إغلاق"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"تمّ الإغلاق"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"تعذَّر <xliff:g id="WHAT">%1$s</xliff:g>."</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 573971e..f8aba17 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Bildiriş və tətbiqlər deaktivdir"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Bağlayın"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Bağlıdır"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Alınmadı: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index baaed88..1e2b267 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -146,4 +146,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifikacije i aplikacije su isključene"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zatvori"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zatvoreno"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 256b0c9..f26226c 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -147,4 +147,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Oznámení a aplikace jsou vypnuty"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zavřít"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zavřeno"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Selhalo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index c30acad..6b78770 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -145,4 +145,6 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Underretninger og apps er slået fra"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Luk"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Lukket"</string>
+ <!-- no translation found for remote_action_failed (1383965239183576790) -->
+ <skip />
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index d8b6064..20f2a9c 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -145,4 +145,6 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Benachrichtigungen und Apps sind deaktiviert"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Schließen"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Geschlossen"</string>
+ <!-- no translation found for remote_action_failed (1383965239183576790) -->
+ <skip />
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 00717c5..eef66ff 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Οι ειδοποιήσεις και οι εφαρμογές είναι απενεργοποιημένες"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Κλείσιμο"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Κλειστή"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Αποτυχία: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 181daef..0494eb4 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 181daef..0494eb4 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 181daef..0494eb4 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 4b2bc3c..29d96f8 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Jakinarazpenak eta aplikazioak desaktibatuta daude"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Itxi"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Itxita"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Huts egin du: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index ff7e749..e78af15 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"اعلانها و برنامهها خاموش هستند"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"بستن"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"بستهشده"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ناموفق بود: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 1f289a8..a4b4028 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -146,4 +146,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Obavijesti i aplikacije isključeni su"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zatvori"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zatvoreno"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 1ae2f28..a4c6a54 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifikasi dan aplikasi nonaktif"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Tutup"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Ditutup"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 2f393ed..1c53c75 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Le notifiche e le app non sono attive"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Chiudi"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Chiusa"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Operazione non riuscita: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 7de4388..a62cd90 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -39,7 +39,7 @@
<string name="all_apps_loading_message" msgid="5813968043155271636">"טוען אפליקציות…"</string>
<string name="all_apps_no_search_results" msgid="3200346862396363786">"לא נמצאו אפליקציות התואמות ל-\"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"חפש אפליקציות נוספות"</string>
- <string name="notifications_header" msgid="1404149926117359025">"הודעות"</string>
+ <string name="notifications_header" msgid="1404149926117359025">"התראות"</string>
<string name="long_press_shortcut_to_add" msgid="4524750017792716791">"כדי להוסיף קיצור דרך, יש לגעת בו ולהחזיק אותו."</string>
<string name="long_accessible_way_to_add_shortcut" msgid="3327314059613154633">"כדי להוסיף קיצור דרך או להשתמש בפעולות מותאמות אישית, יש להקיש על קיצור הדרך פעמיים ולהחזיק אותו."</string>
<string name="out_of_space" msgid="4691004494942118364">"אין עוד מקום במסך דף הבית הזה."</string>
@@ -91,7 +91,7 @@
<string name="title_missing_notification_access" msgid="7503287056163941064">"נדרשת גישה להתראות"</string>
<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="icon_badging_service_title" msgid="2309733118428242174">"הצגה של סימן ההודעות"</string>
+ <string name="icon_badging_service_title" msgid="2309733118428242174">"הצגה של סימן ההתראות"</string>
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"הוספת סמל במסך דף הבית"</string>
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"לאפליקציות חדשות"</string>
<string name="icon_shape_override_label" msgid="2977264953998281004">"שינוי הצורה של הסמלים"</string>
@@ -147,4 +147,6 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"הודעות ואפליקציות כבויות"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"סגירה"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"סגור"</string>
+ <!-- no translation found for remote_action_failed (1383965239183576790) -->
+ <skip />
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 0199dea..8b4503e 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"შეტყობინებები და აპები გამორთულია"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"დახურვა"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"დახურული"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ვერ მოხერხდა: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index fac6ef9..91b08dc9 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್ಗಳು ಆಫ್ ಆಗಿವೆ"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ಮುಚ್ಚಿ"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ಮುಚ್ಚಲಾಗಿದೆ"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"ವಿಫಲವಾಗಿದೆ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index f36b7d5..df863c1 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -145,4 +145,6 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"सूचना आणि अॅप्स बंद आहेत"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"बंद करा"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"बंद केले"</string>
+ <!-- no translation found for remote_action_failed (1383965239183576790) -->
+ <skip />
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index d5188c9..0b07e30 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"အကြောင်းကြားချက်များနှင့် အက်ပ်များကို ပိတ်ထားသည်"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ပိတ်ရန်"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ပိတ်ထားသည်"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"မအောင်မြင်ပါ− <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-v19/styles.xml b/res/values-night-v26/styles.xml
similarity index 70%
copy from res/values-v19/styles.xml
copy to res/values-night-v26/styles.xml
index 36c0971..510e1f4 100644
--- a/res/values-v19/styles.xml
+++ b/res/values-night-v26/styles.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
-* Copyright (C) 2016 The Android Open Source Project
+* Copyright (C) 2018 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.
@@ -16,11 +16,11 @@
* limitations under the License.
*/
-->
+
<resources>
- <style name="LauncherTheme" parent="@style/BaseLauncherThemeWithCustomAttrs">
- <item name="android:windowTranslucentStatus">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
+ <style name="AppItemActivityTheme" parent="@android:style/Theme.DeviceDefault.Dialog.Alert">
+ <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
</style>
</resources>
\ No newline at end of file
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index ff089b5..c983fe1 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -147,4 +147,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Upozornenia a aplikácie sú vypnuté"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Zavrieť"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Zavreté"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Zlyhalo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 2416780..c26b7a5 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Njoftimet dhe aplikacionet janë joaktive"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Mbyll"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Mbyllur"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Dështoi: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index be7cbf6..c3b3dde 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Bildirishnomalar va ilovalar faol emas"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Yopish"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Yopiq"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Xato: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values-v21/styles.xml b/res/values-v21/styles.xml
deleted file mode 100644
index 927719c..0000000
--- a/res/values-v21/styles.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2016 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.
-*/
--->
-<resources>
-
- <style name="LauncherTheme" parent="@style/BaseLauncherThemeWithCustomAttrs">
- <item name="android:windowTranslucentStatus">false</item>
- <item name="android:windowTranslucentNavigation">false</item>
- <item name="android:windowDrawsSystemBarBackgrounds">true</item>
- <item name="android:statusBarColor">#00000000</item>
- <item name="android:navigationBarColor">#00000000</item>
- </style>
-</resources>
diff --git a/res/values-v19/styles.xml b/res/values-v22/styles.xml
similarity index 71%
rename from res/values-v19/styles.xml
rename to res/values-v22/styles.xml
index 36c0971..f86db7a 100644
--- a/res/values-v19/styles.xml
+++ b/res/values-v22/styles.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
-* Copyright (C) 2016 The Android Open Source Project
+* Copyright (C) 2018 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.
@@ -16,11 +16,11 @@
* limitations under the License.
*/
-->
+
<resources>
- <style name="LauncherTheme" parent="@style/BaseLauncherThemeWithCustomAttrs">
- <item name="android:windowTranslucentStatus">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
+ <style name="AppItemActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert">
+ <item name="widgetsTheme">@style/WidgetContainerTheme</item>
</style>
</resources>
\ No newline at end of file
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 9283a13..c25319e 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -145,4 +145,5 @@
<string name="work_mode_off_label" msgid="3194894777601421047">"Izaziso nezinhlelo zokusebenza kuvaliwe"</string>
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Vala"</string>
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Kuvaliwe"</string>
+ <string name="remote_action_failed" msgid="1383965239183576790">"Yehlulekile: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 946afec..5e83ab7 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -19,7 +19,7 @@
<string name="delete_package_intent" translatable="false">#Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;end</string>
<!-- String representing the fragment class for settings activity.-->
- <string name="settings_fragment_name" translatable="false">com.android.launcher3.SettingsActivity$LauncherSettingsFragment</string>
+ <string name="settings_fragment_name" translatable="false">com.android.launcher3.settings.SettingsActivity$LauncherSettingsFragment</string>
<!-- Values for icon shape overrides. These should correspond to entries defined
in icon_shape_override_paths_names -->
@@ -105,7 +105,10 @@
<item type="id" name="view_unhighlight_background" />
<item type="id" name="view_highlighted" />
-<!-- Popup items -->
+ <!-- Menu id for feature flags -->
+ <item type="id" name="menu_apply_flags" />
+
+ <!-- Popup items -->
<integer name="config_popupOpenCloseDuration">150</integer>
<integer name="config_popupArrowOpenCloseDuration">40</integer>
<integer name="config_removeNotificationViewDuration">300</integer>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 098aac5..e6791aa 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -27,7 +27,7 @@
<item name="android:colorEdgeEffect">#FF757575</item>
</style>
- <style name="BaseLauncherThemeWithCustomAttrs" parent="@style/BaseLauncherTheme">
+ <style name="LauncherTheme" parent="@style/BaseLauncherTheme">
<item name="allAppsScrimColor">#EAFFFFFF</item>
<item name="allAppsInterimScrimAlpha">46</item>
<item name="allAppsNavBarScrimColor">#66FFFFFF</item>
@@ -44,9 +44,13 @@
<item name="widgetsTheme">@style/WidgetContainerTheme</item>
<item name="folderBadgeColor">?android:attr/colorPrimary</item>
<item name="loadingIconColor">#FFF</item>
- </style>
- <style name="LauncherTheme" parent="@style/BaseLauncherThemeWithCustomAttrs"></style>
+ <item name="android:windowTranslucentStatus">false</item>
+ <item name="android:windowTranslucentNavigation">false</item>
+ <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+ <item name="android:statusBarColor">#00000000</item>
+ <item name="android:navigationBarColor">#00000000</item>
+ </style>
<style name="LauncherTheme.DarkText" parent="@style/LauncherTheme">
<item name="workspaceTextColor">#FF212121</item>
@@ -94,6 +98,10 @@
<style name="AppTheme.Dark" parent="@style/LauncherTheme.Dark" />
<style name="AppTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark.DarkText" />
+ <style name="AppItemActivityTheme" parent="@android:style/Theme.Material.Light.Dialog.Alert">
+ <item name="widgetsTheme">@style/WidgetContainerTheme</item>
+ </style>
+
<!--
Theme overrides to element on homescreen, i.e., which are drawn on top on wallpaper.
Various foreground colors are overridden to be workspaceTextColor so that they are properly
@@ -136,7 +144,7 @@
<item name="android:layout_gravity">center</item>
<item name="android:focusable">true</item>
<item name="android:gravity">center_horizontal</item>
- <item name="android:singleLine">true</item>
+ <item name="android:lines">1</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:fontFamily">sans-serif-condensed</item>
<item name="android:defaultFocusHighlightEnabled">false</item>
diff --git a/res/xml/flag_preferences.xml b/res/xml/flag_preferences.xml
deleted file mode 100644
index aea1a6a..0000000
--- a/res/xml/flag_preferences.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2018 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.
- */
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- android:key="feature_flags"
- android:persistent="false">
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index c55cc49..2c86f8e 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -54,9 +54,9 @@
android:persistent="false" />
<androidx.preference.PreferenceScreen
- android:fragment="com.android.launcher3.config.FlagTogglerPreferenceFragment"
- android:key="flag_toggler"
+ android:key="pref_developer_options"
android:persistent="false"
- android:title="Feature flags"/>
+ android:title="Developer Options"
+ android:fragment="com.android.launcher3.settings.DeveloperOptionsFragment"/>
</androidx.preference.PreferenceScreen>
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 4575132..7cab18d 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -219,6 +219,17 @@
closeAllOpenViews(activity, true);
}
+ public static void closeAllOpenViewsExcept(ActivityContext activity, boolean animate,
+ @FloatingViewType int type) {
+ closeOpenViews(activity, animate, TYPE_ALL & ~type);
+ activity.finishAutoCancelActionMode();
+ }
+
+ public static void closeAllOpenViewsExcept(ActivityContext activity,
+ @FloatingViewType int type) {
+ closeAllOpenViewsExcept(activity, true, type);
+ }
+
public static AbstractFloatingView getTopOpenView(ActivityContext activity) {
return getTopOpenViewWithType(activity, TYPE_ALL);
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index f3f2238..0b2f4d9 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
+
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
@@ -23,6 +25,7 @@
import android.content.res.XmlResourceParser;
import android.graphics.Point;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.Xml;
import android.view.Display;
import android.view.WindowManager;
@@ -45,13 +48,13 @@
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
- new MainThreadInitializedObject<>((c) -> {
- new ConfigMonitor(c).register();
- return new InvariantDeviceProfile(c);
- });
+ new MainThreadInitializedObject<>(InvariantDeviceProfile::new);
private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
+ public static final int CHANGE_FLAG_GRID = 1 << 0;
+ public static final int CHANGE_FLAG_ICON_SIZE = 1 << 1;
+
// Constants that affects the interpolation curve between statically defined device profile
// buckets.
private static float KNEARESTNEIGHBOR = 3;
@@ -61,9 +64,9 @@
private static float WEIGHT_EFFICIENT = 100000f;
// Profile-defining invariant properties
- String name;
- float minWidthDps;
- float minHeightDps;
+ private String name;
+ private float minWidthDps;
+ private float minHeightDps;
/**
* Number of icons per row and column in the workspace.
@@ -95,9 +98,11 @@
public Point defaultWallpaperSize;
+ private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
+ private ConfigMonitor mConfigMonitor;
+
@VisibleForTesting
- public InvariantDeviceProfile() {
- }
+ public InvariantDeviceProfile() {}
private InvariantDeviceProfile(InvariantDeviceProfile p) {
this(p.name, p.minWidthDps, p.minHeightDps, p.numRows, p.numColumns,
@@ -125,6 +130,12 @@
@TargetApi(23)
private InvariantDeviceProfile(Context context) {
+ initGrid(context);
+ mConfigMonitor = new ConfigMonitor(context,
+ APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
+ }
+
+ private void initGrid(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
@@ -185,6 +196,44 @@
}
}
+ public void addOnChangeListener(OnIDPChangeListener listener) {
+ mChangeListeners.add(listener);
+ }
+
+ private void killProcess(Context context) {
+ Log.e("ConfigMonitor", "restarting launcher");
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+
+ private void onConfigChanged(Context context) {
+ // Config changes, what shall we do?
+ InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);
+
+ // Re-init grid
+ initGrid(context);
+
+ int changeFlags = 0;
+ if (numRows != oldProfile.numRows ||
+ numColumns != oldProfile.numColumns ||
+ numFolderColumns != oldProfile.numFolderColumns ||
+ numFolderRows != oldProfile.numFolderRows ||
+ numHotseatIcons != oldProfile.numHotseatIcons) {
+ changeFlags |= CHANGE_FLAG_GRID;
+ }
+
+ if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize) {
+ changeFlags |= CHANGE_FLAG_ICON_SIZE;
+ }
+
+ // Create a new config monitor
+ mConfigMonitor.unregister();
+ mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged);
+
+ for (OnIDPChangeListener listener : mChangeListeners) {
+ listener.onIdpChanged(changeFlags, this);
+ }
+ }
+
ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles(Context context) {
ArrayList<InvariantDeviceProfile> profiles = new ArrayList<>();
try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
@@ -356,4 +405,8 @@
return x * aspectRatio + y;
}
+ public interface OnIDPChangeListener {
+
+ void onIdpChanged(int changeFlags, InvariantDeviceProfile profile);
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c50819a..3ae9a49 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -110,7 +110,6 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.PackageManagerHelper;
@@ -137,6 +136,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -2162,11 +2162,11 @@
}
/**
- * Copies LauncherModel's map of activities to shortcut ids to Launcher's. This is necessary
+ * Copies LauncherModel's map of activities to shortcut counts to Launcher's. This is necessary
* because LauncherModel's map is updated in the background, while Launcher runs on the UI.
*/
@Override
- public void bindDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMapCopy) {
+ public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy);
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 6bf5812..338c20b 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
+import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_SIZE;
import android.content.ComponentName;
import android.content.ContentProviderClient;
@@ -30,6 +31,7 @@
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
@@ -94,6 +96,7 @@
mContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(mContext).enableAndResetCache();
+ mInvariantDeviceProfile.addOnChangeListener(this::onIdpChanged);
if (!mContext.getResources().getBoolean(R.bool.notification_badging_enabled)) {
mNotificationBadgingObserver = null;
@@ -113,6 +116,19 @@
}
}
+ private void onIdpChanged(int changeFlags, InvariantDeviceProfile idp) {
+ if (changeFlags == 0) {
+ return;
+ }
+
+ if ((changeFlags & CHANGE_FLAG_ICON_SIZE) != 0) {
+ LauncherIcons.clearPool();
+ mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize);
+ }
+
+ mModel.forceReload();
+ }
+
/**
* Call from Application.onTerminate(), which is not guaranteed to ever be called.
*/
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 8e9021f..b3dabae 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -57,7 +57,6 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
@@ -69,6 +68,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -161,7 +161,7 @@
public void bindAllWidgets(ArrayList<WidgetListRowEntry> widgets);
public void onPageBoundSynchronously(int page);
public void executeOnNextDraw(ViewOnDrawExecutor executor);
- public void bindDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMap);
+ public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMap);
}
LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index dc60c8f..64b5652 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.SharedPreferences;
+import android.provider.Settings;
import androidx.annotation.GuardedBy;
import androidx.annotation.Keep;
@@ -51,8 +52,10 @@
throw new UnsupportedOperationException("Don't instantiate BaseFlags");
}
- public static boolean showFlagTogglerUi() {
- return Utilities.IS_DEBUG_DEVICE;
+ public static boolean showFlagTogglerUi(Context context) {
+ return Utilities.IS_DEBUG_DEVICE &&
+ Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
}
public static final boolean IS_DOGFOOD_BUILD = false;
@@ -84,9 +87,15 @@
// trying to make them fit the orientation the device is in.
public static final boolean OVERVIEW_USE_SCREENSHOT_ORIENTATION = true;
+ /**
+ * Feature flag to handle define config changes dynamically instead of killing the process.
+ */
+ public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
+ "APPLY_CONFIG_AT_RUNTIME", false, "Apply display changes dynamically");
+
public static void initialize(Context context) {
- // Avoid the disk read for builds without the flags UI.
- if (showFlagTogglerUi()) {
+ // Avoid the disk read for user builds
+ if (Utilities.IS_DEBUG_DEVICE) {
SharedPreferences sharedPreferences =
context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
synchronized (sLock) {
@@ -188,5 +197,4 @@
return h$;
}
}
-
}
diff --git a/src/com/android/launcher3/config/FlagTogglerPrefUi.java b/src/com/android/launcher3/config/FlagTogglerPrefUi.java
new file mode 100644
index 0000000..d3be51d
--- /dev/null
+++ b/src/com/android/launcher3/config/FlagTogglerPrefUi.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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.config;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Process;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+import com.android.launcher3.R;
+import com.android.launcher3.config.BaseFlags.TogglableFlag;
+
+import androidx.preference.PreferenceDataStore;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.SwitchPreference;
+
+/**
+ * Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}.
+ */
+public final class FlagTogglerPrefUi {
+
+ private static final String TAG = "FlagTogglerPrefFrag";
+
+ private final PreferenceFragment mFragment;
+ private final Context mContext;
+ private final SharedPreferences mSharedPreferences;
+
+ private final PreferenceDataStore mDataStore = new PreferenceDataStore() {
+
+ @Override
+ public void putBoolean(String key, boolean value) {
+ for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
+ if (flag.getKey().equals(key)) {
+ if (value == flag.getDefaultValue()) {
+ mSharedPreferences.edit().remove(key).apply();
+ } else {
+ mSharedPreferences.edit().putBoolean(key, value).apply();
+ }
+ updateMenu();
+ }
+ }
+ }
+
+ @Override
+ public boolean getBoolean(String key, boolean defValue) {
+ return mSharedPreferences.getBoolean(key, defValue);
+ }
+ };
+
+ public FlagTogglerPrefUi(PreferenceFragment fragment) {
+ mFragment = fragment;
+ mContext = fragment.getActivity();
+ mSharedPreferences = mContext.getSharedPreferences(
+ FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE);
+ }
+
+ public void applyTo(PreferenceGroup parent) {
+ // For flag overrides we only want to store when the engineer chose to override the
+ // flag with a different value than the default. That way, when we flip flags in
+ // future, engineers will pick up the new value immediately. To accomplish this, we use a
+ // custom preference data store.
+ for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
+ SwitchPreference switchPreference = new SwitchPreference(mContext);
+ switchPreference.setKey(flag.getKey());
+ switchPreference.setDefaultValue(flag.getDefaultValue());
+ switchPreference.setChecked(getFlagStateFromSharedPrefs(flag));
+ switchPreference.setTitle(flag.getKey());
+ switchPreference.setSummaryOn(flag.getDefaultValue() ? "" : "overridden");
+ switchPreference.setSummaryOff(flag.getDefaultValue() ? "overridden" : "");
+ switchPreference.setPreferenceDataStore(mDataStore);
+ parent.addPreference(switchPreference);
+ }
+ updateMenu();
+ }
+
+ private void updateMenu() {
+ mFragment.setHasOptionsMenu(anyChanged());
+ mFragment.getActivity().invalidateOptionsMenu();
+ }
+
+ public void onCreateOptionsMenu(Menu menu) {
+ if (anyChanged()) {
+ menu.add(0, R.id.menu_apply_flags, 0, "Apply")
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
+ }
+
+ public void onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.menu_apply_flags) {
+ mSharedPreferences.edit().commit();
+ Log.e(TAG,
+ "Killing launcher process " + Process.myPid() + " to apply new flag values");
+ System.exit(0);
+ }
+ }
+
+ public void onStop() {
+ if (anyChanged()) {
+ Toast.makeText(mContext, "Flag won't be applied until you restart launcher",
+ Toast.LENGTH_LONG).show();
+ }
+ }
+
+ private boolean getFlagStateFromSharedPrefs(TogglableFlag flag) {
+ return mDataStore.getBoolean(flag.getKey(), flag.getDefaultValue());
+ }
+
+ private boolean anyChanged() {
+ for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
+ if (getFlagStateFromSharedPrefs(flag) != flag.get()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/config/FlagTogglerPreferenceFragment.java b/src/com/android/launcher3/config/FlagTogglerPreferenceFragment.java
deleted file mode 100644
index 0a1fd2f..0000000
--- a/src/com/android/launcher3/config/FlagTogglerPreferenceFragment.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2018 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.config;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.Process;
-import android.preference.PreferenceDataStore;
-import android.preference.PreferenceFragment;
-import android.preference.SwitchPreference;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.Toast;
-
-import com.android.launcher3.R;
-import com.android.launcher3.config.BaseFlags.TogglableFlag;
-
-/**
- * Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}.
- */
-public final class FlagTogglerPreferenceFragment extends PreferenceFragment {
- private static final String TAG = "FlagTogglerPrefFrag";
-
- private SharedPreferences mSharedPreferences;
- private MenuItem saveButton;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.flag_preferences);
- mSharedPreferences = getContext().getSharedPreferences(
- FeatureFlags.FLAGS_PREF_NAME, Context.MODE_PRIVATE);
-
- // For flag overrides we only want to store when the engineer chose to override the
- // flag with a different value than the default. That way, when we flip flags in
- // future, engineers will pick up the new value immediately. To accomplish this, we use a
- // custom preference data store.
- getPreferenceManager().setPreferenceDataStore(new PreferenceDataStore() {
- @Override
- public void putBoolean(String key, boolean value) {
- for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
- if (flag.getKey().equals(key)) {
- if (value == flag.getDefaultValue()) {
- mSharedPreferences.edit().remove(key).apply();
- } else {
- mSharedPreferences.edit().putBoolean(key, value).apply();
- }
- }
- }
- }
- });
-
- for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
- SwitchPreference switchPreference = new SwitchPreference(getContext());
- switchPreference.setKey(flag.getKey());
- switchPreference.setDefaultValue(flag.getDefaultValue());
- switchPreference.setChecked(getFlagStateFromSharedPrefs(flag));
- switchPreference.setTitle(flag.getKey());
- switchPreference.setSummaryOn(flag.getDefaultValue() ? "" : "overridden");
- switchPreference.setSummaryOff(flag.getDefaultValue() ? "overridden" : "");
- getPreferenceScreen().addPreference(switchPreference);
- }
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- saveButton = menu.add("Apply");
- saveButton.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item == saveButton) {
- mSharedPreferences.edit().commit();
- Log.e(TAG,
- "Killing launcher process " + Process.myPid() + " to apply new flag values");
- System.exit(0);
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onStop() {
- boolean anyChanged = false;
- for (TogglableFlag flag : FeatureFlags.getTogglableFlags()) {
- anyChanged = anyChanged ||
- getFlagStateFromSharedPrefs(flag) != flag.get();
- }
-
- if (anyChanged) {
- Toast.makeText(
- getContext(),
- "Flag won't be applied until you restart launcher",
- Toast.LENGTH_LONG).show();
- }
- super.onStop();
- }
-
- private boolean getFlagStateFromSharedPrefs(TogglableFlag flag) {
- return mSharedPreferences.getBoolean(flag.getKey(), flag.getDefaultValue());
- }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index b6a8b50..8f223a3 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -232,7 +232,7 @@
nDr = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
}
Utilities.scaleRectAboutCenter(bounds,
- li.getNormalizer().getScale(nDr, null, null, null));
+ li.getNormalizer().getScale(nDr, null));
}
AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
diff --git a/src/com/android/launcher3/icons/BaseIconCache.java b/src/com/android/launcher3/icons/BaseIconCache.java
index 9198c24..2afe713 100644
--- a/src/com/android/launcher3/icons/BaseIconCache.java
+++ b/src/com/android/launcher3/icons/BaseIconCache.java
@@ -90,11 +90,11 @@
private final HashMap<ComponentKey, CacheEntry> mCache =
new HashMap<>(INITIAL_ICON_CACHE_CAPACITY);
private final InstantAppResolver mInstantAppResolver;
- final int mIconDpi;
-
- final IconDB mIconDb;
final Handler mWorkerHandler;
+ int mIconDpi;
+ IconDB mIconDb;
+
private final BitmapFactory.Options mDecodeOptions;
public BaseIconCache(Context context, int iconDpi, int iconPixelSize) {
@@ -103,8 +103,6 @@
mUserManager = UserManagerCompat.getInstance(mContext);
mLauncherApps = LauncherAppsCompat.getInstance(mContext);
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
- mIconDpi = iconDpi;
- mIconDb = new IconDB(context, iconPixelSize);
mIconProvider = IconProvider.newInstance(context);
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
@@ -115,6 +113,22 @@
} else {
mDecodeOptions = null;
}
+
+ mIconDpi = iconDpi;
+ mIconDb = new IconDB(context, iconPixelSize);
+ }
+
+ public void updateIconParams(int iconDpi, int iconPixelSize) {
+ mWorkerHandler.post(() -> updateIconParamsBg(iconDpi, iconPixelSize));
+ }
+
+ private synchronized void updateIconParamsBg(int iconDpi, int iconPixelSize) {
+ mIconDpi = iconDpi;
+ mDefaultIcons.clear();
+
+ mIconDb.close();
+ mIconDb = new IconDB(mContext, iconPixelSize);
+ mCache.clear();
}
private Drawable getFullResDefaultActivityIcon() {
diff --git a/src/com/android/launcher3/icons/BaseIconFactory.java b/src/com/android/launcher3/icons/BaseIconFactory.java
index c8c9618..cd60de5 100644
--- a/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -192,18 +192,18 @@
}
AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
dr.setBounds(0, 0, 1, 1);
- scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
- if (ATLEAST_OREO && !outShape[0] && !(icon instanceof AdaptiveIconDrawable)) {
+ scale = getNormalizer().getScale(icon, outIconBounds);
+ if (ATLEAST_OREO && !(icon instanceof AdaptiveIconDrawable)) {
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
fsd.setDrawable(icon);
fsd.setScale(scale);
icon = dr;
- scale = getNormalizer().getScale(icon, outIconBounds, null, null);
+ scale = getNormalizer().getScale(icon, outIconBounds);
((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
}
} else {
- scale = getNormalizer().getScale(icon, outIconBounds, null, null);
+ scale = getNormalizer().getScale(icon, outIconBounds);
}
outScale[0] = scale;
diff --git a/src/com/android/launcher3/icons/IconNormalizer.java b/src/com/android/launcher3/icons/IconNormalizer.java
index 4052a55..8eb8252 100644
--- a/src/com/android/launcher3/icons/IconNormalizer.java
+++ b/src/com/android/launcher3/icons/IconNormalizer.java
@@ -20,16 +20,13 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Matrix;
import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
-import android.util.Log;
import java.nio.ByteBuffer;
@@ -53,9 +50,6 @@
private static final int MIN_VISIBLE_ALPHA = 40;
- // Shape detection related constants
- private static final float BOUND_RATIO_MARGIN = .05f;
- private static final float PIXEL_DIFF_PERCENTAGE_THRESHOLD = 0.005f;
private static final float SCALE_NOT_INITIALIZED = 0;
// Ratio of the diameter of an normalized circular icon to the actual icon size.
@@ -64,8 +58,6 @@
private final int mMaxSize;
private final Bitmap mBitmap;
private final Canvas mCanvas;
- private final Paint mPaintMaskShape;
- private final Paint mPaintMaskShapeOutline;
private final byte[] mPixels;
private final Rect mAdaptiveIconBounds;
@@ -75,8 +67,6 @@
private final float[] mLeftBorder;
private final float[] mRightBorder;
private final Rect mBounds;
- private final Path mShapePath;
- private final Matrix mMatrix;
/** package private **/
IconNormalizer(Context context, int iconBitmapSize) {
@@ -90,89 +80,10 @@
mBounds = new Rect();
mAdaptiveIconBounds = new Rect();
- mPaintMaskShape = new Paint();
- mPaintMaskShape.setColor(Color.RED);
- mPaintMaskShape.setStyle(Paint.Style.FILL);
- mPaintMaskShape.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
-
- mPaintMaskShapeOutline = new Paint();
- mPaintMaskShapeOutline.setStrokeWidth(2 * context.getResources().getDisplayMetrics().density);
- mPaintMaskShapeOutline.setStyle(Paint.Style.STROKE);
- mPaintMaskShapeOutline.setColor(Color.BLACK);
- mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
-
- mShapePath = new Path();
- mMatrix = new Matrix();
mAdaptiveIconScale = SCALE_NOT_INITIALIZED;
}
/**
- * Returns if the shape of the icon is same as the path.
- * For this method to work, the shape path bounds should be in [0,1]x[0,1] bounds.
- */
- private boolean isShape(Path maskPath) {
- // Condition1:
- // If width and height of the path not close to a square, then the icon shape is
- // not same as the mask shape.
- float iconRatio = ((float) mBounds.width()) / mBounds.height();
- if (Math.abs(iconRatio - 1) > BOUND_RATIO_MARGIN) {
- if (DEBUG) {
- Log.d(TAG, "Not same as mask shape because width != height. " + iconRatio);
- }
- return false;
- }
-
- // Condition 2:
- // Actual icon (white) and the fitted shape (e.g., circle)(red) XOR operation
- // should generate transparent image, if the actual icon is equivalent to the shape.
-
- // Fit the shape within the icon's bounding box
- mMatrix.reset();
- mMatrix.setScale(mBounds.width(), mBounds.height());
- mMatrix.postTranslate(mBounds.left, mBounds.top);
- maskPath.transform(mMatrix, mShapePath);
-
- // XOR operation
- mCanvas.drawPath(mShapePath, mPaintMaskShape);
-
- // DST_OUT operation around the mask path outline
- mCanvas.drawPath(mShapePath, mPaintMaskShapeOutline);
-
- // Check if the result is almost transparent
- return isTransparentBitmap();
- }
-
- /**
- * Used to determine if certain the bitmap is transparent.
- */
- private boolean isTransparentBitmap() {
- ByteBuffer buffer = ByteBuffer.wrap(mPixels);
- buffer.rewind();
- mBitmap.copyPixelsToBuffer(buffer);
-
- int y = mBounds.top;
- // buffer position
- int index = y * mMaxSize;
- // buffer shift after every row, width of buffer = mMaxSize
- int rowSizeDiff = mMaxSize - mBounds.right;
-
- int sum = 0;
- for (; y < mBounds.bottom; y++) {
- index += mBounds.left;
- for (int x = mBounds.left; x < mBounds.right; x++) {
- if ((mPixels[index] & 0xFF) > MIN_VISIBLE_ALPHA) {
- sum++;
- }
- index++;
- }
- index += rowSizeDiff;
- }
-
- float percentageDiffPixels = ((float) sum) / (mBounds.width() * mBounds.height());
- return percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD;
- }
-
- /**
* Returns the amount by which the {@param d} should be scaled (in both dimensions) so that it
* matches the design guidelines for a launcher icon.
*
@@ -186,8 +97,7 @@
*
* @param outBounds optional rect to receive the fraction distance from each edge.
*/
- public synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds,
- @Nullable Path path, @Nullable boolean[] outMaskShape) {
+ public synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds) {
if (BaseIconFactory.ATLEAST_OREO && d instanceof AdaptiveIconDrawable) {
if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
if (outBounds != null) {
@@ -298,10 +208,6 @@
1 - ((float) mBounds.right) / width,
1 - ((float) mBounds.bottom) / height);
}
-
- if (outMaskShape != null && outMaskShape.length > 0) {
- outMaskShape[0] = isShape(path);
- }
float areaScale = area / (width * height);
// Use sqrt of the final ratio as the images is scaled across both width and height.
float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index 69614a3..c96d35d 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -27,11 +27,11 @@
import com.android.launcher3.AppInfo;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
+import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
@@ -48,13 +48,14 @@
private static final Object sPoolSync = new Object();
private static LauncherIcons sPool;
- private LauncherIcons next;
+ private static int sPoolId = 0;
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static LauncherIcons obtain(Context context) {
+ int poolId;
synchronized (sPoolSync) {
if (sPool != null) {
LauncherIcons m = sPool;
@@ -62,9 +63,33 @@
m.next = null;
return m;
}
+ poolId = sPoolId;
}
+
InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
- return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize);
+ return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize, poolId);
+ }
+
+ public static void clearPool() {
+ synchronized (sPoolSync) {
+ sPool = null;
+ sPoolId++;
+ }
+ }
+
+ private final Context mContext;
+ private final int mFillResIconDpi;
+ private final int mIconBitmapSize;
+ private final int mPoolId;
+
+ private LauncherIcons next;
+
+ private LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
+ super(context, fillResIconDpi, iconBitmapSize);
+ mContext = context.getApplicationContext();
+ mFillResIconDpi = fillResIconDpi;
+ mIconBitmapSize = iconBitmapSize;
+ mPoolId = poolId;
}
/**
@@ -72,6 +97,9 @@
*/
public void recycle() {
synchronized (sPoolSync) {
+ if (sPoolId != mPoolId) {
+ return;
+ }
// Clear any temporary state variables
clear();
@@ -85,17 +113,6 @@
recycle();
}
- private final Context mContext;
- private final int mFillResIconDpi;
- private final int mIconBitmapSize;
-
- private LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize) {
- super(context, fillResIconDpi, iconBitmapSize);
- mContext = context.getApplicationContext();
- mFillResIconDpi = fillResIconDpi;
- mIconBitmapSize = iconBitmapSize;
- }
-
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user,
int iconAppTargetSdk) {
return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false);
diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java
index fcdc088..c9d8e3e 100644
--- a/src/com/android/launcher3/model/BaseModelUpdateTask.java
+++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java
@@ -27,10 +27,10 @@
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.widget.WidgetListRowEntry;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.concurrent.Executor;
/**
@@ -107,13 +107,9 @@
}
public void bindDeepShortcuts(BgDataModel dataModel) {
- final MultiHashMap<ComponentKey, String> shortcutMapCopy = dataModel.deepShortcutMap.clone();
- scheduleCallbackTask(new CallbackTask() {
- @Override
- public void execute(Callbacks callbacks) {
- callbacks.bindDeepShortcutMap(shortcutMapCopy);
- }
- });
+ final HashMap<ComponentKey, Integer> shortcutMapCopy =
+ new HashMap<>(dataModel.deepShortcutMap);
+ scheduleCallbackTask(callbacks -> callbacks.bindDeepShortcutMap(shortcutMapCopy));
}
public void bindUpdatedWidgets(BgDataModel dataModel) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 81eefc4..151d6f4 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -38,7 +38,6 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
-import com.android.launcher3.util.MultiHashMap;
import com.google.protobuf.nano.MessageNano;
import java.io.FileDescriptor;
@@ -97,9 +96,9 @@
public boolean hasShortcutHostPermission;
/**
- * Maps all launcher activities to the id's of their shortcuts (if they have any).
+ * Maps all launcher activities to counts of their shortcuts.
*/
- public final MultiHashMap<ComponentKey, String> deepShortcutMap = new MultiHashMap<>();
+ public final HashMap<ComponentKey, Integer> deepShortcutMap = new HashMap<>();
/**
* Entire list of widgets.
@@ -154,14 +153,11 @@
}
if (args.length > 0 && TextUtils.equals(args[0], "--all")) {
- writer.println(prefix + "shortcuts");
- for (ArrayList<String> map : deepShortcutMap.values()) {
- writer.print(prefix + " ");
- for (String str : map) {
- writer.print(str + ", ");
- }
- writer.println();
+ writer.println(prefix + "shortcut counts ");
+ for (Integer count : deepShortcutMap.values()) {
+ writer.print(count + ", ");
}
+ writer.println();
}
}
@@ -359,9 +355,9 @@
}
/**
- * Clear all the deep shortcuts for the given package, and re-add the new shortcuts.
+ * Clear all the deep shortcut counts for the given package, and re-add the new shortcut counts.
*/
- public synchronized void updateDeepShortcutMap(
+ public synchronized void updateDeepShortcutCounts(
String packageName, UserHandle user, List<ShortcutInfoCompat> shortcuts) {
if (packageName != null) {
Iterator<ComponentKey> keysIter = deepShortcutMap.keySet().iterator();
@@ -381,7 +377,9 @@
if (shouldShowInContainer) {
ComponentKey targetComponent
= new ComponentKey(shortcut.getActivity(), shortcut.getUserHandle());
- deepShortcutMap.addToList(targetComponent, shortcut.getId());
+
+ Integer previousCount = deepShortcutMap.get(targetComponent);
+ deepShortcutMap.put(targetComponent, previousCount == null ? 1 : previousCount + 1);
}
}
}
diff --git a/src/com/android/launcher3/model/LoaderResults.java b/src/com/android/launcher3/model/LoaderResults.java
index 2c15df1..1d18e76 100644
--- a/src/com/android/launcher3/model/LoaderResults.java
+++ b/src/com/android/launcher3/model/LoaderResults.java
@@ -34,7 +34,6 @@
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperIdleLock;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.ViewOnDrawExecutor;
import com.android.launcher3.widget.WidgetListRowEntry;
@@ -42,9 +41,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.Iterator;
-import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -333,20 +331,16 @@
}
public void bindDeepShortcuts() {
- final MultiHashMap<ComponentKey, String> shortcutMapCopy;
+ final HashMap<ComponentKey, Integer> shortcutMapCopy;
synchronized (mBgDataModel) {
- shortcutMapCopy = mBgDataModel.deepShortcutMap.clone();
+ shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
}
- Runnable r = new Runnable() {
- @Override
- public void run() {
- Callbacks callbacks = mCallbacks.get();
- if (callbacks != null) {
- callbacks.bindDeepShortcutMap(shortcutMapCopy);
- }
+ mUiExecutor.execute(() -> {
+ Callbacks callbacks = mCallbacks.get();
+ if (callbacks != null) {
+ callbacks.bindDeepShortcutMap(shortcutMapCopy);
}
- };
- mUiExecutor.execute(r);
+ });
}
public void bindAllApps() {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 405125e..8b3e2c9 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -861,7 +861,7 @@
if (mUserManager.isUserUnlocked(user)) {
List<ShortcutInfoCompat> shortcuts =
mShortcutManager.queryForAllShortcuts(user);
- mBgDataModel.updateDeepShortcutMap(null, user, shortcuts);
+ mBgDataModel.updateDeepShortcutCounts(null, user, shortcuts);
}
}
}
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 47fcd9e..e99fed9 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -116,7 +116,7 @@
if (mUpdateIdMap) {
// Update the deep shortcut map if the list of ids has changed for an activity.
- dataModel.updateDeepShortcutMap(mPackageName, mUser, mShortcuts);
+ dataModel.updateDeepShortcutCounts(mPackageName, mUser, mShortcuts);
bindDeepShortcuts(dataModel);
}
}
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 40c1912..8e7557a 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -117,7 +117,7 @@
}
if (isUserUnlocked) {
- dataModel.updateDeepShortcutMap(
+ dataModel.updateDeepShortcutCounts(
null, mUser, deepShortcutManager.queryForAllShortcuts(mUser));
}
bindDeepShortcuts(dataModel);
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index b9e6a98..12319f7 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -216,13 +216,17 @@
BubbleTextView icon, ItemInfo item, SystemShortcutFactory factory) {
PopupDataProvider popupDataProvider = mLauncher.getPopupDataProvider();
populateAndShow(icon,
- popupDataProvider.getShortcutIdsForItem(item),
+ popupDataProvider.getShortcutCountForItem(item),
popupDataProvider.getNotificationKeysForItem(item),
factory.getEnabledShortcuts(mLauncher, item));
}
+ public ViewGroup getSystemShortcutContainerForTesting() {
+ return mSystemShortcutContainer;
+ }
+
@TargetApi(Build.VERSION_CODES.P)
- protected void populateAndShow(final BubbleTextView originalIcon, final List<String> shortcutIds,
+ protected void populateAndShow(final BubbleTextView originalIcon, int shortcutCount,
final List<NotificationKeyData> notificationKeys, List<SystemShortcut> systemShortcuts) {
mNumNotifications = notificationKeys.size();
mOriginalIcon = originalIcon;
@@ -240,12 +244,12 @@
int viewsToFlip = getChildCount();
mSystemShortcutContainer = this;
- if (!shortcutIds.isEmpty()) {
+ if (shortcutCount > 0) {
if (mNotificationItemView != null) {
mNotificationItemView.addGutter();
}
- for (int i = shortcutIds.size(); i > 0; i--) {
+ for (int i = shortcutCount; i > 0; i--) {
mShortcuts.add(inflateAndAdd(R.layout.deep_shortcut, this));
}
updateHiddenShortcuts();
@@ -284,7 +288,7 @@
final Looper workerLooper = LauncherModel.getWorkerLooper();
new Handler(workerLooper).postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
mLauncher, originalItemInfo, new Handler(Looper.getMainLooper()),
- this, shortcutIds, mShortcuts, notificationKeys));
+ this, mShortcuts, notificationKeys));
}
private String getTitleForAccessibility() {
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 4d5a9c6..3206503 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -29,7 +29,6 @@
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.WidgetListRowEntry;
@@ -52,8 +51,8 @@
private final Launcher mLauncher;
- /** Maps launcher activity components to their list of shortcut ids. */
- private MultiHashMap<ComponentKey, String> mDeepShortcutMap = new MultiHashMap<>();
+ /** Maps launcher activity components to a count of how many shortcuts they have. */
+ private HashMap<ComponentKey, Integer> mDeepShortcutMap = new HashMap<>();
/** Maps packages to their BadgeInfo's . */
private Map<PackageUserKey, BadgeInfo> mPackageUserToBadgeInfos = new HashMap<>();
/** Maps packages to their Widgets */
@@ -146,22 +145,22 @@
}
}
- public void setDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMapCopy) {
+ public void setDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
mDeepShortcutMap = deepShortcutMapCopy;
if (LOGD) Log.d(TAG, "bindDeepShortcutMap: " + mDeepShortcutMap);
}
- public List<String> getShortcutIdsForItem(ItemInfo info) {
+ public int getShortcutCountForItem(ItemInfo info) {
if (!DeepShortcutManager.supportsShortcuts(info)) {
- return Collections.EMPTY_LIST;
+ return 0;
}
ComponentName component = info.getTargetComponent();
if (component == null) {
- return Collections.EMPTY_LIST;
+ return 0;
}
- List<String> ids = mDeepShortcutMap.get(new ComponentKey(component, info.user));
- return ids == null ? Collections.EMPTY_LIST : ids;
+ Integer count = mDeepShortcutMap.get(new ComponentKey(component, info.user));
+ return count == null ? 0 : count;
}
public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 61113b8..2c59202 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -124,7 +124,7 @@
public static Runnable createUpdateRunnable(final Launcher launcher, final ItemInfo originalInfo,
final Handler uiHandler, final PopupContainerWithArrow container,
- final List<String> shortcutIds, final List<DeepShortcutView> shortcutViews,
+ final List<DeepShortcutView> shortcutViews,
final List<NotificationKeyData> notificationKeys) {
final ComponentName activity = originalInfo.getTargetComponent();
final UserHandle user = originalInfo.user;
@@ -141,7 +141,7 @@
}
List<ShortcutInfoCompat> shortcuts = DeepShortcutManager.getInstance(launcher)
- .queryForShortcutsContainer(activity, shortcutIds, user);
+ .queryForShortcutsContainer(activity, user);
String shortcutIdToDeDupe = notificationKeys.isEmpty() ? null
: notificationKeys.get(0).shortcutId;
shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts, shortcutIdToDeDupe);
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index af0d3da..c76fb96 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.app.RemoteAction;
+import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -48,14 +49,20 @@
AbstractFloatingView.closeAllOpenViews(launcher);
try {
- mAction.getActionIntent().send(0,
+ mAction.getActionIntent().send(
+ launcher,
+ 0,
+ new Intent().putExtra(
+ Intent.EXTRA_PACKAGE_NAME,
+ itemInfo.getTargetComponent().getPackageName()),
(pendingIntent, intent, resultCode, resultData, resultExtras) -> {
if (resultData != null && !resultData.isEmpty()) {
Log.e(TAG, "Remote action returned result: " + mAction.getTitle()
+ " : " + resultData);
Toast.makeText(launcher, resultData, Toast.LENGTH_SHORT).show();
}
- }, new Handler(Looper.getMainLooper()));
+ },
+ new Handler(Looper.getMainLooper()));
} catch (PendingIntent.CanceledException e) {
Log.e(TAG, "Remote action canceled: " + mAction.getTitle(), e);
Toast.makeText(launcher, launcher.getString(
diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
new file mode 100644
index 0000000..a9242f9
--- /dev/null
+++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 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.settings;
+
+import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
+import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;
+
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.config.FlagTogglerPrefUi;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+
+import java.util.List;
+import java.util.Set;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceDataStore;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
+/**
+ * Dev-build only UI allowing developers to toggle flag settings and plugins.
+ * See {@link FeatureFlags}.
+ */
+@TargetApi(Build.VERSION_CODES.O)
+public class DeveloperOptionsFragment extends PreferenceFragment {
+
+ private static final String ACTION_PLUGIN_SETTINGS = "com.android.systemui.action.PLUGIN_SETTINGS";
+ private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
+
+ private final BroadcastReceiver mPluginReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ loadPluginPrefs();
+ }
+ };
+
+ private PreferenceScreen mPreferenceScreen;
+
+ private PreferenceCategory mPluginsCategory;
+ private FlagTogglerPrefUi mFlagTogglerPrefUi;
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ getContext().registerReceiver(mPluginReceiver, filter);
+ getContext().registerReceiver(mPluginReceiver,
+ new IntentFilter(Intent.ACTION_USER_UNLOCKED));
+
+ mPreferenceScreen = getPreferenceManager().createPreferenceScreen(getContext());
+ setPreferenceScreen(mPreferenceScreen);
+
+ initFlags();
+ loadPluginPrefs();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ getContext().unregisterReceiver(mPluginReceiver);
+ }
+
+ private PreferenceCategory newCategory(String title) {
+ PreferenceCategory category = new PreferenceCategory(getContext());
+ category.setOrder(Preference.DEFAULT_ORDER);
+ category.setTitle(title);
+ mPreferenceScreen.addPreference(category);
+ return category;
+ }
+
+ private void initFlags() {
+ if (!FeatureFlags.showFlagTogglerUi(getContext())) {
+ return;
+ }
+
+ mFlagTogglerPrefUi = new FlagTogglerPrefUi(this);
+ mFlagTogglerPrefUi.applyTo(newCategory("Feature flags"));
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (mFlagTogglerPrefUi != null) {
+ mFlagTogglerPrefUi.onCreateOptionsMenu(menu);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mFlagTogglerPrefUi != null) {
+ mFlagTogglerPrefUi.onOptionsItemSelected(item);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onStop() {
+ if (mFlagTogglerPrefUi != null) {
+ mFlagTogglerPrefUi.onStop();
+ }
+ super.onStop();
+ }
+
+ private void loadPluginPrefs() {
+ if (mPluginsCategory != null) {
+ mPreferenceScreen.removePreference(mPluginsCategory);
+ }
+ if (!PluginManagerWrapper.hasPlugins(getActivity())) {
+ mPluginsCategory = null;
+ return;
+ }
+ mPluginsCategory = newCategory("Plugins");
+
+ PluginManagerWrapper manager = PluginManagerWrapper.INSTANCE.get(getContext());
+ Context prefContext = getContext();
+ PackageManager pm = getContext().getPackageManager();
+
+ Set<String> pluginActions = manager.getPluginActions();
+ ArrayMap<String, ArraySet<String>> plugins = new ArrayMap<>();
+ for (String action : pluginActions) {
+ String name = toName(action);
+ List<ResolveInfo> result = pm.queryIntentServices(
+ new Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS);
+ for (ResolveInfo info : result) {
+ String packageName = info.serviceInfo.packageName;
+ if (!plugins.containsKey(packageName)) {
+ plugins.put(packageName, new ArraySet<>());
+ }
+ plugins.get(packageName).add(name);
+ }
+ }
+
+ List<PackageInfo> apps = pm.getPackagesHoldingPermissions(new String[]{PLUGIN_PERMISSION},
+ PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES);
+ PreferenceDataStore enabled = manager.getPluginEnabler();
+ apps.forEach(app -> {
+ if (!plugins.containsKey(app.packageName)) return;
+ SwitchPreference pref = new PluginPreference(prefContext, app, enabled);
+ pref.setSummary("Plugins: " + toString(plugins.get(app.packageName)));
+ mPluginsCategory.addPreference(pref);
+ });
+ }
+
+ private String toString(ArraySet<String> plugins) {
+ StringBuilder b = new StringBuilder();
+ for (String string : plugins) {
+ if (b.length() != 0) {
+ b.append(", ");
+ }
+ b.append(string);
+ }
+ return b.toString();
+ }
+
+ private String toName(String action) {
+ String str = action.replace("com.android.systemui.action.PLUGIN_", "");
+ StringBuilder b = new StringBuilder();
+ for (String s : str.split("_")) {
+ if (b.length() != 0) {
+ b.append(' ');
+ }
+ b.append(s.substring(0, 1));
+ b.append(s.substring(1).toLowerCase());
+ }
+ return b.toString();
+ }
+
+ private static class PluginPreference extends SwitchPreference {
+ private final boolean mHasSettings;
+ private final PackageInfo mInfo;
+ private final PreferenceDataStore mPluginEnabler;
+
+ public PluginPreference(Context prefContext, PackageInfo info,
+ PreferenceDataStore pluginEnabler) {
+ super(prefContext);
+ PackageManager pm = prefContext.getPackageManager();
+ mHasSettings = pm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS)
+ .setPackage(info.packageName), 0) != null;
+ mInfo = info;
+ mPluginEnabler = pluginEnabler;
+ setTitle(info.applicationInfo.loadLabel(pm));
+ setChecked(isPluginEnabled());
+ setWidgetLayoutResource(R.layout.switch_preference_with_settings);
+ }
+
+ private boolean isEnabled(ComponentName cn) {
+ return mPluginEnabler.getBoolean(pluginEnabledKey(cn), true);
+
+ }
+
+ private boolean isPluginEnabled() {
+ for (int i = 0; i < mInfo.services.length; i++) {
+ ComponentName componentName = new ComponentName(mInfo.packageName,
+ mInfo.services[i].name);
+ if (!isEnabled(componentName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean isEnabled) {
+ boolean shouldSendBroadcast = false;
+ for (int i = 0; i < mInfo.services.length; i++) {
+ ComponentName componentName = new ComponentName(mInfo.packageName,
+ mInfo.services[i].name);
+
+ if (isEnabled(componentName) != isEnabled) {
+ mPluginEnabler.putBoolean(pluginEnabledKey(componentName), isEnabled);
+ shouldSendBroadcast = true;
+ }
+ }
+ if (shouldSendBroadcast) {
+ final String pkg = mInfo.packageName;
+ final Intent intent = new Intent(PLUGIN_CHANGED,
+ pkg != null ? Uri.fromParts("package", pkg, null) : null);
+ getContext().sendBroadcast(intent);
+ }
+ setChecked(isEnabled);
+ return true;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ holder.findViewById(R.id.settings).setVisibility(mHasSettings ? View.VISIBLE
+ : View.GONE);
+ holder.findViewById(R.id.divider).setVisibility(mHasSettings ? View.VISIBLE
+ : View.GONE);
+ holder.findViewById(R.id.settings).setOnClickListener(v -> {
+ ResolveInfo result = v.getContext().getPackageManager().resolveActivity(
+ new Intent(ACTION_PLUGIN_SETTINGS).setPackage(
+ mInfo.packageName), 0);
+ if (result != null) {
+ v.getContext().startActivity(new Intent().setComponent(
+ new ComponentName(result.activityInfo.packageName,
+ result.activityInfo.name)));
+ }
+ });
+ holder.itemView.setOnLongClickListener(v -> {
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.fromParts("package", mInfo.packageName, null));
+ getContext().startActivity(intent);
+ return true;
+ });
+ }
+ }
+}
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index 66420d0..7c158d9 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -24,17 +24,16 @@
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
-import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
-import android.util.Log;
import com.android.launcher3.LauncherFiles;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.IconShapeOverride;
+import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SecureSettingsObserver;
import androidx.preference.ListPreference;
@@ -52,6 +51,7 @@
public class SettingsActivity extends Activity
implements OnPreferenceStartFragmentCallback, OnPreferenceStartScreenCallback {
+ private static final String DEVELOPER_OPTIONS_KEY = "pref_developer_options";
private static final String FLAGS_PREFERENCE_KEY = "flag_toggler";
private static final String ICON_BADGING_PREFERENCE_KEY = "pref_icon_badging";
@@ -203,7 +203,12 @@
case FLAGS_PREFERENCE_KEY:
// Only show flag toggler UI if this build variant implements that.
- return FeatureFlags.showFlagTogglerUi();
+ return FeatureFlags.showFlagTogglerUi(getContext());
+
+ case DEVELOPER_OPTIONS_KEY:
+ // Show if plugins are enabled or flag UI is enabled.
+ return FeatureFlags.showFlagTogglerUi(getContext()) ||
+ PluginManagerWrapper.hasPlugins(getContext());
}
return true;
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
index 24e2e2f..e70aac6 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java
@@ -94,10 +94,11 @@
* Gets all the manifest and dynamic shortcuts associated with the given package and user,
* to be displayed in the shortcuts container on long press.
*/
+ @TargetApi(25)
public List<ShortcutInfoCompat> queryForShortcutsContainer(ComponentName activity,
- List<String> ids, UserHandle user) {
+ UserHandle user) {
return query(ShortcutQuery.FLAG_MATCH_MANIFEST | ShortcutQuery.FLAG_MATCH_DYNAMIC,
- activity.getPackageName(), activity, ids, user);
+ activity.getPackageName(), activity, null, user);
}
/**
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutTextView.java b/src/com/android/launcher3/shortcuts/DeepShortcutTextView.java
index c809f27..2daa2fe 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutTextView.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutTextView.java
@@ -18,8 +18,10 @@
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Toast;
@@ -38,6 +40,10 @@
private Toast mInstructionToast;
+ private boolean mShowLoadingState;
+ private Drawable mLoadingStatePlaceholder;
+ private final Rect mLoadingStateBounds = new Rect();
+
public DeepShortcutTextView(Context context) {
this(context, null, 0);
}
@@ -53,6 +59,7 @@
mDragHandleWidth = resources.getDimensionPixelSize(R.dimen.popup_padding_end)
+ resources.getDimensionPixelSize(R.dimen.deep_shortcut_drag_handle_size)
+ resources.getDimensionPixelSize(R.dimen.deep_shortcut_drawable_padding) / 2;
+ showLoadingState(true);
}
@Override
@@ -63,6 +70,25 @@
if (!Utilities.isRtl(getResources())) {
mDragHandleBounds.offset(getMeasuredWidth() - mDragHandleBounds.width(), 0);
}
+
+ setLoadingBounds();
+ }
+
+ private void setLoadingBounds() {
+ if (mLoadingStatePlaceholder == null) {
+ return;
+ }
+ mLoadingStateBounds.set(
+ 0,
+ 0,
+ getMeasuredWidth() - mDragHandleWidth - getPaddingStart(),
+ mLoadingStatePlaceholder.getIntrinsicHeight());
+ mLoadingStateBounds.offset(
+ Utilities.isRtl(getResources()) ? mDragHandleWidth : getPaddingStart(),
+ (int) ((getMeasuredHeight() - mLoadingStatePlaceholder.getIntrinsicHeight())
+ / 2.0f)
+ );
+ mLoadingStatePlaceholder.setBounds(mLoadingStateBounds);
}
@Override
@@ -71,6 +97,15 @@
}
@Override
+ public void setText(CharSequence text, BufferType type) {
+ super.setText(text, type);
+
+ if (!TextUtils.isEmpty(text)) {
+ showLoadingState(false);
+ }
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// Show toast if user touches the drag handle (long clicks still start the drag).
@@ -88,6 +123,34 @@
return super.performClick();
}
+ @Override
+ public void onDraw(Canvas canvas) {
+ if (!mShowLoadingState) {
+ super.onDraw(canvas);
+ return;
+ }
+
+ mLoadingStatePlaceholder.draw(canvas);
+ }
+
+ private void showLoadingState(boolean loading) {
+ if (loading == mShowLoadingState) {
+ return;
+ }
+
+ mShowLoadingState = loading;
+
+ if (loading) {
+ mLoadingStatePlaceholder = getContext().getDrawable(
+ R.drawable.deep_shortcuts_text_placeholder);
+ setLoadingBounds();
+ } else {
+ mLoadingStatePlaceholder = null;
+ }
+
+ invalidate();
+ }
+
private void showToast() {
if (mInstructionToast != null) {
mInstructionToast.cancel();
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutView.java b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
index c856cdb..7b93ba2 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutView.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
@@ -40,8 +40,6 @@
private static final Point sTempPoint = new Point();
- private final Rect mPillRect;
-
private BubbleTextView mBubbleText;
private View mIconView;
private View mDivider;
@@ -59,8 +57,6 @@
public DeepShortcutView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
-
- mPillRect = new Rect();
}
@Override
@@ -98,12 +94,6 @@
return sTempPoint;
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mPillRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
- }
-
/** package private **/
public void applyShortcutInfo(ShortcutInfo info, ShortcutInfoCompat detail,
PopupContainerWithArrow container) {
diff --git a/src/com/android/launcher3/util/ConfigMonitor.java b/src/com/android/launcher3/util/ConfigMonitor.java
index 5dd0d08..717acdc 100644
--- a/src/com/android/launcher3/util/ConfigMonitor.java
+++ b/src/com/android/launcher3/util/ConfigMonitor.java
@@ -29,9 +29,12 @@
import android.view.Display;
import android.view.WindowManager;
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.Utilities.Consumer;
+
/**
* {@link BroadcastReceiver} which watches configuration changes and
- * restarts the process in case changes which affect the device profile occur.
+ * notifies the callback in case changes which affect the device profile occur.
*/
public class ConfigMonitor extends BroadcastReceiver implements DisplayListener {
@@ -48,7 +51,9 @@
private final Point mRealSize;
private final Point mSmallestSize, mLargestSize;
- public ConfigMonitor(Context context) {
+ private Consumer<Context> mCallback;
+
+ public ConfigMonitor(Context context, Consumer<Context> callback) {
mContext = context;
Configuration config = context.getResources().getConfiguration();
@@ -64,6 +69,12 @@
mSmallestSize = new Point();
mLargestSize = new Point();
display.getCurrentSizeRange(mSmallestSize, mLargestSize);
+
+ mCallback = callback;
+
+ mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
+ mContext.getSystemService(DisplayManager.class)
+ .registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
}
@Override
@@ -71,16 +82,10 @@
Configuration config = context.getResources().getConfiguration();
if (mFontScale != config.fontScale || mDensity != config.densityDpi) {
Log.d(TAG, "Configuration changed");
- killProcess();
+ notifyChange();
}
}
- public void register() {
- mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
- mContext.getSystemService(DisplayManager.class)
- .registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
- }
-
@Override
public void onDisplayAdded(int displayId) { }
@@ -97,7 +102,7 @@
if (!mRealSize.equals(mTmpPoint1) && !mRealSize.equals(mTmpPoint1.y, mTmpPoint1.x)) {
Log.d(TAG, String.format("Display size changed from %s to %s", mRealSize, mTmpPoint1));
- killProcess();
+ notifyChange();
return;
}
@@ -105,22 +110,28 @@
if (!mSmallestSize.equals(mTmpPoint1) || !mLargestSize.equals(mTmpPoint2)) {
Log.d(TAG, String.format("Available size changed from [%s, %s] to [%s, %s]",
mSmallestSize, mLargestSize, mTmpPoint1, mTmpPoint2));
- killProcess();
+ notifyChange();
}
}
- private void killProcess() {
- Log.d(TAG, "restarting launcher");
- try {
- mContext.unregisterReceiver(this);
- mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
- } catch (Exception e) {
- // We are going to die anyway, ignore any error die to race condition in registering.
+ private synchronized void notifyChange() {
+ if (mCallback != null) {
+ Consumer<Context> callback = mCallback;
+ mCallback = null;
+ new MainThreadExecutor().execute(() -> callback.accept(mContext));
}
- android.os.Process.killProcess(android.os.Process.myPid());
}
private Display getDefaultDisplay(Context context) {
return context.getSystemService(WindowManager.class).getDefaultDisplay();
}
+
+ public void unregister() {
+ try {
+ mContext.unregisterReceiver(this);
+ mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to unregister config monitor", e);
+ }
+ }
}
diff --git a/src/com/android/launcher3/util/SQLiteCacheHelper.java b/src/com/android/launcher3/util/SQLiteCacheHelper.java
index 44c1762..3faf070 100644
--- a/src/com/android/launcher3/util/SQLiteCacheHelper.java
+++ b/src/com/android/launcher3/util/SQLiteCacheHelper.java
@@ -87,6 +87,10 @@
mOpenHelper.clearDB(mOpenHelper.getWritableDatabase());
}
+ public void close() {
+ mOpenHelper.close();
+ }
+
protected abstract void onCreateTable(SQLiteDatabase db);
/**
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 3e58ea6..c540b59 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -136,7 +136,7 @@
}
@VisibleForTesting
- public static OptionsPopupView getOptionsPopup(Launcher launcher) {
+ public static ArrowPopup getOptionsPopup(Launcher launcher) {
return launcher.findViewById(R.id.deep_shortcuts_container);
}
diff --git a/src_plugins/com/android/systemui/plugins/FirstScreenWidget.java b/src_plugins/com/android/systemui/plugins/FirstScreenWidget.java
new file mode 100644
index 0000000..8d7dd4b
--- /dev/null
+++ b/src_plugins/com/android/systemui/plugins/FirstScreenWidget.java
@@ -0,0 +1,15 @@
+package com.android.systemui.plugins;
+
+import android.view.ViewGroup;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Implement this interface to wrap the widget on the first home screen, e.g. to add new content.
+ */
+@ProvidesInterface(action = FirstScreenWidget.ACTION, version = FirstScreenWidget.VERSION)
+public interface FirstScreenWidget extends Plugin {
+ String ACTION = "com.android.systemui.action.PLUGIN_FIRST_SCREEN_WIDGET";
+ int VERSION = 1;
+
+ void onWidgetUpdated(ViewGroup widgetView);
+}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/src_ui_overrides/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
index 31dbb34..e1a35c9 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
@@ -14,17 +14,26 @@
package com.android.launcher3.uioverrides.plugins;
+import android.content.ComponentName;
import android.content.Context;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
+import java.util.Collections;
+import java.util.Set;
+
+import androidx.preference.PreferenceDataStore;
+
public class PluginManagerWrapper {
public static final MainThreadInitializedObject<PluginManagerWrapper> INSTANCE =
new MainThreadInitializedObject<>(PluginManagerWrapper::new);
+ private static final String PREFIX_PLUGIN_ENABLED = "PLUGIN_ENABLED_";
+ public static final String PLUGIN_CHANGED = "com.android.systemui.action.PLUGIN_CHANGED";
+
private PluginManagerWrapper(Context c) {
}
@@ -35,6 +44,21 @@
boolean allowMultiple) {
}
- public void removePluginListener(PluginListener<? extends Plugin> listener) {
+ public void removePluginListener(PluginListener<? extends Plugin> listener) { }
+
+ public Set<String> getPluginActions() {
+ return Collections.emptySet();
+ }
+
+ public PreferenceDataStore getPluginEnabler() {
+ return new PreferenceDataStore() { };
+ }
+
+ public static String pluginEnabledKey(ComponentName cn) {
+ return PREFIX_PLUGIN_ENABLED + cn.flattenToString();
+ }
+
+ public static boolean hasPlugins(Context context) {
+ return false;
}
}
diff --git a/tests/Android.mk b/tests/Android.mk
index d808873..a787537 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,7 +21,8 @@
include $(CLEAR_VARS)
LOCAL_STATIC_JAVA_LIBRARIES := \
androidx.annotation_annotation \
- androidx-test \
+ androidx.test.runner \
+ androidx.test.rules \
androidx.test.uiautomator_uiautomator \
libSharedSystemUI
@@ -42,7 +43,8 @@
LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx-test \
+ androidx.test.runner \
+ androidx.test.rules \
androidx.test.uiautomator_uiautomator \
mockito-target-minus-junit4
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index c878699..532d3e8 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -56,6 +56,7 @@
import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;
+import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -168,6 +169,16 @@
}
}
+ protected void clearLauncherData() throws IOException {
+ if (TestHelpers.isInLauncherProcess()) {
+ LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
+ LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
+ resetLoaderState();
+ } else {
+ mDevice.executeShellCommand("pm clear " + mDevice.getLauncherPackageName());
+ }
+ }
+
/**
* Scrolls the {@param container} until it finds an object matching {@param condition}.
* @return the matching object.
@@ -261,6 +272,10 @@
launcher -> launcher.getStateManager().getState() == state);
}
+ protected void waitForResumed(String message) {
+ waitForLauncherCondition(message, launcher -> launcher.hasBeenResumed());
+ }
+
// Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
// flakiness.
protected void waitForLauncherCondition(String message, Function<Launcher, Boolean> condition) {
diff --git a/tests/src/com/android/launcher3/ui/TestViewHelpers.java b/tests/src/com/android/launcher3/ui/TestViewHelpers.java
index 5244386..6fa28f1 100644
--- a/tests/src/com/android/launcher3/ui/TestViewHelpers.java
+++ b/tests/src/com/android/launcher3/ui/TestViewHelpers.java
@@ -28,6 +28,8 @@
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
@@ -42,6 +44,7 @@
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
import java.util.concurrent.Callable;
+import java.util.function.Function;
public class TestViewHelpers {
private static final String TAG = "TestViewHelpers";
@@ -183,4 +186,12 @@
AbstractLauncherUiTest.DEFAULT_UI_TIMEOUT).click();
return findViewById(R.id.widgets_list_view);
}
+
+ public static View findChildView(ViewGroup parent, Function<View, Boolean> condition) {
+ for (int i = 0; i < parent.getChildCount(); ++i) {
+ final View child = parent.getChildAt(i);
+ if (condition.apply(child)) return child;
+ }
+ return null;
+ }
}