diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml index ed90c85bc5..5cbe55638e 100644 --- a/quickstep/res/values-af/strings.xml +++ b/quickstep/res/values-af/strings.xml @@ -22,6 +22,8 @@ "Speld vas" "Vormvry" "Rekenaar" + + "Werkskerm" "Geen onlangse items nie" "Programgebruikinstellings" @@ -154,4 +156,6 @@ "Maak almal toe" "vou %1$s uit" "vou %1$s in" + + diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml index 0848ddd48e..ce12f9da4a 100644 --- a/quickstep/res/values-am/strings.xml +++ b/quickstep/res/values-am/strings.xml @@ -22,6 +22,8 @@ "ሰካ" "ነፃ ቅጽ" "ዴስክቶፕ" + + "ዴስክቶፕ" "ምንም የቅርብ ጊዜ ንጥሎች የሉም" "የመተግበሪያ አጠቃቀም ቅንብሮች" @@ -154,4 +156,6 @@ "ሁሉንም አሰናብት" "%1$sን ዘርጋ" "%1$sን ሰብስብ" + + diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 501654f0eb..0f3a854c14 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -22,6 +22,8 @@ "تثبيت" "شكل مجاني" "الكمبيوتر المكتبي" + + "كمبيوتر مكتبي" "ما مِن عناصر تم استخدامها مؤخرًا" "إعدادات استخدام التطبيق" @@ -154,4 +156,6 @@ "إغلاق الكل" "توسيع %1$s" "تصغير %1$s" + + diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml index 1dbab02d17..1d536e840d 100644 --- a/quickstep/res/values-as/strings.xml +++ b/quickstep/res/values-as/strings.xml @@ -22,6 +22,8 @@ "পিন" "Freeform" "ডেস্কটপ" + + "ডেস্কটপ" "কোনো শেহতীয়া বস্তু নাই" "এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং" @@ -154,4 +156,6 @@ "সকলো অগ্ৰাহ্য কৰক" "%1$s বিস্তাৰ কৰক" "%1$s সংকোচন কৰক" + + diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml index e211463c0c..2e6337a71f 100644 --- a/quickstep/res/values-az/strings.xml +++ b/quickstep/res/values-az/strings.xml @@ -22,6 +22,8 @@ "Sancın" "Sərbəst rejim" "Masaüstü" + + "Masaüstü" "Son elementlər yoxdur" "Tətbiq istifadə ayarları" @@ -154,4 +156,6 @@ "Hamısını kənarlaşdırın" "genişləndirin: %1$s" "yığcamlaşdırın: %1$s" + + diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml index aa16f3c353..93a8d48283 100644 --- a/quickstep/res/values-b+sr+Latn/strings.xml +++ b/quickstep/res/values-b+sr+Latn/strings.xml @@ -22,6 +22,8 @@ "Zakači" "Slobodni oblik" "Računar" + + "Računari" "Nema nedavnih stavki" "Podešavanja korišćenja aplikacije" @@ -154,4 +156,6 @@ "Odbaci sve" "proširite oblačić %1$s" "skupite oblačić %1$s" + + diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml index 4dcfe62c1c..3f5a6178a3 100644 --- a/quickstep/res/values-be/strings.xml +++ b/quickstep/res/values-be/strings.xml @@ -22,6 +22,8 @@ "Замацаваць" "Адвольная форма" "Працоўны стол" + + "Працоўны стол" "Няма новых элементаў" "Налады выкарыстання праграмы" @@ -154,4 +156,6 @@ "Закрыць усе" "%1$s: разгарнуць" "%1$s: згарнуць" + + diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index 8ceef779a8..adabb31cbb 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -22,6 +22,8 @@ "Фиксиране" "Свободна форма" "За компютър" + + "Настолен компютър" "Няма скорошни елементи" "Настройки за използването на приложенията" @@ -154,4 +156,6 @@ "Отхвърляне на всички" "разгъване на %1$s" "свиване на %1$s" + + diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml index 14b86de345..7d93d9b323 100644 --- a/quickstep/res/values-bn/strings.xml +++ b/quickstep/res/values-bn/strings.xml @@ -22,6 +22,8 @@ "পিন করুন" "ফ্রি-ফর্ম" "ডেস্কটপ" + + "ডেস্কটপ" "কোনও সাম্প্রতিক আইটেম নেই" "অ্যাপ ব্যবহারের সেটিংস" @@ -154,4 +156,6 @@ "সব বাতিল করুন" "%1$s বড় করুন" "%1$s আড়াল করুন" + + diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml index b60436cb10..2ac0ab1336 100644 --- a/quickstep/res/values-bs/strings.xml +++ b/quickstep/res/values-bs/strings.xml @@ -22,6 +22,8 @@ "Zakači" "Slobodan oblik" "Radna površina" + + "Radna površina" "Nema nedavnih stavki" "Postavke korištenja aplikacije" @@ -154,4 +156,6 @@ "Odbacivanje svega" "proširivanje oblačića %1$s" "sužavanje oblačića %1$s" + + diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index 4447c019a1..1c27b08ddc 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -22,6 +22,8 @@ "Fixa" "Format lliure" "Escriptori" + + "Escriptori" "No hi ha cap element recent" "Configuració d\'ús d\'aplicacions" @@ -154,4 +156,6 @@ "Ignora-ho tot" "desplega %1$s" "replega %1$s" + + diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index 711cbfa788..2f8d4b0b7b 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -22,6 +22,8 @@ "Připnout" "Neomezený režim" "Počítač" + + "Počítač" "Žádné položky z nedávné doby" "Nastavení využití aplikací" @@ -154,4 +156,6 @@ "Zavřít vše" "rozbalit %1$s" "sbalit %1$s" + + diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml index 2a5b34d838..4684af2df4 100644 --- a/quickstep/res/values-da/strings.xml +++ b/quickstep/res/values-da/strings.xml @@ -22,6 +22,8 @@ "Fastgør" "Frit format" "Computertilstand" + + "Computer" "Ingen nye elementer" "Indstillinger for appforbrug" @@ -154,4 +156,6 @@ "Afvis alle" "udvid %1$s" "skjul %1$s" + + diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index 478a7a39ee..155abb4727 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -22,6 +22,8 @@ "Fixieren" "Freeform-Modus" "Desktopmodus" + + "Desktopmodus" "Keine kürzlich verwendeten Elemente" "Einstellungen zur App-Nutzung" @@ -154,4 +156,6 @@ "Alle schließen" "„%1$s“ maximieren" "„%1$s“ minimieren" + + diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml index e47b423bfb..39e891637d 100644 --- a/quickstep/res/values-el/strings.xml +++ b/quickstep/res/values-el/strings.xml @@ -22,6 +22,8 @@ "Καρφίτσωμα" "Ελεύθερη μορφή" "Υπολογιστής" + + "Υπολογιστής" "Δεν υπάρχουν πρόσφατα στοιχεία" "Ρυθμίσεις χρήσης εφαρμογής" @@ -154,4 +156,6 @@ "Παράβλεψη όλων" "ανάπτυξη %1$s" "σύμπτυξη %1$s" + + diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml index 04b04dde75..bc73bfe488 100644 --- a/quickstep/res/values-en-rAU/strings.xml +++ b/quickstep/res/values-en-rAU/strings.xml @@ -22,6 +22,8 @@ "Pin" "Freeform" "Desktop" + + "Desktop" "No recent items" "App usage settings" @@ -154,4 +156,6 @@ "Dismiss all" "expand %1$s" "collapse %1$s" + + diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml index e0787ca316..da4effbb2c 100644 --- a/quickstep/res/values-en-rCA/strings.xml +++ b/quickstep/res/values-en-rCA/strings.xml @@ -22,6 +22,7 @@ "Pin" "Freeform" "Desktop" + "Move to external display" "Desktop" "No recent items" "App usage settings" @@ -154,4 +155,5 @@ "Dismiss all" "expand %1$s" "collapse %1$s" + "Circle to Search" diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml index 04b04dde75..bc73bfe488 100644 --- a/quickstep/res/values-en-rGB/strings.xml +++ b/quickstep/res/values-en-rGB/strings.xml @@ -22,6 +22,8 @@ "Pin" "Freeform" "Desktop" + + "Desktop" "No recent items" "App usage settings" @@ -154,4 +156,6 @@ "Dismiss all" "expand %1$s" "collapse %1$s" + + diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml index 04b04dde75..bc73bfe488 100644 --- a/quickstep/res/values-en-rIN/strings.xml +++ b/quickstep/res/values-en-rIN/strings.xml @@ -22,6 +22,8 @@ "Pin" "Freeform" "Desktop" + + "Desktop" "No recent items" "App usage settings" @@ -154,4 +156,6 @@ "Dismiss all" "expand %1$s" "collapse %1$s" + + diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index dd8de5fad4..25bbba27fa 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -22,6 +22,8 @@ "Fijar" "Formato libre" "Escritorio" + + "Computadoras" "No hay elementos recientes" "Configuración de uso de la app" @@ -154,4 +156,6 @@ "Descartar todo" "expandir %1$s" "contraer %1$s" + + diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index d8bbc55815..a4d7a8b1dc 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -22,6 +22,8 @@ "Fijar" "Formato libre" "Escritorio" + + "Ordenador" "No hay nada reciente" "Ajustes de uso de la aplicación" @@ -154,4 +156,6 @@ "Cerrar todo" "desplegar %1$s" "contraer %1$s" + + diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml index 114f3a187e..63d4d2fcfc 100644 --- a/quickstep/res/values-et/strings.xml +++ b/quickstep/res/values-et/strings.xml @@ -22,6 +22,8 @@ "Kinnita" "Vabavorm" "Lauaarvuti režiim" + + "Töölaud" "Hiljutisi üksusi pole" "Rakenduse kasutuse seaded" @@ -154,4 +156,6 @@ "Loobu kõigist" "Toiminguriba %1$s laiendamine" "Toiminguriba %1$s ahendamine" + + diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml index 45fa5790d0..3c0698c158 100644 --- a/quickstep/res/values-eu/strings.xml +++ b/quickstep/res/values-eu/strings.xml @@ -22,6 +22,8 @@ "Ainguratu" "Modu librea" "Ordenagailua" + + "Mahaigaina" "Ez dago azkenaldi honetako ezer" "Aplikazioen erabileraren ezarpenak" @@ -154,4 +156,6 @@ "Baztertu guztiak" "zabaldu %1$s" "tolestu %1$s" + + diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml index d3e38000d6..8d5d15e7e6 100644 --- a/quickstep/res/values-fa/strings.xml +++ b/quickstep/res/values-fa/strings.xml @@ -22,6 +22,8 @@ "پین" "Freeform" "حالت رایانه" + + "رایانه" "چیز جدیدی اینجا نیست" "تنظیمات استفاده از برنامه" @@ -154,4 +156,6 @@ "رد کردن همه" "ازهم باز کردن %1$s" "جمع کردن %1$s" + + diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml index 54a0c23e34..10ea9ee215 100644 --- a/quickstep/res/values-fi/strings.xml +++ b/quickstep/res/values-fi/strings.xml @@ -22,6 +22,8 @@ "Kiinnitä" "Vapaamuotoinen" "Tietokone" + + "Tietokone" "Ei viimeaikaisia kohteita" "Sovelluksen käyttöasetukset" @@ -154,4 +156,6 @@ "Hylkää kaikki" "laajenna %1$s" "tiivistä %1$s" + + diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index 591c7b7f65..b624b4f73b 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -22,6 +22,8 @@ "Épingler" "Forme libre" "Ordinateur de bureau" + + "Ordinateur de bureau" "Aucun élément récent" "Paramètres d\'utilisation de l\'appli" @@ -154,4 +156,6 @@ "Tout ignorer" "Développer %1$s" "Réduire %1$s" + + diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml index 6371f30a38..3f61d65f35 100644 --- a/quickstep/res/values-fr/strings.xml +++ b/quickstep/res/values-fr/strings.xml @@ -22,6 +22,8 @@ "Épingler" "Format libre" "Ordinateur" + + "Ordinateur" "Aucun élément récent" "Paramètres de consommation de l\'application" @@ -154,4 +156,6 @@ "Tout fermer" "Développer %1$s" "Réduire %1$s" + + diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml index 060328405b..d9d06a1a8a 100644 --- a/quickstep/res/values-gl/strings.xml +++ b/quickstep/res/values-gl/strings.xml @@ -22,6 +22,8 @@ "Fixar" "Forma libre" "Escritorio" + + "Ordenador" "Non hai elementos recentes" "Configuración do uso de aplicacións" @@ -154,4 +156,6 @@ "Pechar todo" "despregar %1$s" "contraer %1$s" + + diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml index 4a8e9f9642..7716d4d3ef 100644 --- a/quickstep/res/values-gu/strings.xml +++ b/quickstep/res/values-gu/strings.xml @@ -22,6 +22,8 @@ "પિન કરો" "ફ્રિફોર્મ" "ડેસ્કટૉપ" + + "ડેસ્કટૉપ" "તાજેતરની કોઈ આઇટમ નથી" "ઍપ વપરાશનું સેટિંગ" @@ -154,4 +156,6 @@ "તમામ છોડી દો" "%1$s મોટો કરો" "%1$s નાનો કરો" + + diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 2cec388ac7..02e23ec579 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -22,6 +22,8 @@ "पिन करें" "फ़्रीफ़ॉर्म" "डेस्कटॉप" + + "डेस्कटॉप" "हाल ही का कोई आइटम नहीं है" "ऐप्लिकेशन इस्तेमाल की सेटिंग" @@ -154,4 +156,6 @@ "सभी खारिज करें" "%1$s को बड़ा करें" "%1$s को छोटा करें" + + diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index ed52e90b48..a742c01bdc 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -22,6 +22,8 @@ "Prikvači" "Slobodni oblik" "Računalo" + + "Radna površina" "Nema nedavnih stavki" "Postavke upotrebe aplikacija" @@ -154,4 +156,6 @@ "Odbaci sve" "proširite oblačić %1$s" "sažmite oblačić %1$s" + + diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml index 27db3e0b3b..439d6ed55a 100644 --- a/quickstep/res/values-hu/strings.xml +++ b/quickstep/res/values-hu/strings.xml @@ -22,6 +22,8 @@ "Kitűzés" "Szabad forma" "Asztali" + + "Asztali" "Nincsenek mostanában használt elemek" "Alkalmazáshasználati beállítások" @@ -154,4 +156,6 @@ "Az összes elvetése" "%1$s kibontása" "%1$s összecsukása" + + diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml index 9a2cb2ee3e..87681c0ea1 100644 --- a/quickstep/res/values-hy/strings.xml +++ b/quickstep/res/values-hy/strings.xml @@ -22,6 +22,8 @@ "Ամրացնել" "Կամայական ձև" "Համակարգիչ" + + "Համակարգիչ" "Այստեղ դեռ ոչինչ չկա" "Հավելվածի օգտագործման կարգավորումներ" @@ -154,4 +156,6 @@ "Փակել բոլորը" "%1$s. ծավալել" "%1$s. ծալել" + + diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml index 5ddfb7e716..119ed6b8cf 100644 --- a/quickstep/res/values-in/strings.xml +++ b/quickstep/res/values-in/strings.xml @@ -22,6 +22,8 @@ "Sematkan" "Format bebas" "Desktop" + + "Desktop" "Tidak ada item yang baru dibuka" "Setelan penggunaan aplikasi" @@ -154,4 +156,6 @@ "Tutup semua" "luaskan %1$s" "ciutkan %1$s" + + diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index 3aec0ceb32..68f46565e6 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -22,6 +22,8 @@ "Festa" "Frjálst snið" "Tölva" + + "Tölva" "Engin nýleg atriði" "Notkunarstillingar forrits" @@ -154,4 +156,6 @@ "Hunsa allt" "stækka %1$s" "minnka %1$s" + + diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index b9e6f623c6..0498c4ea41 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -22,6 +22,8 @@ "Blocca su schermo" "Forma libera" "Desktop" + + "Desktop" "Nessun elemento recente" "Impostazioni di utilizzo delle app" @@ -154,4 +156,6 @@ "Ignora tutte" "espandi %1$s" "comprimi %1$s" + + diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml index 2a016fa962..ad525609aa 100644 --- a/quickstep/res/values-iw/strings.xml +++ b/quickstep/res/values-iw/strings.xml @@ -22,6 +22,8 @@ "הצמדה" "מצב חופשי" "במחשב" + + "מחשב" "אין פריטים אחרונים" "הגדרות שימוש באפליקציה" @@ -154,4 +156,6 @@ "ביטול של הכול" "הרחבה של %1$s" "כיווץ של %1$s" + + diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml index 28b7746b43..4cfe9ed4f5 100644 --- a/quickstep/res/values-ja/strings.xml +++ b/quickstep/res/values-ja/strings.xml @@ -22,6 +22,8 @@ "固定" "フリーフォーム" "デスクトップ" + + "パソコン" "最近のアイテムはありません" "アプリの使用状況の設定" @@ -154,4 +156,6 @@ "すべて解除" "%1$sを開きます" "%1$sを閉じます" + + diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml index d84d53e576..c02e9ad755 100644 --- a/quickstep/res/values-ka/strings.xml +++ b/quickstep/res/values-ka/strings.xml @@ -22,6 +22,8 @@ "ჩამაგრება" "თავისუფალი ფორმა" "დესკტოპი" + + "დესკტოპი" "ბოლოს გამოყენებული ერთეულები არ არის" "აპების გამოყენების პარამეტრები" @@ -154,4 +156,6 @@ "ყველას დახურვა" "%1$s-ის გაფართოება" "%1$s-ის ჩაკეცვა" + + diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index 4cdbfc4d94..64b3e53ddc 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -22,6 +22,8 @@ "Бекіту" "Еркін форма" "Компьютер" + + "Жұмыс үстелі" "Соңғы элементтер жоқ" "Қолданбаны пайдалану параметрлері" @@ -154,4 +156,6 @@ "Барлығын жабу" "%1$s: жаю" "%1$s: жию" + + diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index 5cf1b92737..d962ba5572 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -22,6 +22,8 @@ "ខ្ទាស់" "មុខងារទម្រង់សេរី" "ដែសថប" + + "អេក្រង់ដើម" "មិនមានធាតុថ្មីៗទេ" "ការកំណត់​ការប្រើប្រាស់​កម្មវិធី" @@ -154,4 +156,6 @@ "ច្រានចោលទាំងអស់" "ពង្រីក %1$s" "បង្រួម %1$s" + + diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml index 63b0006ee9..3a05e21dec 100644 --- a/quickstep/res/values-kn/strings.xml +++ b/quickstep/res/values-kn/strings.xml @@ -22,6 +22,8 @@ "ಪಿನ್ ಮಾಡಿ" "ಮುಕ್ತಸ್ವರೂಪ" "ಡೆಸ್ಕ್‌ಟಾಪ್" + + "ಡೆಸ್ಕ್‌ಟಾಪ್" "ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ" "ಆ್ಯಪ್‌ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" @@ -154,4 +156,6 @@ "ಎಲ್ಲವನ್ನು ವಜಾಗೊಳಿಸಿ" "%1$s ಅನ್ನು ವಿಸ್ತೃತಗೊಳಿಸಿ" "%1$s ಅನ್ನು ಕುಗ್ಗಿಸಿ" + + diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml index 589cc225f6..6a7ba74377 100644 --- a/quickstep/res/values-ko/strings.xml +++ b/quickstep/res/values-ko/strings.xml @@ -22,6 +22,8 @@ "고정" "자유 형식" "데스크톱" + + "데스크톱" "최근 항목이 없습니다." "앱 사용 설정" @@ -154,4 +156,6 @@ "모두 닫기" "%1$s 펼치기" "%1$s 접기" + + diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index faf5675762..e92b920bb3 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -22,6 +22,8 @@ "Кадап коюу" "Эркин форма режими" "Компьютер" + + "Компьютер" "Акыркы колдонмолор жок" "Колдонмону пайдалануу параметрлери" @@ -154,4 +156,6 @@ "Баарын четке кагуу" "%1$s жайып көрсөтүү" "%1$s жыйыштыруу" + + diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml index 622db2d1b0..f45c8ce0a6 100644 --- a/quickstep/res/values-lo/strings.xml +++ b/quickstep/res/values-lo/strings.xml @@ -22,6 +22,8 @@ "ປັກໝຸດ" "ຮູບແບບອິດສະຫລະ" "ເດັສທັອບ" + + "ເດັສທັອບ" "ບໍ່ມີລາຍການຫຼ້າສຸດ" "ການຕັ້ງຄ່າການນຳໃຊ້ແອັບ" @@ -154,4 +156,6 @@ "ປິດທັງໝົດ" "ຂະຫຍາຍ %1$s" "ຫຍໍ້ %1$s ລົງ" + + diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml index a95249b508..c488859752 100644 --- a/quickstep/res/values-lt/strings.xml +++ b/quickstep/res/values-lt/strings.xml @@ -22,6 +22,8 @@ "Prisegti" "Laisva forma" "Stalinis kompiuteris" + + "Stalinis kompiuteris" "Nėra jokių naujausių elementų" "Programos naudojimo nustatymai" @@ -154,4 +156,5 @@ "Atsisakyti visų" "išskleisti „%1$s“" "sutraukti „%1$s“" + "Paieška apibrėžiant" diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml index 1892f6462e..23e64a7fff 100644 --- a/quickstep/res/values-lv/strings.xml +++ b/quickstep/res/values-lv/strings.xml @@ -22,6 +22,8 @@ "Piespraust" "Brīva forma" "Dators" + + "Darbvirsma" "Nav nesenu vienumu." "Lietotņu izmantošanas iestatījumi" @@ -154,4 +156,6 @@ "Nerādīt nevienu" "izvērst “%1$s”" "sakļaut “%1$s”" + + diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml index ce4e1b098e..f0588e88da 100644 --- a/quickstep/res/values-mk/strings.xml +++ b/quickstep/res/values-mk/strings.xml @@ -22,6 +22,8 @@ "Закачи" "Freeform" "Работна површина" + + "За компјутер" "Нема неодамнешни ставки" "Поставки за користење на апликациите" @@ -154,4 +156,6 @@ "Отфрли ги сите" "прошири %1$s" "собери %1$s" + + diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml index c15a241bdb..833090cc62 100644 --- a/quickstep/res/values-ml/strings.xml +++ b/quickstep/res/values-ml/strings.xml @@ -22,6 +22,8 @@ "പിൻ ചെയ്യുക" "ഫ്രീഫോം" "ഡെസ്‌ക്ടോപ്പ്" + + "ഡെസ്‌ക്ടോപ്പ്" "സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല" "ആപ്പ് ഉപയോഗ ക്രമീകരണം" @@ -154,4 +156,6 @@ "എല്ലാം ഡിസ്മിസ് ചെയ്യുക" "%1$s വികസിപ്പിക്കുക" "%1$s ചുരുക്കുക" + + diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml index 1ff7502644..100b8edfb4 100644 --- a/quickstep/res/values-mn/strings.xml +++ b/quickstep/res/values-mn/strings.xml @@ -22,6 +22,8 @@ "Бэхлэх" "Чөлөөтэй хувьсах" "Компьютер" + + "Дэлгэц" "Сүүлийн үеийн зүйл алга" "Апп ашиглалтын тохиргоо" @@ -154,4 +156,6 @@ "Бүгдийг үл хэрэгсэх" "%1$s-г дэлгэх" "%1$s-г хураах" + + diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index 215ae3f77c..870cf4ea6d 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -22,6 +22,8 @@ "पिन करा" "फ्रीफॉर्म" "डेस्कटॉप" + + "डेस्कटॉप" "कोणतेही अलीकडील आयटम नाहीत" "अ‍ॅप वापर सेटिंग्ज" @@ -154,4 +156,6 @@ "सर्व डिसमिस करा" "%1$s चा विस्तार करा" "%1$s कोलॅप्स करा" + + diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml index a1f19a95a4..bed2fce8d5 100644 --- a/quickstep/res/values-ms/strings.xml +++ b/quickstep/res/values-ms/strings.xml @@ -22,6 +22,8 @@ "Semat" "Bentuk bebas" "Desktop" + + "Desktop" "Tiada item terbaharu" "Tetapan penggunaan apl" @@ -154,4 +156,6 @@ "Ketepikan semua" "kembangkan %1$s" "kuncupkan %1$s" + + diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index eeb774b367..ae0f66d1cb 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -22,6 +22,8 @@ "ပင်ထိုးရန်" "အလွတ်ပုံစံ" "ဒက်စ်တော့" + + "ဒက်စ်တော့" "မကြာမီကဖွင့်ထားသည်များ မရှိပါ" "အက်ပ်အသုံးပြုမှု ဆက်တင်များ" @@ -154,4 +156,6 @@ "အားလုံးကို ပယ်ရန်" "%1$s ကို ပိုပြပါ" "%1$s ကို လျှော့ပြပါ" + + diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index b62b7fde0c..1ce18c1b3b 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -22,6 +22,8 @@ "Fest" "Fritt format" "Skrivebord" + + "Skrivebord" "Ingen nylige elementer" "Innstillinger for appbruk" @@ -154,4 +156,6 @@ "Lukk alle" "vis %1$s" "skjul %1$s" + + diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index a2d4d325b3..1921fed160 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -22,6 +22,8 @@ "पिन गर्नुहोस्" "फ्रिफर्म" "डेस्कटप" + + "डेस्कटप" "हालसालैको कुनै पनि वस्तु छैन" "एपको उपयोगका सेटिङहरू" @@ -154,4 +156,6 @@ "सबै हटाउनुहोस्" "%1$s एक्स्पान्ड गर्नुहोस्" "%1$s कोल्याप्स गर्नुहोस्" + + diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml index ee876cfcfc..995d8d4849 100644 --- a/quickstep/res/values-nl/strings.xml +++ b/quickstep/res/values-nl/strings.xml @@ -22,6 +22,8 @@ "Vastzetten" "Vrije vorm" "Desktop" + + "Desktop" "Geen recente items" "Instellingen voor app-gebruik" @@ -154,4 +156,6 @@ "Alles sluiten" "%1$s uitvouwen" "%1$s samenvouwen" + + diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml index 3ee59b5194..430058b24d 100644 --- a/quickstep/res/values-or/strings.xml +++ b/quickstep/res/values-or/strings.xml @@ -22,6 +22,8 @@ "ପିନ୍‍" "ଫ୍ରିଫର୍ମ" "ଡେସ୍କଟପ" + + "ଡେସ୍କଟପ" "ବର୍ତ୍ତମାନର କୌଣସି ଆଇଟମ ନାହିଁ" "ଆପ ବ୍ୟବହାର ସେଟିଂସ" @@ -154,4 +156,6 @@ "ସବୁ ଖାରଜ କରନ୍ତୁ" "%1$s ବିସ୍ତାର କରନ୍ତୁ" "%1$s ସଙ୍କୁଚିତ କରନ୍ତୁ" + + diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml index 1e8d52e741..d8d0907390 100644 --- a/quickstep/res/values-pa/strings.xml +++ b/quickstep/res/values-pa/strings.xml @@ -22,6 +22,8 @@ "ਪਿੰਨ ਕਰੋ" "ਫ੍ਰੀਫਾਰਮ" "ਡੈਸਕਟਾਪ" + + "ਡੈਸਕਟਾਪ" "ਕੋਈ ਹਾਲੀਆ ਆਈਟਮ ਨਹੀਂ" "ਐਪ ਵਰਤੋਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ" @@ -154,4 +156,6 @@ "ਸਭ ਖਾਰਜ ਕਰੋ" "%1$s ਦਾ ਵਿਸਤਾਰ ਕਰੋ" "%1$s ਨੂੰ ਸਮੇਟੋ" + + diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml index 64adddf55e..957e5c47e2 100644 --- a/quickstep/res/values-pl/strings.xml +++ b/quickstep/res/values-pl/strings.xml @@ -22,6 +22,8 @@ "Przypnij" "Tryb dowolny" "Pulpit" + + "Pulpit" "Brak ostatnich elementów" "Ustawienia użycia aplikacji" @@ -154,4 +156,6 @@ "Zamknij wszystkie" "rozwiń dymek: %1$s" "zwiń dymek: %1$s" + + diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index 2167875719..ca7cd58bb5 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -22,6 +22,8 @@ "Fixar" "Forma livre" "Computador" + + "Computador" "Nenhum item recente" "Definições de utilização de aplicações" @@ -154,4 +156,6 @@ "Ignorar tudo" "expandir %1$s" "reduzir %1$s" + + diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index 9309810cdf..aee1c8d758 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -22,6 +22,8 @@ "Fixar" "Forma livre" "Modo área de trabalho" + + "Computador" "Nenhum item recente" "Configurações de uso do app" @@ -154,4 +156,6 @@ "Dispensar todos" "abrir %1$s" "fechar %1$s" + + diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml index 19075cd554..c05b85b5ab 100644 --- a/quickstep/res/values-ro/strings.xml +++ b/quickstep/res/values-ro/strings.xml @@ -22,6 +22,8 @@ "Fixează" "Formă liberă" "Desktop" + + "Computer" "Niciun element recent" "Setări de utilizare a aplicației" @@ -154,4 +156,6 @@ "Închide-le pe toate" "extinde %1$s" "restrânge %1$s" + + diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml index 76c4e1f646..fca0a056d3 100644 --- a/quickstep/res/values-ru/strings.xml +++ b/quickstep/res/values-ru/strings.xml @@ -22,6 +22,8 @@ "Закрепить" "Произвольная форма" "Мультиоконный режим" + + "Мультиоконный режим" "Здесь пока ничего нет." "Настройки использования приложения" @@ -154,4 +156,6 @@ "Закрыть все" "Развернуто: %1$s" "Свернуто: %1$s" + + diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml index 0953b38bd1..cfbf1ddd2e 100644 --- a/quickstep/res/values-si/strings.xml +++ b/quickstep/res/values-si/strings.xml @@ -22,6 +22,8 @@ "අමුණන්න" "Freeform" "ඩෙස්ක්ටොපය" + + "ඩෙස්ක්ටොපය" "මෑත අයිතම නැත" "යෙදුම් භාවිත සැකසීම්" @@ -154,4 +156,6 @@ "සියල්ල ඉවතලන්න" "%1$s දිග හරින්න" "%1$s හකුළන්න" + + diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml index 9b682e6034..b3145de532 100644 --- a/quickstep/res/values-sk/strings.xml +++ b/quickstep/res/values-sk/strings.xml @@ -22,6 +22,8 @@ "Pripnúť" "Voľný režim" "Počítač" + + "Počítač" "Žiadne nedávne položky" "Nastavenia využívania aplikácie" @@ -154,4 +156,6 @@ "Zavrieť všetko" "rozbaliť %1$s" "zbaliť %1$s" + + diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml index 94de1e0567..d72436a046 100644 --- a/quickstep/res/values-sl/strings.xml +++ b/quickstep/res/values-sl/strings.xml @@ -22,6 +22,8 @@ "Pripni" "Prosta oblika" "Namizni računalnik" + + "Namizni način" "Ni nedavnih elementov" "Nastavitve uporabe aplikacij" @@ -154,4 +156,6 @@ "Opusti vse" "razširitev oblačka %1$s" "strnitev oblačka %1$s" + + diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml index 29214c9701..30ba61df9f 100644 --- a/quickstep/res/values-sq/strings.xml +++ b/quickstep/res/values-sq/strings.xml @@ -22,6 +22,8 @@ "Gozhdo" "Formë e lirë" "Desktopi" + + "Desktopi" "Nuk ka asnjë artikull të fundit" "Cilësimet e përdorimit të aplikacionit" @@ -154,4 +156,6 @@ "Hiqi të gjitha" "zgjero %1$s" "palos %1$s" + + diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml index d6e5d03cee..b83a4f251e 100644 --- a/quickstep/res/values-sr/strings.xml +++ b/quickstep/res/values-sr/strings.xml @@ -22,6 +22,8 @@ "Закачи" "Слободни облик" "Рачунар" + + "Рачунари" "Нема недавних ставки" "Подешавања коришћења апликације" @@ -154,4 +156,6 @@ "Одбаци све" "проширите облачић %1$s" "скупите облачић %1$s" + + diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index bba98c6fb6..5ab3866475 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -22,6 +22,8 @@ "Fäst" "Fritt format" "Dator" + + "Dator" "Listan är tom" "Inställningar för appanvändning" @@ -154,4 +156,6 @@ "Stäng alla" "utöka %1$s" "komprimera %1$s" + + diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml index f8d6a4f229..9d13df8a77 100644 --- a/quickstep/res/values-sw/strings.xml +++ b/quickstep/res/values-sw/strings.xml @@ -22,6 +22,8 @@ "Bandika" "Muundo huru" "Kompyuta ya mezani" + + "Kompyuta ya Mezani" "Hakuna vipengee vya hivi karibuni" "Mipangilio ya matumizi ya programu" @@ -154,4 +156,6 @@ "Ondoa vyote" "panua %1$s" "kunja %1$s" + + diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml index 73c6c3746f..8ac0ff8aab 100644 --- a/quickstep/res/values-ta/strings.xml +++ b/quickstep/res/values-ta/strings.xml @@ -22,6 +22,8 @@ "பின் செய்தல்" "குறிப்பிட்ட வடிவமில்லாத பயன்முறை" "டெஸ்க்டாப்" + + "டெஸ்க்டாப்" "சமீபத்தியவை எதுவுமில்லை" "ஆப்ஸ் உபயோக அமைப்புகள்" @@ -154,4 +156,6 @@ "அனைத்தையும் மூடும்" "%1$s ஐ விரிவாக்கும்" "%1$s ஐச் சுருக்கும்" + + diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index 91ef8463a9..4ae7a58ed5 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -22,6 +22,8 @@ "పిన్ చేయండి" "సంప్రదాయేతర" "డెస్క్‌టాప్" + + "డెస్క్‌టాప్" "ఇటీవలి ఐటెమ్‌లు ఏవీ లేవు" "యాప్ వినియోగ సెట్టింగ్‌లు" @@ -154,4 +156,6 @@ "అన్నింటినీ విస్మరించండి" "%1$sను విస్తరించండి" "%1$sను కుదించండి" + + diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml index 2218e6d0e1..210e996664 100644 --- a/quickstep/res/values-th/strings.xml +++ b/quickstep/res/values-th/strings.xml @@ -22,6 +22,8 @@ "ปักหมุด" "รูปแบบอิสระ" "เดสก์ท็อป" + + "เดสก์ท็อป" "ไม่มีรายการล่าสุด" "การตั้งค่าการใช้แอป" @@ -154,4 +156,6 @@ "ปิดทั้งหมด" "ขยาย %1$s" "ยุบ %1$s" + + diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml index fac6a52650..13d89a269d 100644 --- a/quickstep/res/values-tl/strings.xml +++ b/quickstep/res/values-tl/strings.xml @@ -22,6 +22,8 @@ "I-pin" "Freeform" "Desktop" + + "Desktop" "Walang kamakailang item" "Mga setting ng paggamit ng app" @@ -154,4 +156,6 @@ "I-dismiss lahat" "i-expand ang %1$s" "i-collapse ang %1$s" + + diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml index d44d710365..1cb1fa7e4f 100644 --- a/quickstep/res/values-tr/strings.xml +++ b/quickstep/res/values-tr/strings.xml @@ -22,6 +22,8 @@ "Sabitle" "Serbest çalışma" "Masaüstü" + + "Masaüstü" "Yeni öğe yok" "Uygulama kullanım ayarları" @@ -154,4 +156,6 @@ "Tümünü kapat" "genişlet: %1$s" "daralt: %1$s" + + diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml index 320c2ea10e..84ddd81fbc 100644 --- a/quickstep/res/values-uk/strings.xml +++ b/quickstep/res/values-uk/strings.xml @@ -22,6 +22,8 @@ "Закріпити" "Довільна форма" "Робочий стіл" + + "Комп’ютер" "Немає нещодавніх додатків" "Налаштування використання додатка" @@ -154,4 +156,6 @@ "Закрити все" "розгорнути \"%1$s\"" "згорнути \"%1$s\"" + + diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml index c71625a117..43e97c24b7 100644 --- a/quickstep/res/values-ur/strings.xml +++ b/quickstep/res/values-ur/strings.xml @@ -22,6 +22,8 @@ "پن کریں" "فری فارم" "ڈیسک ٹاپ" + + "ڈیسک ٹاپ" "کوئی حالیہ آئٹم نہیں" "ایپ کے استعمال کی ترتیبات" @@ -154,4 +156,6 @@ "سبھی کو برخاست کریں" "%1$s کو پھیلائیں" "%1$s کو سکیڑیں" + + diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml index e37945355a..090753ff45 100644 --- a/quickstep/res/values-uz/strings.xml +++ b/quickstep/res/values-uz/strings.xml @@ -22,6 +22,8 @@ "Qadash" "Erkin shakl" "Desktop" + + "Desktop" "Yaqinda ishlatilgan ilovalar yo‘q" "Ilovadan foydalanish sozlamalari" @@ -154,4 +156,6 @@ "Hammasini yopish" "%1$sni yoyish" "%1$sni yigʻish" + + diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml index ddefb9e9c4..b0d31cbfb6 100644 --- a/quickstep/res/values-vi/strings.xml +++ b/quickstep/res/values-vi/strings.xml @@ -22,6 +22,8 @@ "Ghim" "Dạng tự do" "Máy tính" + + "Máy tính" "Không có mục gần đây nào" "Cài đặt mức sử dụng ứng dụng" @@ -154,4 +156,6 @@ "Đóng tất cả" "mở rộng %1$s" "thu gọn %1$s" + + diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index 8540cd9c4c..73121b4976 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -22,6 +22,8 @@ "固定" "自由窗口" "桌面" + + "桌面设备" "近期没有任何内容" "应用使用设置" @@ -154,4 +156,6 @@ "全部关闭" "展开“%1$s”" "收起“%1$s”" + + diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index 3d16e8db3c..b934dfcf44 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -22,6 +22,8 @@ "固定" "自由形式" "桌面" + + "桌面" "最近沒有任何項目" "應用程式使用情況設定" @@ -154,4 +156,6 @@ "全部關閉" "打開%1$s" "收埋%1$s" + + diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index bf0381205e..1cba81966b 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -22,6 +22,8 @@ "固定" "自由形式" "桌面" + + "電腦" "最近沒有任何項目" "應用程式使用情況設定" @@ -154,4 +156,6 @@ "全部關閉" "展開「%1$s」" "收合「%1$s」" + + diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml index d0d0bb646a..ee6b3b7208 100644 --- a/quickstep/res/values-zu/strings.xml +++ b/quickstep/res/values-zu/strings.xml @@ -22,6 +22,8 @@ "Phina" "I-Freeform" "Ideskithophu" + + "Ideskithophu" "Azikho izinto zakamuva" "Izilungiselelo zokusetshenziswa kohlelo lokusebenza" @@ -154,4 +156,6 @@ "Chitha konke" "nweba %1$s" "goqa %1$s" + + diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index 41b2384a35..db5ff199ab 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -33,7 +33,6 @@ com.android.launcher3.taskbar.TaskbarModelCallbacksFactory com.android.launcher3.taskbar.TaskbarViewCallbacksFactory com.android.quickstep.LauncherRestoreEventLoggerImpl - com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl com.android.launcher3.taskbar.TaskbarEduTooltipController com.android.quickstep.contextualeducation.SystemContextualEduStatsManager diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt new file mode 100644 index 0000000000..dd2ff2d580 --- /dev/null +++ b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.desktop + +import android.animation.Animator +import android.animation.AnimatorSet +import android.animation.ValueAnimator +import android.content.Context +import android.os.IBinder +import android.view.SurfaceControl.Transaction +import android.view.WindowManager.TRANSIT_OPEN +import android.view.WindowManager.TRANSIT_TO_BACK +import android.view.WindowManager.TRANSIT_TO_FRONT +import android.window.IRemoteTransitionFinishedCallback +import android.window.RemoteTransitionStub +import android.window.TransitionInfo +import android.window.TransitionInfo.Change +import androidx.core.animation.addListener +import com.android.app.animation.Interpolators +import com.android.quickstep.RemoteRunnable +import java.util.concurrent.Executor + +/** + * [android.window.RemoteTransition] for Desktop app launches. + * + * This transition supports minimize-changes, i.e. in a launch-transition, if a window is moved back + * ([android.view.WindowManager.TRANSIT_TO_BACK]) this transition will apply a minimize animation to + * that window. + */ +class DesktopAppLaunchTransition(private val context: Context, private val mainExecutor: Executor) : + RemoteTransitionStub() { + + override fun startAnimation( + token: IBinder, + info: TransitionInfo, + t: Transaction, + transitionFinishedCallback: IRemoteTransitionFinishedCallback, + ) { + val safeTransitionFinishedCallback = RemoteRunnable { + transitionFinishedCallback.onTransitionFinished(/* wct= */ null, /* sct= */ null) + } + mainExecutor.execute { + runAnimators(info, safeTransitionFinishedCallback) + t.apply() + } + } + + private fun runAnimators(info: TransitionInfo, finishedCallback: RemoteRunnable) { + val animators = mutableListOf() + val animatorFinishedCallback: (Animator) -> Unit = { animator -> + animators -= animator + if (animators.isEmpty()) finishedCallback.run() + } + animators += createAnimators(info, animatorFinishedCallback) + animators.forEach { it.start() } + } + + private fun createAnimators( + info: TransitionInfo, + finishCallback: (Animator) -> Unit, + ): List { + val transaction = Transaction() + val launchAnimator = + createLaunchAnimator(getLaunchChange(info), transaction, finishCallback) + val minimizeChange = getMinimizeChange(info) ?: return listOf(launchAnimator) + val minimizeAnimator = createMinimizeAnimator(minimizeChange, transaction, finishCallback) + return listOf(launchAnimator, minimizeAnimator) + } + + private fun getLaunchChange(info: TransitionInfo): Change = + requireNotNull(info.changes.firstOrNull { change -> change.mode in LAUNCH_CHANGE_MODES }) { + "expected an app launch Change" + } + + private fun getMinimizeChange(info: TransitionInfo): Change? = + info.changes.firstOrNull { change -> change.mode == TRANSIT_TO_BACK } + + private fun createLaunchAnimator( + change: Change, + transaction: Transaction, + onAnimFinish: (Animator) -> Unit, + ): Animator { + val boundsAnimator = + WindowAnimator.createBoundsAnimator( + context, + launchBoundsAnimationDef, + change, + transaction, + ) + val alphaAnimator = + ValueAnimator.ofFloat(0f, 1f).apply { + duration = LAUNCH_ANIM_ALPHA_DURATION_MS + interpolator = Interpolators.LINEAR + addUpdateListener { animation -> + transaction.setAlpha(change.leash, animation.animatedValue as Float).apply() + } + } + return AnimatorSet().apply { + playTogether(boundsAnimator, alphaAnimator) + addListener(onEnd = { animation -> onAnimFinish(animation) }) + } + } + + private fun createMinimizeAnimator( + change: Change, + transaction: Transaction, + onAnimFinish: (Animator) -> Unit, + ): Animator { + val boundsAnimator = + WindowAnimator.createBoundsAnimator( + context, + minimizeBoundsAnimationDef, + change, + transaction, + ) + val alphaAnimator = + ValueAnimator.ofFloat(1f, 0f).apply { + duration = MINIMIZE_ANIM_ALPHA_DURATION_MS + interpolator = Interpolators.LINEAR + addUpdateListener { animation -> + transaction.setAlpha(change.leash, animation.animatedValue as Float).apply() + } + } + return AnimatorSet().apply { + playTogether(boundsAnimator, alphaAnimator) + addListener(onEnd = { animation -> onAnimFinish(animation) }) + } + } + + companion object { + private val LAUNCH_CHANGE_MODES = intArrayOf(TRANSIT_OPEN, TRANSIT_TO_FRONT) + + private const val LAUNCH_ANIM_ALPHA_DURATION_MS = 100L + private const val MINIMIZE_ANIM_ALPHA_DURATION_MS = 100L + + private val launchBoundsAnimationDef = + WindowAnimator.BoundsAnimationParams( + durationMs = 300, + startOffsetYDp = 12f, + startScale = 0.97f, + interpolator = Interpolators.STANDARD_DECELERATE, + ) + + private val minimizeBoundsAnimationDef = + WindowAnimator.BoundsAnimationParams( + durationMs = 200, + endOffsetYDp = 12f, + endScale = 0.97f, + interpolator = Interpolators.STANDARD_ACCELERATE, + ) + } +} diff --git a/quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt b/quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt new file mode 100644 index 0000000000..1a99a36b4c --- /dev/null +++ b/quickstep/src/com/android/launcher3/desktop/WindowAnimator.kt @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.desktop + +import android.animation.RectEvaluator +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Rect +import android.util.TypedValue +import android.view.SurfaceControl +import android.view.animation.Interpolator +import android.window.TransitionInfo + +/** Creates animations that can be applied to windows/surfaces. */ +object WindowAnimator { + + /** Parameters defining a window bounds animation. */ + data class BoundsAnimationParams( + val durationMs: Long, + val startOffsetYDp: Float = 0f, + val endOffsetYDp: Float = 0f, + val startScale: Float = 1f, + val endScale: Float = 1f, + val interpolator: Interpolator, + ) + + /** + * Creates an animator to reposition and scale the bounds of the leash of the given change. + * + * @param boundsAnimDef the parameters for the animation itself (duration, scale, position) + * @param change the change to which the animation should be applied + * @param transaction the transaction to apply the animation to + */ + fun createBoundsAnimator( + context: Context, + boundsAnimDef: BoundsAnimationParams, + change: TransitionInfo.Change, + transaction: SurfaceControl.Transaction, + ): ValueAnimator { + val startBounds = + createBounds( + context, + change.startAbsBounds, + boundsAnimDef.startScale, + boundsAnimDef.startOffsetYDp, + ) + val leash = change.leash + val endBounds = + createBounds( + context, + change.startAbsBounds, + boundsAnimDef.endScale, + boundsAnimDef.endOffsetYDp, + ) + return ValueAnimator.ofObject(RectEvaluator(), startBounds, endBounds).apply { + duration = boundsAnimDef.durationMs + interpolator = boundsAnimDef.interpolator + addUpdateListener { animation -> + val animBounds = animation.animatedValue as Rect + val animScale = 1 - (1 - boundsAnimDef.endScale) * animation.animatedFraction + transaction + .setPosition(leash, animBounds.left.toFloat(), animBounds.top.toFloat()) + .setScale(leash, animScale, animScale) + .apply() + } + } + } + + private fun createBounds(context: Context, origBounds: Rect, scale: Float, offsetYDp: Float) = + Rect(origBounds).apply { + check(scale in 0.0..1.0) + // Scale the bounds down with an anchor in the center + inset( + (origBounds.width().toFloat() * (1 - scale) / 2).toInt(), + (origBounds.height().toFloat() * (1 - scale) / 2).toInt(), + ) + val offsetYPx = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + offsetYDp, + context.resources.displayMetrics, + ) + .toInt() + offset(/* dx= */ 0, offsetYPx) + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java index 1c8a094c06..a80c11cc17 100644 --- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.taskbar; +import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.animation.Animator; @@ -31,6 +32,7 @@ import androidx.annotation.Nullable; import com.android.internal.jank.Cuj; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; +import com.android.launcher3.desktop.DesktopAppLaunchTransition; import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer; import com.android.launcher3.views.BaseDragLayer; @@ -41,6 +43,7 @@ import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.QuickStepContract; +import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.List; @@ -181,7 +184,7 @@ public class KeyboardQuickSwitchViewController { Runnable onFinishCallback = () -> InteractionJankMonitorWrapper.end( Cuj.CUJ_LAUNCHER_KEYBOARD_QUICK_SWITCH_APP_LAUNCH); TaskbarActivityContext context = mControllers.taskbarActivityContext; - RemoteTransition remoteTransition = new RemoteTransition(new SlideInRemoteTransition( + final RemoteTransition slideInTransition = new RemoteTransition(new SlideInRemoteTransition( Utilities.isRtl(mControllers.taskbarActivityContext.getResources()), context.getDeviceProfile().overviewPageSpacing, QuickStepContract.getWindowCornerRadius(context), @@ -195,7 +198,7 @@ public class KeyboardQuickSwitchViewController { SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext()) .showDesktopApps( mKeyboardQuickSwitchView.getDisplay().getDisplayId(), - remoteTransition)); + slideInTransition)); return -1; } // Even with a valid index, this can be null if the user tries to quick switch before the @@ -208,6 +211,13 @@ public class KeyboardQuickSwitchViewController { // Ignore attempts to run the selected task if it is already running. return -1; } + RemoteTransition remoteTransition = slideInTransition; + if (mOnDesktop && task.task1.isMinimized + && Flags.enableDesktopAppLaunchAlttabTransitions()) { + // This app is being unminimized - use our own transition runner. + remoteTransition = new RemoteTransition( + new DesktopAppLaunchTransition(context, MAIN_EXECUTOR)); + } mControllers.taskbarActivityContext.handleGroupTaskLaunch( task, remoteTransition, diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 1b9614a33a..12be99dc3d 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -952,6 +952,12 @@ public class TaskbarActivityContext extends BaseTaskbarContext { * Hides the taskbar icons and background when the notification shade is expanded. */ private void onNotificationShadeExpandChanged(boolean isExpanded, boolean skipAnim) { + // Close all floating views within the Taskbar window to make sure nothing is shown over + // the notification shade. + if (isExpanded) { + AbstractFloatingView.closeAllOpenViewsExcept(this, TYPE_TASKBAR_OVERLAY_PROXY); + } + float alpha = isExpanded ? 0 : 1; AnimatorSet anim = new AnimatorSet(); anim.play(mControllers.taskbarViewController.getTaskbarIconAlpha().get( @@ -1234,7 +1240,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } } else if (tag instanceof TaskItemInfo info) { UI_HELPER_EXECUTOR.execute(() -> - SystemUiProxy.INSTANCE.get(this).showDesktopApp(info.getTaskId())); + SystemUiProxy.INSTANCE.get(this).showDesktopApp( + info.getTaskId(), /* remoteTransition= */ null)); mControllers.taskbarStashController.updateAndAnimateTransientTaskbar( /* stash= */ true); } else if (tag instanceof WorkspaceItemInfo) { @@ -1325,7 +1332,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { GroupTask task, @Nullable RemoteTransition remoteTransition, boolean onDesktop) { - handleGroupTaskLaunch(task, remoteTransition, onDesktop, null, null); + handleGroupTaskLaunch(task, remoteTransition, onDesktop, + /* onStartCallback= */ null, /* onFinishCallback= */ null); } /** @@ -1349,17 +1357,24 @@ public class TaskbarActivityContext extends BaseTaskbarContext { UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(this).showDesktopApps(getDisplay().getDisplayId(), remoteTransition)); - } else if (onDesktop) { + return; + } + if (onDesktop) { + boolean useRemoteTransition = task.task1.isMinimized + && com.android.window.flags.Flags.enableDesktopAppLaunchAlttabTransitions(); UI_HELPER_EXECUTOR.execute(() -> { if (onStartCallback != null) { onStartCallback.run(); } - SystemUiProxy.INSTANCE.get(this).showDesktopApp(task.task1.key.id); + SystemUiProxy.INSTANCE.get(this).showDesktopApp( + task.task1.key.id, useRemoteTransition ? remoteTransition : null); if (onFinishCallback != null) { onFinishCallback.run(); } }); - } else if (task.task2 == null) { + return; + } + if (task.task2 == null) { UI_HELPER_EXECUTOR.execute(() -> { ActivityOptions activityOptions = makeDefaultActivityOptions(SPLASH_SCREEN_STYLE_UNDEFINED).options; @@ -1368,9 +1383,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { ActivityManagerWrapper.getInstance().startActivityFromRecents( task.task1.key, activityOptions); }); - } else { - mControllers.uiController.launchSplitTasks(task, remoteTransition); + return; } + mControllers.uiController.launchSplitTasks(task, remoteTransition); } /** @@ -1547,6 +1562,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { /** * Called when we want to unstash taskbar when user performs swipes up gesture. + * * @param delayTaskbarBackground whether we will delay the taskbar background animation */ public void onSwipeToUnstashTaskbar(boolean delayTaskbarBackground) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 1141a01726..55722a9b62 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -151,30 +151,26 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas DisplayController.showLockedTaskbarOnHome(context) ) { // adding the taskbar touch region - val touchableHeight: Int var left = 0 var right = context.deviceProfile.widthPx - var bubbleBarAdjustment = 0 + val touchableHeight: Int if (uiController.isAnimatingToLauncher) { val dp = controllers.taskbarActivityContext.deviceProfile touchableHeight = windowLayoutParams.height if (dp.isQsbInline) { // if Qsb is inline need to exclude search icon from touch region val isRtl = Utilities.isRtl(context.resources) - bubbleControllers?.bubbleBarViewController?.let { - if (dp.shouldAdjustHotseatOnBubblesLocationUpdate(context)) { + val navBarOffset = + bubbleControllers?.bubbleBarViewController?.let { val isBubblesOnLeft = it.bubbleBarLocation.isOnLeft(isRtl) - bubbleBarAdjustment = - dp.getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl) - } - } + dp.getHotseatTranslationXForNavBar(context, isBubblesOnLeft) + } ?: 0 val hotseatPadding: Rect = dp.getHotseatLayoutPadding(context) val borderSpacing: Int = dp.hotseatBorderSpace if (isRtl) { - right = - dp.widthPx - hotseatPadding.right + borderSpacing + bubbleBarAdjustment + right = dp.widthPx - hotseatPadding.right + borderSpacing + navBarOffset } else { - left = hotseatPadding.left - borderSpacing + bubbleBarAdjustment + left = hotseatPadding.left - borderSpacing + navBarOffset } } } else { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 39aef28d45..4bc7d3c329 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar; import static com.android.app.animation.Interpolators.EMPHASIZED; +import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_ALIGNMENT; import static com.android.launcher3.Hotseat.ALPHA_CHANNEL_TASKBAR_STASH; @@ -31,11 +32,8 @@ import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_IN_ANIM_A import static com.android.launcher3.taskbar.bubbles.BubbleBarView.FADE_OUT_ANIM_POSITION_DURATION_MS; import static com.android.launcher3.util.FlagDebugUtils.appendFlag; import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange; +import static com.android.quickstep.util.SystemUiFlagUtils.isTaskbarHidden; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_COMMUNAL_HUB_SHOWING; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK; -import static com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_AWAKE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -380,16 +378,7 @@ public class TaskbarLauncherStateController { updateStateForFlag(FLAG_DEVICE_LOCKED, SystemUiFlagUtils.isLocked(systemUiStateFlags)); - // Taskbar is hidden whenever the device is dreaming. The dreaming state includes the - // interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in - // when the device is asleep, the second condition extends ensures that the transition from - // and to the WAKEFULNESS_ASLEEP state also hide the taskbar, and improves the taskbar - // hide/reveal animation timings. The Taskbar can show when dreaming if the glanceable hub - // is showing on top. - boolean isTaskbarHidden = (hasAnyFlag(systemUiStateFlags, SYSUI_STATE_DEVICE_DREAMING) - && !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_COMMUNAL_HUB_SHOWING)) - || (systemUiStateFlags & SYSUI_STATE_WAKEFULNESS_MASK) != WAKEFULNESS_AWAKE; - updateStateForFlag(FLAG_TASKBAR_HIDDEN, isTaskbarHidden); + updateStateForFlag(FLAG_TASKBAR_HIDDEN, isTaskbarHidden(systemUiStateFlags)); if (applyState) { applyState(); @@ -684,7 +673,11 @@ public class TaskbarLauncherStateController { + mIconAlignment.value + " -> " + toAlignment + ": " + duration); } - animatorSet.play(iconAlignAnim); + if (hasAnyFlag(FLAG_TASKBAR_HIDDEN)) { + iconAlignAnim.setInterpolator(FINAL_FRAME); + } else { + animatorSet.play(iconAlignAnim); + } } Interpolator interpolator = enableScalingRevealHomeAnimation() @@ -893,19 +886,18 @@ public class TaskbarLauncherStateController { mBubbleBarLocation = location; if (location == null) { // bubble bar is not present, hence no location, resetting the hotseat - updateHotseatAndQsbTranslationX(0, animate); + updateHotseatAndQsbTranslationX(/* targetValue = */ 0, animate); mBubbleBarLocation = null; return; } DeviceProfile deviceProfile = mLauncher.getDeviceProfile(); - if (!deviceProfile.shouldAdjustHotseatOnBubblesLocationUpdate( + if (!deviceProfile.shouldAdjustHotseatOnNavBarLocationUpdate( mControllers.taskbarActivityContext)) { return; } - boolean isRtl = isRtl(mLauncher.getResources()); - boolean isBubblesOnLeft = location.isOnLeft(isRtl); + boolean isBubblesOnLeft = location.isOnLeft(isRtl(mLauncher.getResources())); int targetX = deviceProfile - .getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl); + .getHotseatTranslationXForNavBar(mLauncher, isBubblesOnLeft); updateHotseatAndQsbTranslationX(targetX, animate); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt index 9c34ff0eb8..3e8b615b69 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt @@ -251,7 +251,7 @@ class TaskbarRecentAppsController(context: Context, private val recentsModel: Re // Remove any newly-missing Tasks, and actual group-tasks val newShownTasks = shownTasks - .filter { !it.hasMultipleTasks() } + .filter { !it.supportsMultipleTasks() } .filter { it.task1.key.id in desktopTaskIds } .toMutableList() // Add any new Tasks, maintaining the order from previous shownTasks. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 8991965f61..b19da6b8e2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -30,6 +30,7 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.FlagDebugUtils.appendFlag; import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange; import static com.android.quickstep.util.SystemActionConstants.SYSTEM_ACTION_ID_TASKBAR; +import static com.android.quickstep.util.SystemUiFlagUtils.isTaskbarHidden; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DIALOG_SHOWING; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING; @@ -104,6 +105,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba // An internal no-op flag to determine whether we should delay the taskbar background animation private static final int FLAG_DELAY_TASKBAR_BG_TAG = 1 << 12; public static final int FLAG_STASHED_FOR_BUBBLES = 1 << 13; // show handle for stashed hotseat + public static final int FLAG_TASKBAR_HIDDEN = 1 << 14; // taskbar hidden during dream, etc... // If any of these flags are enabled, isInApp should return true. private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP; @@ -215,6 +217,13 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba */ private static final int TRANSITION_UNSTASH_SUW_MANUAL = 3; + /** + * total duration of entering dream state animation, which we use as start delay to + * applyState() when SYSUI_STATE_DEVICE_DREAMING flag is present. Keep this in sync with + * DreamAnimationController.TOTAL_ANIM_DURATION. + */ + private static final int SKIP_TOTAL_DREAM_ANIM_DURATION = 450; + @Retention(RetentionPolicy.SOURCE) @IntDef(value = { TRANSITION_DEFAULT, @@ -1123,7 +1132,13 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba startDelay = getTaskbarStashStartDelayForIme(); } - applyState(skipAnim ? 0 : animDuration, skipAnim ? 0 : startDelay); + if (isTaskbarHidden(systemUiStateFlags) && !hasAnyFlag(FLAG_TASKBAR_HIDDEN)) { + updateStateForFlag(FLAG_TASKBAR_HIDDEN, isTaskbarHidden(systemUiStateFlags)); + applyState(0, SKIP_TOTAL_DREAM_ANIM_DURATION); + } else { + updateStateForFlag(FLAG_TASKBAR_HIDDEN, isTaskbarHidden(systemUiStateFlags)); + applyState(skipAnim ? 0 : animDuration, skipAnim ? 0 : startDelay); + } } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index f8adf8e247..d75718043b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -65,8 +65,8 @@ import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ActivityContext; import com.android.launcher3.views.IconButtonView; -import com.android.quickstep.util.DesktopTask; import com.android.quickstep.util.GroupTask; +import com.android.quickstep.views.TaskViewType; import com.android.systemui.shared.recents.model.Task; import com.android.wm.shell.shared.bubbles.BubbleBarLocation; @@ -472,8 +472,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar // Replace any Recent views with the appropriate type if it's not already that type. final int expectedLayoutResId; boolean isCollection = false; - if (task.hasMultipleTasks()) { - if (task instanceof DesktopTask) { + if (task.supportsMultipleTasks()) { + if (task.taskViewType == TaskViewType.DESKTOP) { // TODO(b/316004172): use Desktop tile layout. expectedLayoutResId = -1; } else { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index c275536b47..e9458ff5a5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -837,12 +837,11 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar int firstRecentTaskIndex = -1; int hotseatNavBarTranslationX = 0; - if (mCurrentBubbleBarLocation != null - && taskbarDp.shouldAdjustHotseatOnBubblesLocationUpdate(mActivity)) { - boolean isRtl = mTaskbarView.isLayoutRtl(); - boolean isBubblesOnLeft = mCurrentBubbleBarLocation.isOnLeft(isRtl); + if (mCurrentBubbleBarLocation != null) { + boolean isBubblesOnLeft = mCurrentBubbleBarLocation + .isOnLeft(mTaskbarView.isLayoutRtl()); hotseatNavBarTranslationX = taskbarDp - .getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl); + .getHotseatTranslationXForNavBar(mActivity, isBubblesOnLeft); } for (int i = 0; i < mTaskbarView.getChildCount(); i++) { View child = mTaskbarView.getChildAt(i); diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index acdff71e61..4ad65e1be8 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -1101,10 +1101,9 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer, if (isBubbleBarEnabled() && enableBubbleBarInPersistentTaskBar() && mBubbleBarLocation != null) { - boolean isRtl = isRtl(getResources()); - boolean isBubblesOnLeft = mBubbleBarLocation.isOnLeft(isRtl); + boolean isBubblesOnLeft = mBubbleBarLocation.isOnLeft(isRtl(getResources())); translationX += mDeviceProfile - .getHotseatTranslationXForBubbleBar(isBubblesOnLeft, isRtl); + .getHotseatTranslationXForNavBar(this, isBubblesOnLeft); } if (isBubbleBarEnabled() && mDeviceProfile.shouldAdjustHotseatForBubbleBar(getContext(), hasBubbles())) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapperImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapperImpl.java index 74572c4136..3aa196365b 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapperImpl.java +++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapperImpl.java @@ -27,6 +27,8 @@ import android.content.Intent; import android.content.pm.ResolveInfo; import com.android.launcher3.BuildConfig; +import com.android.launcher3.dagger.ApplicationContext; +import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.util.PluginManagerWrapper; import com.android.systemui.plugins.Plugin; import com.android.systemui.plugins.PluginListener; @@ -34,7 +36,6 @@ import com.android.systemui.shared.plugins.PluginActionManager; import com.android.systemui.shared.plugins.PluginInstance; import com.android.systemui.shared.plugins.PluginManagerImpl; import com.android.systemui.shared.plugins.PluginPrefs; -import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager; import java.io.PrintWriter; import java.util.ArrayList; @@ -42,16 +43,17 @@ import java.util.Collections; import java.util.List; import java.util.Set; -public class PluginManagerWrapperImpl extends PluginManagerWrapper { +import javax.inject.Inject; - private static final UncaughtExceptionPreHandlerManager UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER = - new UncaughtExceptionPreHandlerManager(); +@LauncherAppSingleton +public class PluginManagerWrapperImpl extends PluginManagerWrapper { private final Context mContext; private final PluginManagerImpl mPluginManager; private final PluginEnablerImpl mPluginEnabler; - public PluginManagerWrapperImpl(Context c) { + @Inject + public PluginManagerWrapperImpl(@ApplicationContext Context c) { mContext = c; mPluginEnabler = new PluginEnablerImpl(c); List privilegedPlugins = Collections.emptyList(); @@ -64,9 +66,11 @@ public class PluginManagerWrapperImpl extends PluginManagerWrapper { c.getSystemService(NotificationManager.class), mPluginEnabler, privilegedPlugins, instanceFactory); + // Use null preHandlerManager, as the handler is never unregistered which can cause leaks + // when using multiple dagger graphs. mPluginManager = new PluginManagerImpl(c, instanceManagerFactory, BuildConfig.IS_DEBUG_DEVICE, - UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER, mPluginEnabler, + null /* preHandlerManager */, mPluginEnabler, new PluginPrefs(c), privilegedPlugins); } diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java index 2892d2c913..015a449cc4 100644 --- a/quickstep/src/com/android/quickstep/GestureState.java +++ b/quickstep/src/com/android/quickstep/GestureState.java @@ -36,6 +36,7 @@ import android.view.RemoteAnimationTarget; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.launcher3.Flags; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulContainer; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; @@ -301,6 +302,16 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL return mTrackpadGestureType == TrackpadGestureType.FOUR_FINGER; } + /** + * Requests that handling for this gesture should use a synthetic transition, as in that it + * will need to start a recents transition that is not backed by a system transition. This is + * generally only needed in scenarios where a system transition can not be created due to no + * changes in the WM hierarchy (ie. starting recents transition when you are already over home). + */ + public boolean useSyntheticRecentsTransition() { + return mRunningTask.isHomeTask() && Flags.enableFallbackOverviewInWindow(); + } + /** * @return the running task for this gesture. */ diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index fc11812f0e..7d5bd377d0 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -15,7 +15,9 @@ */ package com.android.quickstep; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.view.RemoteAnimationTarget.MODE_CLOSING; +import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; @@ -29,6 +31,7 @@ import androidx.annotation.BinderThread; import androidx.annotation.NonNull; import androidx.annotation.UiThread; +import com.android.launcher3.Flags; import com.android.launcher3.Utilities; import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.ActiveGestureProtoLogProxy; @@ -102,7 +105,11 @@ public class RecentsAnimationCallbacks implements long appCount = Arrays.stream(appTargets) .filter(app -> app.mode == MODE_CLOSING) .count(); - if (appCount == 0) { + + boolean isOpeningHome = Arrays.stream(appTargets).filter(app -> app.mode == MODE_OPENING + && app.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME) + .count() > 0; + if (appCount == 0 && (!Flags.enableFallbackOverviewInWindow() || isOpeningHome)) { ActiveGestureProtoLogProxy.logOnRecentsAnimationStartCancelled(); // Edge case, if there are no closing app targets, then Launcher has nothing to handle notifyAnimationCanceled(); diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index c66813fe8b..c1d7ffa7e0 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -1426,10 +1426,10 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { /** * If task with the given id is on the desktop, bring it to front */ - public void showDesktopApp(int taskId) { + public void showDesktopApp(int taskId, @Nullable RemoteTransition transition) { if (mDesktopMode != null) { try { - mDesktopMode.showDesktopApp(taskId); + mDesktopMode.showDesktopApp(taskId, transition); } catch (RemoteException e) { Log.w(TAG, "Failed call showDesktopApp", e); } @@ -1535,7 +1535,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { * Starts the recents activity. The caller should manage the thread on which this is called. */ public boolean startRecentsActivity(Intent intent, ActivityOptions options, - RecentsAnimationListener listener) { + RecentsAnimationListener listener, boolean useSyntheticRecentsTransition) { if (mRecentTasks == null) { ActiveGestureProtoLogProxy.logRecentTasksMissing(); return false; @@ -1566,6 +1566,9 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { } }; final Bundle optsBundle = options.toBundle(); + if (useSyntheticRecentsTransition) { + optsBundle.putBoolean("is_synthetic_recents_transition", true); + } try { mRecentTasks.startRecentsTransition(mRecentsPendingIntent, intent, optsBundle, mContext.getIApplicationThread(), runner); diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index bda292af01..56c978a318 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -296,8 +296,8 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn // TODO:(b/365777482) if flag is enabled, but on launcher it will crash. if(containerInterface.getCreatedContainer() instanceof RecentsWindowManager && Flags.enableFallbackOverviewInWindow()){ - mRecentsAnimationStartPending = - getSystemUiProxy().startRecentsActivity(intent, options, mCallbacks); + mRecentsAnimationStartPending = getSystemUiProxy().startRecentsActivity(intent, options, + mCallbacks, gestureState.useSyntheticRecentsTransition()); mRecentsWindowsManager.startRecentsWindow(mCallbacks); } else { options.setPendingIntentBackgroundActivityStartMode( @@ -326,9 +326,10 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn }); } - mRecentsAnimationStartPending = getSystemUiProxy() - .startRecentsActivity(intent, options, mCallbacks); + mRecentsAnimationStartPending = getSystemUiProxy().startRecentsActivity(intent, + options, mCallbacks, false /* useSyntheticRecentsTransition */); } + if (enableHandleDelayedGestureCallbacks()) { ActiveGestureProtoLogProxy.logSettingRecentsAnimationStartPending( mRecentsAnimationStartPending); diff --git a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java index 08345b85f6..ab77a7f62c 100644 --- a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java +++ b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java @@ -15,8 +15,14 @@ */ package com.android.quickstep.dagger; +import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl; +import com.android.launcher3.util.PluginManagerWrapper; + +import dagger.Binds; import dagger.Module; @Module -public class QuickStepModule { +public abstract class QuickStepModule { + + @Binds abstract PluginManagerWrapper bindPluginManagerWrapper(PluginManagerWrapperImpl impl); } diff --git a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java index 335161b24c..e82d9fcd1b 100644 --- a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java +++ b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java @@ -19,7 +19,6 @@ package com.android.quickstep.dagger; import com.android.launcher3.dagger.LauncherAppComponent; import com.android.launcher3.dagger.LauncherBaseAppComponent; import com.android.launcher3.model.WellbeingModel; -import com.android.quickstep.logging.SettingsChangeLogger; import com.android.quickstep.util.AsyncClockEventDelegate; import com.android.quickstep.util.ContextualSearchHapticManager; @@ -32,7 +31,6 @@ import com.android.quickstep.util.ContextualSearchHapticManager; * See {@link LauncherAppComponent} for the one actually used. */ public interface QuickstepBaseAppComponent extends LauncherBaseAppComponent { - SettingsChangeLogger getSettingsChangeLogger(); WellbeingModel getWellbeingModel(); diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java index 995635fa6c..dd721e16f6 100644 --- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java +++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java @@ -44,20 +44,16 @@ import androidx.annotation.VisibleForTesting; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.R; import com.android.launcher3.dagger.ApplicationContext; -import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.model.DeviceGridState; -import com.android.launcher3.util.DaggerSingletonObject; -import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; -import com.android.launcher3.util.ExecutorUtil; +import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.NavigationMode; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.util.SettingsCache; -import com.android.quickstep.dagger.QuickstepBaseAppComponent; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -65,12 +61,9 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.Optional; -import javax.inject.Inject; - /** * Utility class to log launcher settings changes */ -@LauncherAppSingleton public class SettingsChangeLogger implements DisplayController.DisplayInfoChangeListener, OnSharedPreferenceChangeListener, SafeCloseable { @@ -78,8 +71,8 @@ public class SettingsChangeLogger implements /** * Singleton instance */ - public static DaggerSingletonObject INSTANCE = - new DaggerSingletonObject<>(QuickstepBaseAppComponent::getSettingsChangeLogger); + public static MainThreadInitializedObject INSTANCE = + new MainThreadInitializedObject<>(SettingsChangeLogger::new); private static final String TAG = "SettingsChangeLogger"; private static final String BOOLEAN_PREF = "SwitchPreference"; @@ -92,31 +85,26 @@ public class SettingsChangeLogger implements private StatsLogManager.LauncherEvent mNotificationDotsEvent; private StatsLogManager.LauncherEvent mHomeScreenSuggestionEvent; - @Inject - SettingsChangeLogger(@ApplicationContext Context context, DaggerSingletonTracker tracker) { - this(context, StatsLogManager.newInstance(context), tracker); + SettingsChangeLogger(@ApplicationContext Context context) { + this(context, StatsLogManager.newInstance(context)); } @VisibleForTesting - SettingsChangeLogger(Context context, StatsLogManager statsLogManager, - DaggerSingletonTracker tracker) { + SettingsChangeLogger(Context context, StatsLogManager statsLogManager) { mContext = context; mStatsLogManager = statsLogManager; mLoggablePrefs = loadPrefKeys(context); - ExecutorUtil.executeSyncOnMainOrFail(() -> { - DisplayController.INSTANCE.get(context).addChangeListener(this); - mNavMode = DisplayController.getNavigationMode(context); + DisplayController.INSTANCE.get(context).addChangeListener(this); + mNavMode = DisplayController.getNavigationMode(context); - getPrefs(context).registerOnSharedPreferenceChangeListener(this); - getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this); + getPrefs(context).registerOnSharedPreferenceChangeListener(this); + getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this); - SettingsCache settingsCache = SettingsCache.INSTANCE.get(context); - settingsCache.register(NOTIFICATION_BADGING_URI, - this::onNotificationDotsChanged); - onNotificationDotsChanged(settingsCache.getValue(NOTIFICATION_BADGING_URI)); - tracker.addCloseable(this); - }); + SettingsCache settingsCache = SettingsCache.INSTANCE.get(context); + settingsCache.register(NOTIFICATION_BADGING_URI, + this::onNotificationDotsChanged); + onNotificationDotsChanged(settingsCache.getValue(NOTIFICATION_BADGING_URI)); } private static ArrayMap loadPrefKeys(Context context) { @@ -223,8 +211,6 @@ public class SettingsChangeLogger implements public void close() { getPrefs(mContext).unregisterOnSharedPreferenceChangeListener(this); getDevicePrefs(mContext).unregisterOnSharedPreferenceChangeListener(this); - SettingsCache settingsCache = SettingsCache.INSTANCE.get(mContext); - settingsCache.unregister(NOTIFICATION_BADGING_URI, this::onNotificationDotsChanged); } @VisibleForTesting diff --git a/quickstep/src/com/android/quickstep/util/DesktopTask.java b/quickstep/src/com/android/quickstep/util/DesktopTask.java index a727aa2efb..fc4fc4df78 100644 --- a/quickstep/src/com/android/quickstep/util/DesktopTask.java +++ b/quickstep/src/com/android/quickstep/util/DesktopTask.java @@ -50,6 +50,11 @@ public class DesktopTask extends GroupTask { @Override public boolean hasMultipleTasks() { + return tasks.size() > 1; + } + + @Override + public boolean supportsMultipleTasks() { return true; } diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java index fba08a96b2..7aeeb2fc32 100644 --- a/quickstep/src/com/android/quickstep/util/GroupTask.java +++ b/quickstep/src/com/android/quickstep/util/GroupTask.java @@ -65,6 +65,13 @@ public class GroupTask { return task2 != null; } + /** + * Returns whether this task supports multiple tasks or not. + */ + public boolean supportsMultipleTasks() { + return taskViewType == TaskViewType.GROUPED; + } + /** * Returns a List of all the Tasks in this GroupTask */ diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index 511c989928..ea582c493f 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -900,7 +900,7 @@ public class SplitSelectStateController { SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()) .startRecentsActivity( mOverviewComponentObserver.getOverviewIntent(), options, - callbacks); + callbacks, false /* useSyntheticRecentsTransition */); }); } diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java index 4c6e4ff359..744c08cc3c 100644 --- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java +++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java @@ -99,7 +99,8 @@ public class SplitWithKeyboardShortcutController { options.setTransientLaunch(); SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()) .startRecentsActivity(mOverviewComponentObserver.getOverviewIntent(), - ActivityOptions.makeBasic(), callbacks); + ActivityOptions.makeBasic(), callbacks, + false /* useSyntheticRecentsTransition */); }); }); } diff --git a/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt b/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt index 5f4388c918..1ff05dae56 100644 --- a/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt +++ b/quickstep/src/com/android/quickstep/util/SystemUiFlagUtils.kt @@ -47,6 +47,22 @@ object SystemUiFlagUtils { !hasAnyFlag(flags, QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY) } + /** + * Taskbar is hidden whenever the device is dreaming. The dreaming state includes the + * interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in when + * the device is asleep, the second condition extends ensures that the transition from and to + * the WAKEFULNESS_ASLEEP state also hide the taskbar, and improves the taskbar hide/reveal + * animation timings. The Taskbar can show when dreaming if the glanceable hub is showing on + * top. + */ + @JvmStatic + fun isTaskbarHidden(@SystemUiStateFlags flags: Long): Boolean { + return ((hasAnyFlag(flags, QuickStepContract.SYSUI_STATE_DEVICE_DREAMING) && + !hasAnyFlag(flags, QuickStepContract.SYSUI_STATE_COMMUNAL_HUB_SHOWING)) || + (flags and QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK) != + QuickStepContract.WAKEFULNESS_AWAKE) + } + private fun hasAnyFlag(@SystemUiStateFlags flags: Long, flagMask: Long): Boolean { return (flags and flagMask) != 0L } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index bccfa0c756..b18af65ece 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1885,19 +1885,22 @@ public abstract class RecentsView< // taskGroups backwards populates the thumbnail grid from least recent to most recent. for (int i = taskGroups.size() - 1; i >= 0; i--) { GroupTask groupTask = taskGroups.get(i); - boolean isRemovalNeeded = stagedTaskIdToBeRemoved != INVALID_TASK_ID + boolean containsStagedTask = stagedTaskIdToBeRemoved != INVALID_TASK_ID && groupTask.containsTask(stagedTaskIdToBeRemoved); + boolean shouldSkipGroupTask = containsStagedTask && !groupTask.hasMultipleTasks(); - if (isRemovalNeeded && !groupTask.hasMultipleTasks()) { - // If the task we need to remove is not part of a pair, avoiding creating the - // TaskView. + if ((isSplitSelectionActive() && groupTask.taskViewType == TaskViewType.DESKTOP) + || shouldSkipGroupTask) { + // To avoid these tasks from being chosen as the app pair, the creation of a + // TaskView is bypassed. The staged task is already selected for the app pair, + // and the Desktop task should be hidden when selecting a pair. continue; } // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE // to be a temporary container for the remaining task. TaskView taskView = getTaskViewFromPool( - isRemovalNeeded ? TaskViewType.SINGLE : groupTask.taskViewType); + containsStagedTask ? TaskViewType.SINGLE : groupTask.taskViewType); if (taskView instanceof GroupedTaskView) { boolean firstTaskIsLeftTopTask = groupTask.mSplitBounds.leftTopTaskId == groupTask.task1.key.id; @@ -5572,15 +5575,13 @@ public abstract class RecentsView< remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator() .addOverviewToAppAnim(mPendingAnimation, interpolator)); mPendingAnimation.addOnFrameCallback(this::redrawLiveTile); - if (taskView instanceof DesktopTaskView && mRemoteTargetHandles != null) { - mPendingAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - runActionOnRemoteHandles(remoteTargetHandle -> - remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false)); - } - }); - } + mPendingAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + runActionOnRemoteHandles(remoteTargetHandle -> + remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false)); + } + }); mPendingAnimation.addEndListener(isSuccess -> { if (isSuccess) { if (taskView instanceof GroupedTaskView && hasAllValidTaskIds(taskView.getTaskIds()) @@ -5612,6 +5613,13 @@ public abstract class RecentsView< protected Unit onTaskLaunchAnimationEnd(boolean success) { if (success) { resetTaskVisuals(); + } else { + // If launch animation didn't complete i.e. user dragged live tile down and then + // back up and returned to Overview, then we need to ensure we reset the + // view to draw below recents so that it can't be interacted with. + runActionOnRemoteHandles(remoteTargetHandle -> + remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(true)); + redrawLiveTile(); } return Unit.INSTANCE; } diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt index 0a607744d0..7c48ea489c 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt @@ -34,7 +34,6 @@ import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVI import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_ENABLED import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_THEMED_ICON_DISABLED import com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY -import com.android.launcher3.util.DaggerSingletonTracker import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before @@ -63,7 +62,6 @@ class SettingsChangeLoggerTest { @Mock private lateinit var mMockLogger: StatsLogManager.StatsLogger @Captor private lateinit var mEventCaptor: ArgumentCaptor - @Mock private lateinit var mTracker: DaggerSingletonTracker private var mDefaultThemedIcons = false private var mDefaultAllowRotation = false @@ -81,7 +79,7 @@ class SettingsChangeLoggerTest { // To match the default value of ALLOW_ROTATION LauncherPrefs.get(mContext).put(item = ALLOW_ROTATION, value = false) - mSystemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager, mTracker) + mSystemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager) } @After @@ -92,7 +90,7 @@ class SettingsChangeLoggerTest { @Test fun loggingPrefs_correctDefaultValue() { - val systemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager, mTracker) + val systemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager) assertThat(systemUnderTest.loggingPrefs[ALLOW_ROTATION_PREFERENCE_KEY]!!.defaultValue) .isFalse() @@ -119,7 +117,7 @@ class SettingsChangeLoggerTest { LauncherPrefs.get(mContext).put(item = ALLOW_ROTATION, value = true) // This a new object so the values of mLoggablePrefs will be different - SettingsChangeLogger(mContext, mStatsLogManager, mTracker).logSnapshot(mInstanceId) + SettingsChangeLogger(mContext, mStatsLogManager).logSnapshot(mInstanceId) verify(mMockLogger, atLeastOnce()).log(mEventCaptor.capture()) val capturedEvents = mEventCaptor.allValues diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java index 800fd4aa93..b15b78e305 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java @@ -56,8 +56,6 @@ public class TaplPrivateSpaceTest extends AbstractQuickStepTest { @Override public void setUp() throws Exception { super.setUp(); - initialize(this); - createAndStartPrivateProfileUser(); mDevice.pressHome(); diff --git a/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java b/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java index ec07b9310e..633a5756c2 100644 --- a/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java +++ b/quickstep/tests/src/com/android/quickstep/TaskAnimationManagerTest.java @@ -17,8 +17,8 @@ package com.android.quickstep; import static org.junit.Assert.assertEquals; -import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -73,7 +73,8 @@ public class TaskAnimationManagerTest { final ArgumentCaptor optionsCaptor = ArgumentCaptor.forClass(ActivityOptions.class); - verify(mSystemUiProxy).startRecentsActivity(any(), optionsCaptor.capture(), any()); + verify(mSystemUiProxy) + .startRecentsActivity(any(), optionsCaptor.capture(), any(), anyBoolean()); assertEquals(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS, optionsCaptor.getValue().getPendingIntentBackgroundActivityStartMode()); } diff --git a/quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt b/quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt new file mode 100644 index 0000000000..e5e6df3b1e --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/desktop/WindowAnimatorTest.kt @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep.desktop + +import android.animation.ValueAnimator +import android.content.Context +import android.content.res.Resources +import android.graphics.Rect +import android.util.DisplayMetrics +import android.view.SurfaceControl +import android.window.TransitionInfo +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread +import com.android.app.animation.Interpolators +import com.android.launcher3.desktop.WindowAnimator +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyFloat +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +@SmallTest +@RunWith(AndroidJUnit4::class) +class WindowAnimatorTest { + + private val context = mock() + private val resources = mock() + private val transaction = mock() + private val change = mock() + private val leash = mock() + + private val displayMetrics = DisplayMetrics().apply { density = 1f } + + @Before + fun setup() { + whenever(context.resources).thenReturn(resources) + whenever(resources.displayMetrics).thenReturn(displayMetrics) + whenever(change.leash).thenReturn(leash) + whenever(change.startAbsBounds).thenReturn(START_BOUNDS) + whenever(transaction.setPosition(any(), anyFloat(), anyFloat())).thenReturn(transaction) + whenever(transaction.setScale(any(), anyFloat(), anyFloat())).thenReturn(transaction) + } + + @Test + fun createBoundsAnimator_returnsCorrectDefaultAnimatorParams() = runOnUiThread { + val boundsAnimParams = + WindowAnimator.BoundsAnimationParams( + durationMs = 100L, + interpolator = Interpolators.STANDARD_ACCELERATE, + ) + + val valueAnimator = + WindowAnimator.createBoundsAnimator(context, boundsAnimParams, change, transaction) + + assertThat(valueAnimator.duration).isEqualTo(100L) + assertThat(valueAnimator.interpolator).isEqualTo(Interpolators.STANDARD_ACCELERATE) + assertStartAndEndBounds(valueAnimator, startBounds = START_BOUNDS, endBounds = START_BOUNDS) + } + + @Test + fun createBoundsAnimator_startScaleAndOffset_returnsCorrectBounds() = runOnUiThread { + val bounds = Rect(/* left= */ 100, /* top= */ 200, /* right= */ 300, /* bottom= */ 400) + whenever(change.startAbsBounds).thenReturn(bounds) + val boundsAnimParams = + WindowAnimator.BoundsAnimationParams( + durationMs = 100L, + startOffsetYDp = 10f, + startScale = 0.5f, + interpolator = Interpolators.STANDARD_ACCELERATE, + ) + + val valueAnimator = + WindowAnimator.createBoundsAnimator(context, boundsAnimParams, change, transaction) + + assertStartAndEndBounds( + valueAnimator, + startBounds = + Rect(/* left= */ 150, /* top= */ 260, /* right= */ 250, /* bottom= */ 360), + endBounds = bounds, + ) + } + + @Test + fun createBoundsAnimator_endScaleAndOffset_returnsCorrectBounds() = runOnUiThread { + val bounds = Rect(/* left= */ 100, /* top= */ 200, /* right= */ 300, /* bottom= */ 400) + whenever(change.startAbsBounds).thenReturn(bounds) + val boundsAnimParams = + WindowAnimator.BoundsAnimationParams( + durationMs = 100L, + endOffsetYDp = 10f, + endScale = 0.5f, + interpolator = Interpolators.STANDARD_ACCELERATE, + ) + + val valueAnimator = + WindowAnimator.createBoundsAnimator(context, boundsAnimParams, change, transaction) + + assertStartAndEndBounds( + valueAnimator, + startBounds = bounds, + endBounds = Rect(/* left= */ 150, /* top= */ 260, /* right= */ 250, /* bottom= */ 360), + ) + } + + private fun assertStartAndEndBounds( + valueAnimator: ValueAnimator, + startBounds: Rect, + endBounds: Rect, + ) { + valueAnimator.start() + valueAnimator.animatedValue + assertThat(valueAnimator.animatedValue).isEqualTo(startBounds) + valueAnimator.end() + assertThat(valueAnimator.animatedValue).isEqualTo(endBounds) + } + + companion object { + private val START_BOUNDS = + Rect(/* left= */ 10, /* top= */ 20, /* right= */ 30, /* bottom= */ 40) + } +} diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 9211e7640d..0d78d9032d 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -174,7 +174,7 @@ "Genveje" "Afvis" "Luk" - "Personlige" + "Personlig" "Arbejde" "Arbejdsprofil" "Arbejdsapps har badges og kan ses af din it-administrator" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 0c46eb43e5..786cea1e58 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -21,7 +21,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Launcher3" "ಕೆಲಸ" - "ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ" + "ಆ್ಯಪ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ" "ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ" "ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾದ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" "ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" @@ -103,7 +103,7 @@ "ವಿಜೆಟ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ" "ವಿಜೆಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ಸೆಟಪ್ ಪೂರ್ಣಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" - "ಇದೊಂದು ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." + "ಇದೊಂದು ಆ್ಯಪ್‌ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." "ಹೆಸರನ್ನು ಎಡಿಟ್ ಮಾಡಿ" "%1$s ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" "{count,plural, =1{{app_name} ಆ್ಯಪ್ # ಅಧಿಸೂಚನೆಯನ್ನು ಹೊಂದಿದೆ}one{{app_name} ಆ್ಯಪ್ # ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ}other{{app_name} ಆ್ಯಪ್ # ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ}}" diff --git a/res/values/config.xml b/res/values/config.xml index 701e64a4b4..504218b78e 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -85,7 +85,6 @@ - diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index afe0ee1967..886255094f 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -2355,18 +2355,23 @@ public class DeviceProfile { /** * Returns whether Taskbar and Hotseat should adjust horizontally on bubble bar location update. */ - public boolean shouldAdjustHotseatOnBubblesLocationUpdate(Context context) { + public boolean shouldAdjustHotseatOnNavBarLocationUpdate(Context context) { return enableBubbleBar() && enableBubbleBarInPersistentTaskBar() && !DisplayController.getNavigationMode(context).hasGestures; } /** Returns hotseat translation X for the bubble bar position. */ - public int getHotseatTranslationXForBubbleBar(boolean isNavbarOnRight, boolean isRtl) { - if (isNavbarOnRight) { - return isRtl ? -navButtonsLayoutWidthPx : 0; + public int getHotseatTranslationXForNavBar(Context context, boolean isBubblesOnLeft) { + if (shouldAdjustHotseatOnNavBarLocationUpdate(context)) { + boolean isRtl = Utilities.isRtl(context.getResources()); + if (isBubblesOnLeft) { + return isRtl ? -navButtonsLayoutWidthPx : 0; + } else { + return isRtl ? 0 : navButtonsLayoutWidthPx; + } } else { - return isRtl ? 0 : navButtonsLayoutWidthPx; + return 0; } } diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index 6a401215f1..9c36dc2751 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -474,7 +474,8 @@ public class PrivateProfileManager extends UserProfileManager { break; } // Make the private space apps gone to "collapse". - if (mFloatingMaskView == null && isPrivateSpaceItem(currentItem)) { + if ((mFloatingMaskView == null && isPrivateSpaceItem(currentItem)) || + currentItem.viewType == VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER) { RecyclerView.ViewHolder viewHolder = allAppsRecyclerView.findViewHolderForAdapterPosition(i); if (viewHolder != null) { diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index c3508b77db..4da7c2716a 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -20,6 +20,7 @@ import android.content.Context; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.util.DaggerSingletonTracker; +import com.android.launcher3.util.PluginManagerWrapper; import com.android.launcher3.util.ScreenOnTracker; import com.android.launcher3.util.SettingsCache; import com.android.launcher3.widget.custom.CustomWidgetManager; @@ -40,6 +41,7 @@ public interface LauncherBaseAppComponent { ScreenOnTracker getScreenOnTracker(); SettingsCache getSettingsCache(); CustomWidgetManager getCustomWidgetManager(); + PluginManagerWrapper getPluginManagerWrapper(); /** Builder for LauncherBaseAppComponent. */ interface Builder { diff --git a/src/com/android/launcher3/util/PluginManagerWrapper.java b/src/com/android/launcher3/util/PluginManagerWrapper.java index b27aa120b9..5b28570acb 100644 --- a/src/com/android/launcher3/util/PluginManagerWrapper.java +++ b/src/com/android/launcher3/util/PluginManagerWrapper.java @@ -15,32 +15,39 @@ */ package com.android.launcher3.util; -import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; +import androidx.annotation.AnyThread; -import com.android.launcher3.R; +import com.android.launcher3.dagger.LauncherAppSingleton; +import com.android.launcher3.dagger.LauncherBaseAppComponent; import com.android.systemui.plugins.Plugin; import com.android.systemui.plugins.PluginListener; import java.io.PrintWriter; -public class PluginManagerWrapper implements ResourceBasedOverride, SafeCloseable { +import javax.inject.Inject; - public static final MainThreadInitializedObject INSTANCE = - forOverride(PluginManagerWrapper.class, R.string.plugin_manager_wrapper_class); +@LauncherAppSingleton +public class PluginManagerWrapper{ + public static final DaggerSingletonObject INSTANCE = + new DaggerSingletonObject<>(LauncherBaseAppComponent::getPluginManagerWrapper); + + @Inject + public PluginManagerWrapper() { } + + @AnyThread public void addPluginListener( PluginListener listener, Class pluginClass) { addPluginListener(listener, pluginClass, false); } + @AnyThread public void addPluginListener( PluginListener listener, Class pluginClass, boolean allowMultiple) { } + @AnyThread public void removePluginListener(PluginListener listener) { } - @Override - public void close() { } - public void dump(PrintWriter pw) { } } diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java index 0778172127..4aeac7639a 100644 --- a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java +++ b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java @@ -41,7 +41,6 @@ import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.ExecutorUtil; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.PluginManagerWrapper; -import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.widget.LauncherAppWidgetHostView; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.systemui.plugins.CustomWidgetPlugin; @@ -61,7 +60,7 @@ import javax.inject.Inject; * CustomWidgetManager handles custom widgets implemented as a plugin. */ @LauncherAppSingleton -public class CustomWidgetManager implements PluginListener, SafeCloseable { +public class CustomWidgetManager implements PluginListener { public static final DaggerSingletonObject INSTANCE = new DaggerSingletonObject<>(LauncherBaseAppComponent::getCustomWidgetManager); @@ -75,12 +74,14 @@ public class CustomWidgetManager implements PluginListener, private final @NonNull AppWidgetManager mAppWidgetManager; @Inject - CustomWidgetManager(@ApplicationContext Context context, DaggerSingletonTracker tracker) { - this(context, AppWidgetManager.getInstance(context), tracker); + CustomWidgetManager(@ApplicationContext Context context, PluginManagerWrapper pluginManager, + DaggerSingletonTracker tracker) { + this(context, pluginManager, AppWidgetManager.getInstance(context), tracker); } @VisibleForTesting CustomWidgetManager(@ApplicationContext Context context, + PluginManagerWrapper pluginManager, @NonNull AppWidgetManager widgetManager, DaggerSingletonTracker tracker) { mContext = context; @@ -88,11 +89,9 @@ public class CustomWidgetManager implements PluginListener, mPlugins = new HashMap<>(); mCustomWidgets = new ArrayList<>(); + pluginManager.addPluginListener(this, CustomWidgetPlugin.class, true); ExecutorUtil.executeSyncOnMainOrFail(() -> { - PluginManagerWrapper.INSTANCE.get(context) - .addPluginListener(this, CustomWidgetPlugin.class, true); - if (enableSmartspaceAsAWidget()) { for (String s: context.getResources() .getStringArray(R.array.custom_widget_providers)) { @@ -110,15 +109,10 @@ public class CustomWidgetManager implements PluginListener, } } - tracker.addCloseable(this); + tracker.addCloseable(() -> pluginManager.removePluginListener(this)); }); } - @Override - public void close() { - PluginManagerWrapper.INSTANCE.get(mContext).removePluginListener(this); - } - @Override public void onPluginConnected(CustomWidgetPlugin plugin, Context context) { List providers = mAppWidgetManager diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java index 4e9143e050..825b52b5fb 100644 --- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java +++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java @@ -167,7 +167,6 @@ public final class TestProtocol { public static final String PERMANENT_DIAG_TAG = "TaplTarget"; public static final String ICON_MISSING = "b/282963545"; - public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890"; public static final String REQUEST_FLAG_ENABLE_GRID_ONLY_OVERVIEW = "enable-grid-only-overview"; public static final String REQUEST_FLAG_ENABLE_APP_PAIRS = "enable-app-pairs"; diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt index 82f56b8c2e..1c25db92be 100644 --- a/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/widget/custom/CustomWidgetManagerTest.kt @@ -26,17 +26,19 @@ import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import com.android.launcher3.util.DaggerSingletonTracker import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext import com.android.launcher3.util.PluginManagerWrapper +import com.android.launcher3.util.SafeCloseable import com.android.launcher3.util.WidgetUtils import com.android.launcher3.widget.LauncherAppWidgetHostView import com.android.launcher3.widget.LauncherAppWidgetProviderInfo import com.android.systemui.plugins.CustomWidgetPlugin -import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations @@ -60,16 +62,12 @@ class CustomWidgetManagerTest { @Mock private lateinit var mockAppWidgetManager: AppWidgetManager @Mock private lateinit var tracker: DaggerSingletonTracker + @Captor private lateinit var closableCaptor: ArgumentCaptor + @Before fun setUp() { MockitoAnnotations.initMocks(this) - context.putObject(PluginManagerWrapper.INSTANCE, pluginManager) - underTest = CustomWidgetManager(context, mockAppWidgetManager, tracker) - } - - @After - fun tearDown() { - underTest.close() + underTest = CustomWidgetManager(context, pluginManager, mockAppWidgetManager, tracker) } @Test @@ -80,7 +78,8 @@ class CustomWidgetManagerTest { @Test fun close_widget_manager_should_remove_plugin_listener() { - underTest.close() + verify(tracker).addCloseable(closableCaptor.capture()) + closableCaptor.allValues.forEach(SafeCloseable::close) verify(pluginManager).removePluginListener(same(underTest)) } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index cee88ac047..4ca6da8a47 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -20,7 +20,6 @@ import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType import static androidx.test.InstrumentationRegistry.getInstrumentation; import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING; -import static com.android.launcher3.testing.shared.TestProtocol.WIDGET_CONFIG_NULL_EXTRA_INTENT; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static org.junit.Assert.assertEquals; @@ -415,6 +414,7 @@ public abstract class AbstractLauncherUiTest { public void verifyLauncherState() { try { // Limits UI tests affecting tests running after them. + mDevice.pressHome(); mLauncher.waitForLauncherInitialized(); if (mLauncherPid != 0) { assertEquals("Launcher crashed, pid mismatch:", @@ -563,23 +563,13 @@ public abstract class AbstractLauncherUiTest { @Override public void onReceive(Context context, Intent intent) { - Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, intent == null - ? "AbstractLauncherUiTest.onReceive(): inputted intent NULL" - : "AbstractLauncherUiTest.onReceive(): inputted intent NOT NULL"); mIntent = intent; latch.countDown(); - Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, - "AbstractLauncherUiTest.onReceive() Countdown Latch started"); } public Intent blockingGetIntent() throws InterruptedException { - Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, - "AbstractLauncherUiTest.blockingGetIntent()"); assertTrue("Timed Out", latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS)); mTargetContext.unregisterReceiver(this); - Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, mIntent == null - ? "AbstractLauncherUiTest.onReceive(): mIntent NULL" - : "AbstractLauncherUiTest.onReceive(): mIntent NOT NULL"); return mIntent; } diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java index b38dd4ba11..a45e3bbb84 100644 --- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java +++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java @@ -70,7 +70,6 @@ public class TaplWorkProfileTest extends AbstractLauncherUiTest { @Override public void setUp() throws Exception { super.setUp(); - initialize(this); String output = mDevice.executeShellCommand( "pm create-user --profileOf 0 --managed TestProfile"); diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java index 490cff20b4..237f2a97a7 100644 --- a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java +++ b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java @@ -32,7 +32,6 @@ import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; import org.junit.After; -import org.junit.Before; import org.junit.Test; /** @@ -50,12 +49,6 @@ public class TaplWorkspaceTest extends AbstractLauncherUiTest { return launcher.getWorkspace().getCurrentPage(); } - @Before - public void setUp() throws Exception { - super.setUp(); - initialize(this); - } - @After public void tearDown() throws Exception { if (mLauncherLayout != null) {