From 9d8eeabfecb85ce88f492f9960c1b68d086528a2 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Tue, 5 Apr 2022 17:13:56 +0100 Subject: [PATCH 01/15] Reset touch state when removing all tasks in RecentsView.applyLoadPlan Fix: 223245248 Test: com.android.quickstep.FallbackRecentsTest#goToOverviewFromHome Change-Id: I1cc8952e077b9cc79a93d909b80e215e61e8deab --- quickstep/src/com/android/quickstep/views/RecentsView.java | 3 +++ src/com/android/launcher3/PagedView.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 25f8f01a3b..4317d55c33 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1390,6 +1390,9 @@ public abstract class RecentsView extends ViewGrou return Math.abs(velocity) > threshold; } - private void resetTouchState() { + protected void resetTouchState() { releaseVelocityTracker(); mIsBeingDragged = false; mActivePointerId = INVALID_POINTER; From a7572a77d646ab0e1ce23029fb983f86979a93f7 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 19 Apr 2022 19:04:37 +0000 Subject: [PATCH 02/15] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I99b021e480994659cd0a29f18d6e315d8daff052 --- res/values-ar/strings.xml | 2 +- res/values-b+sr+Latn/strings.xml | 2 +- res/values-cs/strings.xml | 4 ++-- res/values-en-rXC/strings.xml | 12 ++++-------- res/values-es/strings.xml | 8 ++++---- res/values-gu/strings.xml | 6 +++--- res/values-iw/strings.xml | 6 +++--- res/values-nb/strings.xml | 2 +- res/values-sr/strings.xml | 2 +- 9 files changed, 20 insertions(+), 24 deletions(-) diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index ae190c5db9..774977ce3f 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -32,7 +32,7 @@ "تقسيم لليسار" "تقسيم لليمين" "‏معلومات تطبيق %1$s" - "انقر مع الاستمرار لنقل أداة" + "انقر مع الاستمرار لنقل أداة." "انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة." "%1$d × %2$d" "‏العرض %1$d الطول %2$d" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 49b34dd8f7..ddcb256753 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -47,7 +47,7 @@ "Pretražite" "Obrišite tekst iz okvira za pretragu" "Vidžeti i prečice nisu dostupni" - "Nije pronađen nijedan vidžet ili prečica" + "Nije pronađen nijedan vidžet ni prečica" "Lično" "Posao" "Konverzacije" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 82031a69b5..3b38e62286 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -32,7 +32,7 @@ "Rozdělit vlevo" "Rozdělit vpravo" "Informace o aplikaci %1$s" - "Klepnutím a podržením přesunete widget." + "Widget přesunete klepnutím a podržením." "Dvojitým klepnutím a podržením přesunete widget, případně použijte vlastní akce." "%1$d × %2$d" "šířka %1$d, výška %2$d" @@ -164,7 +164,7 @@ "Osobní" "Pracovní" "Pracovní profil" - "Pracovní aplikace jsou označené a viditelné vašemu administrátorovi IT" + "Pracovní aplikace jsou označené a váš administrátor IT je vidí" "Rozumím" "Pracovní aplikace jsou pozastaveny" "Pracovní aplikace vám nemohou zasílat oznámení, používat vaši baterii ani získat přístup k vaší poloze" diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index e5eeb3b1df..90cd6cd498 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -124,14 +124,10 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ installing, ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ complete‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ downloading, ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ complete‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ waiting to install‎‏‎‎‏‎" - - - - - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎App update required‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎The app for this icon isn\'t updated. You can update manually to re-enable this shortcut, or remove the icon.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‎‎Update‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎Remove‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎Widgets list‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎Widgets list closed‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎Add to home screen‎‏‎‎‏‎" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 8572b6716e..a6f07da11b 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -23,8 +23,8 @@ "Trabajo" "La aplicación no está instalada." "La aplicación no está disponible" - "Aplicación descargada inhabilitada en modo seguro" - "Widgets inhabilitados en modo seguro" + "Aplicación descargada inhabilitada en modo Seguro" + "Widgets inhabilitados en modo Seguro" "Acceso directo no disponible" "Inicio" "Pantalla dividida" @@ -32,7 +32,7 @@ "Dividir parte izquierda" "Dividir parte derecha" "Información de la aplicación %1$s" - "Mantén pulsado un widget para moverlo." + "Mantén pulsado un widget para moverlo" "Toca dos veces y mantén pulsado un widget para moverlo o usar acciones personalizadas." "%1$d × %2$d" "%1$d de ancho por %2$d de alto" @@ -41,7 +41,7 @@ "Añadir a pantalla de inicio" "Widget %1$s añadido a la pantalla de inicio" "{count,plural, =1{# widget}other{# widgets}}" - "{count,plural, =1{# combinación de teclas}other{# combinaciones de teclas}}" + "{count,plural, =1{# acceso directo}other{# accesos directos}}" "%1$s, %2$s" "Widgets" "Buscar" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index fabe73c868..b2d2654a53 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -164,12 +164,12 @@ "મનગમતી ઍપ" "ઑફિસની ઍપ" "ઑફિસની પ્રોફાઇલ" - "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT વ્યવસ્થાપક તેમને જોઈ શકે છે" + "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT ઍડમિન તેમને જોઈ શકે છે" "સમજાઈ ગયું" - "ઑફિસ માટેની ઍપ થોભાવવામાં આવેલ છે" + "ઑફિસ માટેની ઍપ થોભાવવામાં આવી છે" "ઑફિસ માટેની તમારી ઍપ તમને નોટિફિકેશન મોકલી શકતી નથી, તમારી બૅટરી વાપરી શકતી નથી કે તમારું સ્થાન ઍક્સેસ કરી શકતી નથી" "ઑફિસ માટેની ઍપ બંધ છે. ઑફિસ માટેની તમારી ઍપ તમને નોટિફિકેશન મોકલી શકતી નથી, તમારી બૅટરી વાપરી શકતી નથી કે તમારું સ્થાન ઍક્સેસ કરી શકતી નથી" - "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT વ્યવસ્થાપક તેમને જોઈ શકે છે" + "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT ઍડમિન તેમને જોઈ શકે છે" "સમજાઈ ગયું" "ઑફિસ માટેની ઍપ બંધ કરો" "ઑફિસ માટેની ઍપ ચાલુ કરો" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 9f216968cc..0aa3f11479 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -32,7 +32,7 @@ "פיצול שמאלה" "פיצול ימינה" "‏פרטים על האפליקציה %1$s" - "כדי להעביר ווידג\'ט למקום אחר יש לגעת ולא להרפות." + "להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה." "כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות." "%1$d × %2$d" "‏רוחב %1$d על גובה %2$d" @@ -161,7 +161,7 @@ "סגירה" "סגירה" "ההתראה נסגרה" - "אישיות" + "אישי" "עבודה" "פרופיל עבודה" "‏האפליקציות לעבודה מתויגות ומוצגות למנהל ה-IT" @@ -171,7 +171,7 @@ "האפליקציות לעבודה מושבתות. האפליקציות לא יכולות לשלוח לך התראות, להשתמש בסוללה או לגשת למיקום שלך" "‏האפליקציות לעבודה מתויגות ומוצגות למנהל ה-IT" "הבנתי" - "כיבוי של אפליקציות לעבודה" + "השבתה של אפליקציות לעבודה" "הפעלה של אפליקציות לעבודה" "סינון" "הפעולה נכשלה: %1$s" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 8ce6c7341a..416f2042d9 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -164,7 +164,7 @@ "Personlig" "Jobb" "Jobbprofil" - "Jobbapper er merket og synlige for IT-administratoren din" + "Jobbapper er merket og synlige for IT-administratoren" "Greit" "Jobbapper er satt på pause" "Jobbapper kan ikke sende deg varsler, bruke batteriet eller få tilgang til posisjonen din" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 5553e8c97a..6b5fe2bba0 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -47,7 +47,7 @@ "Претражите" "Обришите текст из оквира за претрагу" "Виџети и пречице нису доступни" - "Није пронађен ниједан виџет или пречица" + "Није пронађен ниједан виџет ни пречица" "Лично" "Посао" "Конверзације" From 3946ecd4418a795fa37a9a2c12cc50cd3568ffd3 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 20 Apr 2022 09:51:48 -0700 Subject: [PATCH 03/15] Removing some unused code from All-Apps Bug: 229860311 Test: Verified on device Change-Id: I72394fb421679688f87cdbf725859ec35529a59e --- src/com/android/launcher3/BubbleTextView.java | 27 ++---- .../allapps/AlphabeticalAppsList.java | 95 +++++++++++-------- .../launcher3/allapps/BaseAllAppsAdapter.java | 38 ++++---- .../allapps/BaseAllAppsContainerView.java | 7 ++ .../launcher3/allapps/DecorationInfo.java | 19 ---- .../search/DefaultAppSearchAlgorithm.java | 2 +- src/com/android/launcher3/util/Executors.java | 14 +-- 7 files changed, 95 insertions(+), 107 deletions(-) delete mode 100644 src/com/android/launcher3/allapps/DecorationInfo.java diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 74ec7ee327..6302739bc5 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -96,7 +96,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private static final int MAX_SEARCH_LOOP_COUNT = 20; private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed}; - private static final float HIGHLIGHT_SCALE = 1.16f; private final PointF mTranslationForReorderBounce = new PointF(0, 0); private final PointF mTranslationForReorderPreview = new PointF(0, 0); @@ -259,6 +258,12 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, mDotParams.scale = 0f; mForceHideDot = false; setBackground(null); + + setTag(null); + if (mIconLoadRequest != null) { + mIconLoadRequest.cancel(); + mIconLoadRequest = null; + } } private void cancelDotScaleAnim() { @@ -363,8 +368,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } } - public void setBubbleTextHolder( - BubbleTextHolder bubbleTextHolder) { + public void setBubbleTextHolder(BubbleTextHolder bubbleTextHolder) { mBubbleTextHolder = bubbleTextHolder; } @@ -1020,19 +1024,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, getIconBounds(mIconSize, bounds); } - private int getIconSizeForDisplay(int display) { - DeviceProfile grid = mActivity.getDeviceProfile(); - switch (display) { - case DISPLAY_ALL_APPS: - return grid.allAppsIconSizePx; - case DISPLAY_FOLDER: - return grid.folderChildIconSizePx; - case DISPLAY_WORKSPACE: - default: - return grid.iconSizePx; - } - } - public void getSourceVisualDragBounds(Rect bounds) { getIconBounds(mIconSize, bounds); } @@ -1045,8 +1036,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } private void resetIconScale() { - if (mIcon instanceof FastBitmapDrawable) { - ((FastBitmapDrawable) mIcon).resetScale(); + if (mIcon != null) { + mIcon.resetScale(); } } diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 7687fea85d..00156b1f8d 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -18,6 +18,9 @@ package com.android.launcher3.allapps; import android.content.Context; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.DiffUtil.DiffResult; + import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; @@ -43,10 +46,6 @@ public class AlphabeticalAppsList implement public static final String TAG = "AlphabeticalAppsList"; - private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION = 0; - private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1; - - private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS; private final WorkAdapterProvider mWorkAdapterProvider; /** @@ -198,8 +197,11 @@ public class AlphabeticalAppsList implement public boolean appendSearchResults(ArrayList results) { if (hasFilter() && results != null && results.size() > 0) { - updateSearchAdapterItems(results, mSearchResults.size()); - refreshRecyclerView(); + int pos = mSearchResults.size(); + updateSearchAdapterItems(results, pos); + if (mAdapter != null) { + mAdapter.notifyItemRangeInserted(pos, results.size()); + } return true; } return false; @@ -273,10 +275,6 @@ public class AlphabeticalAppsList implement */ public void updateAdapterItems() { refillAdapterItems(); - refreshRecyclerView(); - } - - private void refreshRecyclerView() { if (mAdapter != null) { mAdapter.notifyDataSetChanged(); } @@ -286,9 +284,9 @@ public class AlphabeticalAppsList implement String lastSectionName = null; FastScrollSectionInfo lastFastScrollerSectionInfo = null; int position = 0; - int appIndex = 0; // Prepare to update the list of sections, filtered apps, etc. + ArrayList oldList = new ArrayList<>(mAdapterItems); mAccessibilityResultsCount = 0; mFastScrollerSections.clear(); mAdapterItems.clear(); @@ -315,8 +313,7 @@ public class AlphabeticalAppsList implement } // Create an app item - AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, - appIndex++); + AdapterItem appItem = AdapterItem.asApp(position++, info); if (lastFastScrollerSectionInfo.fastScrollToItem == null) { lastFastScrollerSectionInfo.fastScrollToItem = appItem; } @@ -342,6 +339,7 @@ public class AlphabeticalAppsList implement int numAppsInSection = 0; int numAppsInRow = 0; int rowIndex = -1; + for (AdapterItem item : mAdapterItems) { item.rowIndex = 0; if (BaseAllAppsAdapter.isDividerViewType(item.viewType)) { @@ -360,35 +358,50 @@ public class AlphabeticalAppsList implement mNumAppRowsInAdapter = rowIndex + 1; // Pre-calculate all the fast scroller fractions - switch (mFastScrollDistributionMode) { - case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION: - float rowFraction = 1f / mNumAppRowsInAdapter; - for (FastScrollSectionInfo info : mFastScrollerSections) { - AdapterItem item = info.fastScrollToItem; - if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) { - info.touchFraction = 0f; - continue; - } - - float subRowFraction = - item.rowAppIndex * (rowFraction / mNumAppsPerRowAllApps); - info.touchFraction = item.rowIndex * rowFraction + subRowFraction; - } - break; - case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS: - float perSectionTouchFraction = 1f / mFastScrollerSections.size(); - float cumulativeTouchFraction = 0f; - for (FastScrollSectionInfo info : mFastScrollerSections) { - AdapterItem item = info.fastScrollToItem; - if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) { - info.touchFraction = 0f; - continue; - } - info.touchFraction = cumulativeTouchFraction; - cumulativeTouchFraction += perSectionTouchFraction; - } - break; + float perSectionTouchFraction = 1f / mFastScrollerSections.size(); + float cumulativeTouchFraction = 0f; + for (FastScrollSectionInfo info : mFastScrollerSections) { + AdapterItem item = info.fastScrollToItem; + if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) { + info.touchFraction = 0f; + continue; + } + info.touchFraction = cumulativeTouchFraction; + cumulativeTouchFraction += perSectionTouchFraction; } } + + DiffResult result = DiffUtil.calculateDiff(new DiffCallback(oldList, mAdapterItems)); + } + + private static class DiffCallback extends DiffUtil.Callback { + private final List mOldItems; + private final List mNewItems; + + DiffCallback(List oldItems, List newItems) { + mOldItems = oldItems; + mNewItems = newItems; + } + + @Override + public int getOldListSize() { + return mOldItems.size(); + } + + @Override + public int getNewListSize() { + return mNewItems.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + return mOldItems.get(oldItemPosition).getStableId() + == mNewItems.get(newItemPosition).getStableId(); + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + return mOldItems.get(oldItemPosition).isContentSame(mNewItems.get(newItemPosition)); + } } } diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java index 976284d947..e912cf22da 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java @@ -36,7 +36,6 @@ import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; -import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.views.ActivityContext; import java.util.Arrays; @@ -94,31 +93,21 @@ public abstract class BaseAllAppsAdapter ex // The type of this item public int viewType; - // The section name of this item. Note that there can be multiple items with different - // sectionNames in the same section - public String sectionName = null; // The row that this item shows up on public int rowIndex; // The index of this app in the row public int rowAppIndex; // The associated ItemInfoWithIcon for the item - public ItemInfoWithIcon itemInfo = null; - // The index of this app not including sections - public int appIndex = -1; - // Search section associated to result - public DecorationInfo decorationInfo = null; + public AppInfo itemInfo = null; /** * Factory method for AppIcon AdapterItem */ - public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, - int appIndex) { + public static AdapterItem asApp(int pos, AppInfo appInfo) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ICON; item.position = pos; - item.sectionName = sectionName; item.itemInfo = appInfo; - item.appIndex = appIndex; return item; } @@ -155,6 +144,23 @@ public abstract class BaseAllAppsAdapter ex protected boolean isCountedForAccessibility() { return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_MARKET; } + + public long getStableId() { + return viewType; + } + + /** + * Called to check if the content of the item is same as the other item. This is called only + * if the {@link #getStableId()} matches for both the items. + */ + public boolean isContentSame(AdapterItem other) { + // We can use itemInfo for diff, but since ItemInfo objects are singleton per Model, + // this could prevent updates within this itemInfo object itself (like title change + // or flag changes). We can create a better diffing logic if we store a clone a snapshot + // of the itemInfo, but that would cause icons to be loaded lazily on the cloned object + // instead of the singleton object. + return false; + } } protected final T mActivityContext; @@ -267,11 +273,7 @@ public abstract class BaseAllAppsAdapter ex AdapterItem adapterItem = mApps.getAdapterItems().get(position); BubbleTextView icon = (BubbleTextView) holder.itemView; icon.reset(); - if (adapterItem.itemInfo instanceof AppInfo) { - icon.applyFromApplicationInfo((AppInfo) adapterItem.itemInfo); - } else { - icon.applyFromItemInfoWithIcon(adapterItem.itemInfo); - } + icon.applyFromApplicationInfo(adapterItem.itemInfo); break; case VIEW_TYPE_EMPTY_SEARCH: TextView emptyViewText = (TextView) holder.itemView; diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index f913aa9093..31c0c69355 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -45,6 +45,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.DeviceProfileListenable; @@ -727,6 +728,12 @@ public abstract class BaseAllAppsContainerView { for (int i = 0; i < total && resultCount < MAX_RESULTS_COUNT; i++) { AppInfo info = apps.get(i); if (StringMatcherUtility.matches(queryTextLower, info.title.toString(), matcher)) { - AdapterItem appItem = AdapterItem.asApp(resultCount, "", info, resultCount); + AdapterItem appItem = AdapterItem.asApp(resultCount, info); result.add(appItem); resultCount++; } diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java index 8485371a79..6978e0c2a4 100644 --- a/src/com/android/launcher3/util/Executors.java +++ b/src/com/android/launcher3/util/Executors.java @@ -15,17 +15,12 @@ */ package com.android.launcher3.util; -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; - -import static java.util.concurrent.Executors.newSingleThreadExecutor; - import android.os.HandlerThread; import android.os.Looper; import android.os.Process; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; @@ -42,7 +37,7 @@ public class Executors { private static final int KEEP_ALIVE = 1; /** Dedicated executor instances for work depending on other packages. */ - private static final Map PACKAGE_EXECUTORS = new ConcurrentHashMap<>(); + private static final Map PACKAGE_EXECUTORS = new ConcurrentHashMap<>(); /** * An {@link ThreadPoolExecutor} to be used with async task with no limit on the queue size. @@ -90,11 +85,10 @@ public class Executors { * * @param packageName Package associated with the executor. */ - public static ExecutorService getPackageExecutor(String packageName) { + public static LooperExecutor getPackageExecutor(String packageName) { return PACKAGE_EXECUTORS.computeIfAbsent( - packageName, - p -> newSingleThreadExecutor( - new SimpleThreadFactory(p, THREAD_PRIORITY_BACKGROUND))); + packageName, p -> new LooperExecutor( + createAndStartNewLooper(p, Process.THREAD_PRIORITY_DEFAULT))); } /** From e7af40c247d0cb6d05cfac45861e46018a1f016b Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 21 Apr 2022 04:07:40 +0000 Subject: [PATCH 04/15] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ie56ee2fc9fee1ff17c9554e0727f7d1f41d3d3f6 --- quickstep/res/values-nb/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index 5c4121081f..e2ae437312 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -70,7 +70,7 @@ "Ferdig" "Ferdig" "Innstillinger" - "Prøv igjen" + "Prøv på nytt" "Bra!" "Veiledning %1$d/%2$d" "Alt er klart!" From 5c590bd79aa6d0ad92ffda4acf0a52da84367f9c Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 21 Apr 2022 04:08:36 +0000 Subject: [PATCH 05/15] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I6e93daa5f1859dcd51bd2f60d59c651cb1189f7a --- res/values-ar/strings.xml | 2 +- res/values-b+sr+Latn/strings.xml | 2 +- res/values-es/strings.xml | 4 ++-- res/values-gu/strings.xml | 6 +++--- res/values-hi/strings.xml | 2 +- res/values-iw/strings.xml | 6 +++--- res/values-kk/strings.xml | 2 +- res/values-kn/strings.xml | 2 +- res/values-ml/strings.xml | 2 +- res/values-pl/strings.xml | 2 +- res/values-sr/strings.xml | 2 +- res/values-zh-rCN/strings.xml | 2 +- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index a208704478..1fcce913c1 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -32,7 +32,7 @@ "تقسيم لليسار" "تقسيم لليمين" "‏معلومات تطبيق %1$s" - "انقر مع الاستمرار لنقل أداة" + "انقر مع الاستمرار لنقل أداة." "انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة." "%1$d × %2$d" "‏العرض %1$d الطول %2$d" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index b10ae183c6..f1dcef466c 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -47,7 +47,7 @@ "Pretražite" "Obrišite tekst iz okvira za pretragu" "Vidžeti i prečice nisu dostupni" - "Nije pronađen nijedan vidžet ili prečica" + "Nije pronađen nijedan vidžet ni prečica" "Lično" "Posao" "Konverzacije" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index aa01867fcc..87eb67ae68 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -23,8 +23,8 @@ "Trabajo" "La aplicación no está instalada." "La aplicación no está disponible" - "Aplicación descargada inhabilitada en modo seguro" - "Widgets inhabilitados en modo seguro" + "Aplicación descargada inhabilitada en modo Seguro" + "Widgets inhabilitados en modo Seguro" "Acceso directo no disponible" "Inicio" "Pantalla dividida" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index fae3773756..e1a4e458d9 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -156,12 +156,12 @@ "મનગમતી ઍપ" "ઑફિસની ઍપ" "ઑફિસની પ્રોફાઇલ" - "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT વ્યવસ્થાપક તેમને જોઈ શકે છે" + "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT ઍડમિન તેમને જોઈ શકે છે" "સમજાઈ ગયું" - "ઑફિસ માટેની ઍપ થોભાવવામાં આવેલ છે" + "ઑફિસ માટેની ઍપ થોભાવવામાં આવી છે" "ઑફિસ માટેની તમારી ઍપ તમને નોટિફિકેશન મોકલી શકતી નથી, તમારી બૅટરી વાપરી શકતી નથી કે તમારું સ્થાન ઍક્સેસ કરી શકતી નથી" "ઑફિસ માટેની ઍપ બંધ છે. ઑફિસ માટેની તમારી ઍપ તમને નોટિફિકેશન મોકલી શકતી નથી, તમારી બૅટરી વાપરી શકતી નથી કે તમારું સ્થાન ઍક્સેસ કરી શકતી નથી" - "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT વ્યવસ્થાપક તેમને જોઈ શકે છે" + "ઑફિસની ઍપને બૅજ આપેલા હોય છે અને તમારા IT ઍડમિન તેમને જોઈ શકે છે" "સમજાઈ ગયું" "ઑફિસ માટેની ઍપ બંધ કરો" "ઑફિસ માટેની ઍપ ચાલુ કરો" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 45387f2d53..c7f2d9c806 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -108,7 +108,7 @@ "होमस्क्रीन घुमाने की अनुमति दें" "फ़ोन घुुमाए जाने पर" "सूचनाएं बताने वाला डॉट" - "चालू" + "चालू है" "चालू" "सूचना के ऐक्सेस की ज़रूरत है" "सूचना बिंदु दिखाने के लिए, %1$s के ऐप्लिकेशन सूचना चालू करें" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 1d5edd2558..a85258703a 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -32,7 +32,7 @@ "פיצול שמאלה" "פיצול ימינה" "‏פרטים על האפליקציה %1$s" - "כדי להעביר ווידג\'ט למקום אחר יש לגעת ולא להרפות." + "להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה." "כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות." "%1$d × %2$d" "‏רוחב %1$d על גובה %2$d" @@ -153,7 +153,7 @@ "סגירה" "סגירה" "ההתראה נסגרה" - "אישיות" + "אישי" "עבודה" "פרופיל עבודה" "‏האפליקציות לעבודה מתויגות ומוצגות למנהל ה-IT" @@ -163,7 +163,7 @@ "האפליקציות לעבודה מושבתות. האפליקציות לא יכולות לשלוח לך התראות, להשתמש בסוללה או לגשת למיקום שלך" "‏האפליקציות לעבודה מתויגות ומוצגות למנהל ה-IT" "הבנתי" - "כיבוי של אפליקציות לעבודה" + "השבתה של אפליקציות לעבודה" "הפעלה של אפליקציות לעבודה" "סינון" "הפעולה נכשלה: %1$s" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 17d21d187d..48bb2ebf5a 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -75,7 +75,7 @@ "Жою" "Қолданба ақпараты" "Орнату" - "Қолданбаны ұсынбау" + "Қолданба ұсынбау" "Болжанған қолданбаны бекіту" "таңбаша орнату" "Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді." diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index d7f8a1691c..4eedd5be31 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -47,7 +47,7 @@ "ಹುಡುಕಿ" "ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯಿಂದ ಪಠ್ಯವನ್ನು ತೆರವುಗೊಳಿಸಿ" "ವಿಜೆಟ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ" - "ಯಾವುದೇ ವಿಜೆಟ್‌ಗಳು ಅಥವಾ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ" + "ಯಾವುದೇ ವಿಜೆಟ್‌ಗಳು ಅಥವಾ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು ಪತ್ತೆಯಾಗಿಲ್ಲ" "ವೈಯಕ್ತಿಕ" "ಕೆಲಸ" "ಸಂಭಾಷಣೆಗಳು" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 5c626db7a3..e0e7d4ae4e 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -72,7 +72,7 @@ "വ്യക്തിഗത ആപ്പുകളുടെ ലിസ്റ്റ്" "ഔദ്യോഗിക ആപ്പുകളുടെ ലിസ്റ്റ്" "നീക്കംചെയ്യുക" - "അൺഇൻസ്റ്റാളുചെയ്യുക" + "അൺഇൻസ്റ്റാൾ" "ആപ്പ് വിവരങ്ങൾ" "ഇൻസ്‌റ്റാൾ ചെയ്യുക" "ആപ്പ് നിർദ്ദേശിക്കരുത്" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index f9bfb77749..565a7b08fa 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -153,7 +153,7 @@ "Zamknij" "Zamknij" "Powiadomienie odrzucone" - "Osobiste" + "Prywatne" "Służbowe" "Profil służbowy" "Aplikacje służbowe mają plakietki i są widoczne dla administratora IT" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index e719db6109..99769c25ae 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -47,7 +47,7 @@ "Претражите" "Обришите текст из оквира за претрагу" "Виџети и пречице нису доступни" - "Није пронађен ниједан виџет или пречица" + "Није пронађен ниједан виџет ни пречица" "Лично" "Посао" "Конверзације" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index c7eb21e54b..f11f020f94 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -32,7 +32,7 @@ "左分屏" "右分屏" "%1$s 的应用信息" - "轻触并按住微件即可移动该微件。" + "轻触并按住即可移动微件。" "点按两次并按住微件即可移动该微件或使用自定义操作。" "%1$d × %2$d" "宽 %1$d,高 %2$d" From a681cf6abed6409e250c57236eb1f3ad934a7524 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 15 Apr 2022 16:01:38 -0700 Subject: [PATCH 06/15] Migrate from InsetsInfo.contentInsets to WindowManager.LayoutParams#providedInternalInsets - This allows us to distinguish taskbar's ITYPE_EXTRA_NAVIGATION_BAR insets from its ITYPE_BOTTOM_TAPPABLE_ELEMENT insets - Set nav bar insets as before (contentInsets) - Set tappable elements insets the same, except when taskbar is stashed, in which case set to 0 Test: TaplTestsTaskbar; manually stash/unstash taskbar, open IME, open Calculator (which uses tappableElement() insets) and Contacts (which uses systemBars()) Fixes: 215411414 Change-Id: If00f7a590b0780715d5b8159f5135054364ce84e --- .../taskbar/StashedHandleViewController.java | 3 +- .../taskbar/TaskbarActivityContext.java | 2 +- .../launcher3/taskbar/TaskbarDragLayer.java | 1 - .../taskbar/TaskbarDragLayerController.java | 10 ------- .../taskbar/TaskbarInsetsController.kt | 28 +++++++++++++++++-- .../taskbar/TaskbarStashController.java | 19 +++++++++++-- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java index a9ae7bdc3f..b7978076c1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java @@ -176,7 +176,8 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT return revealAnim; } - public void onIsStashed(boolean isStashed) { + /** Called when taskbar is stashed or unstashed. */ + public void onIsStashedChanged(boolean isStashed) { mRegionSamplingHelper.setWindowVisible(isStashed); if (isStashed) { mStashedHandleView.updateSampledRegion(mStashedHandleBounds); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 9561b749f2..b349637c6b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -559,7 +559,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } } mWindowLayoutParams.height = height; - mControllers.taskbarInsetsController.onTaskbarWindowHeightChanged(); + mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged(); mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index 089c26d3f9..c1a6185d23 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -83,7 +83,6 @@ public class TaskbarDragLayer extends BaseDragLayer { private void onComputeTaskbarInsets(InsetsInfo insetsInfo) { if (mControllerCallbacks != null) { mControllerCallbacks.updateInsetsTouchability(insetsInfo); - mControllerCallbacks.updateContentInsets(insetsInfo.contentInsets); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index 307f674ee6..3e2695c135 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -163,16 +163,6 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo); } - /** - * Called to update the {@link InsetsInfo#contentInsets}. This is reported to apps but our - * internal launcher will ignore these insets. - */ - public void updateContentInsets(Rect outContentInsets) { - int contentHeight = mControllers.taskbarStashController - .getContentHeightToReportToApps(); - outContentInsets.top = mTaskbarDragLayer.getHeight() - contentHeight; - } - /** * Called when a child is removed from TaskbarDragLayer. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index a2ff7806f7..9571798d53 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -53,19 +53,37 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask ) ) + windowLayoutParams.providedInternalInsets = arrayOfNulls(ITYPE_SIZE) windowLayoutParams.providedInternalImeInsets = arrayOfNulls(ITYPE_SIZE) - onTaskbarWindowHeightChanged() + onTaskbarWindowHeightOrInsetsChanged() windowLayoutParams.insetsRoundedCornerFrame = true } - fun onTaskbarWindowHeightChanged() { - val reducingSize = Insets.of(0, windowLayoutParams.height - taskbarHeightForIme, 0, 0) + fun onTaskbarWindowHeightOrInsetsChanged() { + var reducingSize = getReducingInsetsForTaskbarInsetsHeight( + controllers.taskbarStashController.contentHeightToReportToApps) + windowLayoutParams.providedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize + reducingSize = getReducingInsetsForTaskbarInsetsHeight( + controllers.taskbarStashController.tappableHeightToReportToApps) + windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = reducingSize + + reducingSize = getReducingInsetsForTaskbarInsetsHeight(taskbarHeightForIme) windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = reducingSize } + /** + * WindowLayoutParams.providedInternal*Insets expects Insets that subtract from the window frame + * height (i.e. WindowLayoutParams#height). So for Taskbar to report bottom insets to apps, it + * actually provides insets from the top of its window frame. + * @param height The number of pixels from the bottom of the screen that Taskbar insets. + */ + private fun getReducingInsetsForTaskbarInsetsHeight(height: Int): Insets { + return Insets.of(0, windowLayoutParams.height - height, 0, 0) + } + /** * Called to update the touchable insets. * @see InsetsInfo.setTouchableInsets @@ -120,6 +138,10 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask override fun dumpLogs(prefix: String, pw: PrintWriter) { pw.println(prefix + "TaskbarInsetsController:") pw.println("$prefix\twindowHeight=${windowLayoutParams.height}") + pw.println("$prefix\tprovidedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR]=" + + "${windowLayoutParams.providedInternalInsets[ITYPE_EXTRA_NAVIGATION_BAR]}") + pw.println("$prefix\tprovidedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]=" + + "${windowLayoutParams.providedInternalInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]}") pw.println("$prefix\tprovidedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR]=" + "${windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR]}") pw.println("$prefix\tprovidedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]=" + diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index be67136bf0..f1a226fe25 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -30,6 +30,7 @@ import android.annotation.Nullable; import android.content.SharedPreferences; import android.util.Log; import android.view.ViewConfiguration; +import android.view.WindowInsets; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Utilities; @@ -280,6 +281,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba /** * Returns the height that taskbar will inset when inside apps. + * @see WindowInsets.Type#navigationBars() + * @see WindowInsets.Type#systemBars() */ public int getContentHeightToReportToApps() { if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) { @@ -304,6 +307,15 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba return mUnstashedHeight; } + /** + * Returns the height that taskbar will inset when inside apps. + * @see WindowInsets.Type#tappableElement() + */ + public int getTappableHeightToReportToApps() { + int contentHeight = getContentHeightToReportToApps(); + return contentHeight <= mStashedHeight ? 0 : contentHeight; + } + public int getStashedHeight() { return mStashedHeight; } @@ -442,7 +454,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba @Override public void onAnimationStart(Animator animation) { mIsStashed = isStashed; - onIsStashed(mIsStashed); + onIsStashedChanged(mIsStashed); } @Override @@ -489,8 +501,9 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba .setDuration(TASKBAR_HINT_STASH_DURATION).start(); } - private void onIsStashed(boolean isStashed) { - mControllers.stashedHandleViewController.onIsStashed(isStashed); + private void onIsStashedChanged(boolean isStashed) { + mControllers.stashedHandleViewController.onIsStashedChanged(isStashed); + mControllers.taskbarInsetsController.onTaskbarWindowHeightOrInsetsChanged(); } public void applyState() { From f286f9cb984693e0b202bb396b08d7e48b617e8b Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 20 Apr 2022 14:43:39 -0700 Subject: [PATCH 07/15] Address a couple small followups for TaskbarInsetsController - Added no-op onDestroy() - Reformated some if conditions, also adding AbstractFloatingView.hasOpenView() Test: TaplTestsTaskbar Bug: 215411414 Change-Id: I89b39ca5fabd03f5ac0f25d6ef69170683cf060d --- .../launcher3/taskbar/TaskbarControllers.java | 1 + .../launcher3/taskbar/TaskbarInsetsController.kt | 14 +++++--------- .../android/launcher3/AbstractFloatingView.java | 7 +++++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index 5d3a1520fc..ff08e3dda7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -160,6 +160,7 @@ public class TaskbarControllers { taskbarForceVisibleImmersiveController.onDestroy(); taskbarAllAppsController.onDestroy(); navButtonController.onDestroy(); + taskbarInsetsController.onDestroy(); mControllersToLog = null; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt index 9571798d53..9870a2e0bf 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -18,6 +18,7 @@ package com.android.launcher3.taskbar import android.graphics.Insets import android.view.WindowManager import com.android.launcher3.AbstractFloatingView +import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS import com.android.launcher3.R import com.android.launcher3.anim.AlphaUpdateListener import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController @@ -61,6 +62,8 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask windowLayoutParams.insetsRoundedCornerFrame = true } + fun onDestroy() {} + fun onTaskbarWindowHeightOrInsetsChanged() { var reducingSize = getReducingInsetsForTaskbarInsetsHeight( controllers.taskbarStashController.contentHeightToReportToApps) @@ -106,18 +109,11 @@ class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTask } else if (controllers.taskbarDragController.isSystemDragInProgress) { // Let touches pass through us. insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) - } else if (AbstractFloatingView.getOpenView( - context, - AbstractFloatingView.TYPE_TASKBAR_ALL_APPS - ) != null - ) { + } else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_ALL_APPS)) { // Let touches pass through us. insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) } else if (controllers.taskbarViewController.areIconsVisible() - || AbstractFloatingView.getOpenView( - context, - AbstractFloatingView.TYPE_ALL - ) != null + || AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL) || context.isNavBarKidsModeActive ) { // Taskbar has some touchable elements, take over the full taskbar area diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index 4386f4196c..90869c2965 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -207,6 +207,13 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch return getView(activity, type, true /* mustBeOpen */); } + /** + * Returns whether there is at least one view of the given type where {@link #isOpen()} == true. + */ + public static boolean hasOpenView(ActivityContext activity, @FloatingViewType int type) { + return getOpenView(activity, type) != null; + } + /** * Returns a view matching FloatingViewType, and {@link #isOpen()} may be false (if animating * closed). From 1dc4dea6ae35efcba6242ea10b30b0ca3466074f Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Thu, 21 Apr 2022 10:53:17 -0700 Subject: [PATCH 08/15] Bring Widget Picker message style inline with All Apps message style. Bug: 188227318 Test: Local flash with TestDPC to test message. Change-Id: I63403f1472a582a63299e647604eaea25b50b8e7 --- res/layout/widgets_full_sheet.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml index e867405fd6..e3f1fca91b 100644 --- a/res/layout/widgets_full_sheet.xml +++ b/res/layout/widgets_full_sheet.xml @@ -38,12 +38,13 @@ android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/> From dd7e132db52c0eaf23d341f50e8f8f7747dd7a81 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Fri, 15 Apr 2022 17:58:38 -0700 Subject: [PATCH 09/15] Use new onStartSplitLegacy when starting split from overview Bug: 223396876 Change-Id: I696749f7674a09b2a12c6ef2c2b7d19d0884049a --- .../quickstep/RecentsAnimationCallbacks.java | 3 +-- .../com/android/quickstep/SystemUiProxy.java | 17 +++++++++++++---- .../android/quickstep/TaskAnimationManager.java | 5 +++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index fe31f1d8bb..51ae56b96d 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -104,8 +104,7 @@ public class RecentsAnimationCallbacks implements .map(RemoteAnimationTargetCompat::unwrap) .toArray(RemoteAnimationTarget[]::new); - RemoteAnimationTarget[] nonAppTargets = - mSystemUiProxy.onGoingToRecentsLegacy(mCancelled, nonHomeApps); + RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(nonHomeApps); RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets, wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets), diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 5ef89d309a..5e12f319ba 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -676,14 +676,12 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI * Call this when going to recents so that shell can set-up and provide appropriate leashes * for animation (eg. DividerBar). * - * @param cancel true if recents starting is being cancelled. * @return RemoteAnimationTargets of windows that need to animate but only exist in shell. */ - public RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, - RemoteAnimationTarget[] apps) { + public RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) { if (mSplitScreen != null) { try { - return mSplitScreen.onGoingToRecentsLegacy(cancel, apps); + return mSplitScreen.onGoingToRecentsLegacy(apps); } catch (RemoteException e) { Log.w(TAG, "Failed call onGoingToRecentsLegacy"); } @@ -691,6 +689,17 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI return null; } + public RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) { + if (mSplitScreen != null) { + try { + return mSplitScreen.onStartingSplitLegacy(apps); + } catch (RemoteException e) { + Log.w(TAG, "Failed call onStartingSplitLegacy"); + } + } + return null; + } + // // One handed // diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index f094d712a1..2565674763 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -177,8 +177,9 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn ((RecentsActivity) activityInterface.getCreatedActivity()).startHome(); return; } - RemoteAnimationTarget[] nonAppTargets = SystemUiProxy.INSTANCE.get(mCtx) - .onGoingToRecentsLegacy(false, nonHomeApps); + + RemoteAnimationTarget[] nonAppTargets = + SystemUiProxy.INSTANCE.getNoCreate().onStartingSplitLegacy(nonHomeApps); if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode() && activityInterface.getCreatedActivity() != null) { From e10ab8cdcde65f32cdf0d5e96e8721a62cbd7725 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Thu, 21 Apr 2022 20:39:52 +0000 Subject: [PATCH 10/15] Snap to last task if swiping down at a greater Y than X velocity. If you swipe down slightly diagonally, it will almost always be treated as a swipe to the next task rather than a return to the current task. If we are swiping down and the Y velocity is grater, we should snap to the current task instead. Test: Manually in fully gestural mode. Bug: 222117127 Change-Id: I0f591fa5117291a9c095c2b733280464d29103d9 --- .../android/quickstep/AbsSwipeUpHandler.java | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index b073b90baf..b90e8206f7 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1013,19 +1013,19 @@ public abstract class AbsSwipeUpHandler, return RECENTS; } final GestureEndTarget endTarget; - final boolean goingToNewTask; + final boolean canGoToNewTask; if (mRecentsView != null) { if (!hasTargets()) { // If there are no running tasks, then we can assume that this is a continuation of // the last gesture, but after the recents animation has finished - goingToNewTask = true; + canGoToNewTask = true; } else { final int runningTaskIndex = mRecentsView.getRunningTaskIndex(); final int taskToLaunch = mRecentsView.getNextPage(); - goingToNewTask = runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex; + canGoToNewTask = runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex; } } else { - goingToNewTask = false; + canGoToNewTask = false; } final boolean reachedOverviewThreshold = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW; final boolean isFlingX = Math.abs(velocity.x) > mContext.getResources() @@ -1034,13 +1034,13 @@ public abstract class AbsSwipeUpHandler, if (isCancel) { endTarget = LAST_TASK; } else if (mDeviceState.isFullyGesturalNavMode()) { - if (goingToNewTask && isFlingX) { + if (canGoToNewTask && isFlingX) { // Flinging towards new task takes precedence over mIsMotionPaused (which only // checks y-velocity). endTarget = NEW_TASK; } else if (mIsMotionPaused) { endTarget = RECENTS; - } else if (goingToNewTask) { + } else if (canGoToNewTask) { endTarget = NEW_TASK; } else { endTarget = !reachedOverviewThreshold ? LAST_TASK : HOME; @@ -1048,26 +1048,22 @@ public abstract class AbsSwipeUpHandler, } else { endTarget = reachedOverviewThreshold && mGestureStarted ? RECENTS - : goingToNewTask + : canGoToNewTask ? NEW_TASK : LAST_TASK; } } else { // If swiping at a diagonal, base end target on the faster velocity. boolean isSwipeUp = endVelocity < 0; - boolean willGoToNewTaskOnSwipeUp = - goingToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity); + boolean willGoToNewTask = + canGoToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity); - if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) { - endTarget = HOME; - } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) { - // If swiping at a diagonal, base end target on the faster velocity. - endTarget = NEW_TASK; + if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) { + endTarget = willGoToNewTask ? NEW_TASK : HOME; } else if (isSwipeUp) { - endTarget = !reachedOverviewThreshold && willGoToNewTaskOnSwipeUp - ? NEW_TASK : RECENTS; + endTarget = (!reachedOverviewThreshold && willGoToNewTask) ? NEW_TASK : RECENTS; } else { - endTarget = goingToNewTask ? NEW_TASK : LAST_TASK; + endTarget = willGoToNewTask ? NEW_TASK : LAST_TASK; // Swipe is downward. } } @@ -1145,6 +1141,8 @@ public abstract class AbsSwipeUpHandler, duration = Math.max(duration, mRecentsView.getScroller().getDuration()); } } + } else if (endTarget == LAST_TASK && mRecentsView != null) { + mRecentsView.snapToPage(mRecentsView.getCurrentPage(), Math.toIntExact(duration)); } // Let RecentsView handle the scrolling to the task, which we launch in startNewTask() From e3b806366a2276b279ec587e03f6fd084eabecb3 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 14 Apr 2022 18:36:57 +0100 Subject: [PATCH 11/15] Update pull back animation for tablet AllApps - This is a follow-up of http://ag/17636490 - Introduced animation property specifically for pullback translation and alpha, which will invoke getRecyclerViewContainer directly on tablet, and invoke aggregate setter of appsView on phones - Delay reset of pullback animation to after dismiss animation to avoid jump in value during state transition animation - Introduced property factory for addictive properties similar to MultiScalePropertyFactory Fix: 220345008 Test: manual on small and large screen Change-Id: I7b5c0019c1d4d36c3c7ca4ec79e38e4eb09c32ca --- .../NavBarToHomeTouchController.java | 19 +-- .../allapps/AllAppsTransitionController.java | 96 ++++++++++++--- .../util/MultiAdditivePropertyFactory.java | 115 ++++++++++++++++++ .../util/MultiAdditivePropertyTest.kt | 66 ++++++++++ .../launcher3/util/MultiScalePropertyTest.kt | 16 +++ 5 files changed, 279 insertions(+), 33 deletions(-) create mode 100644 src/com/android/launcher3/util/MultiAdditivePropertyFactory.java create mode 100644 tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index 7bfb76a978..34a6821ac5 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -21,7 +21,8 @@ import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRES import static com.android.launcher3.LauncherAnimUtils.newCancelListener; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_PROGRESS; +import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_ALPHA; +import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_TRANSLATION; import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback; import static com.android.launcher3.anim.Interpolators.DEACCEL_3; import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU; @@ -40,11 +41,9 @@ import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.anim.AnimatorPlaybackController; -import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.SingleAxisSwipeDetector; import com.android.launcher3.util.TouchController; import com.android.quickstep.TaskUtils; @@ -148,16 +147,10 @@ public class NavBarToHomeTouchController implements TouchController, AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_TASK_MENU); } else if (mStartState == ALL_APPS) { AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); - builder.setFloat(allAppsController, ALL_APPS_PULL_BACK_PROGRESS, - -mPullbackDistance / allAppsController.getShiftRange(), PULLBACK_INTERPOLATOR); - - // Slightly fade out all apps content to further distinguish from scrolling. - StateAnimationConfig config = new StateAnimationConfig(); - config.duration = accuracy; - config.setInterpolator(StateAnimationConfig.ANIM_ALL_APPS_FADE, Interpolators - .mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f)); - - allAppsController.setAlphas(mEndState, config, builder); + builder.setFloat(allAppsController, ALL_APPS_PULL_BACK_TRANSLATION, + -mPullbackDistance, PULLBACK_INTERPOLATOR); + builder.setFloat(allAppsController, ALL_APPS_PULL_BACK_ALPHA, + 0.5f, PULLBACK_INTERPOLATOR); } AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher); if (topView != null) { diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 8662d0067d..637a4189b8 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -44,6 +44,8 @@ import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.states.StateAnimationConfig; +import com.android.launcher3.util.MultiAdditivePropertyFactory; +import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.UiThreadHelper; import com.android.launcher3.views.ScrimView; @@ -76,20 +78,56 @@ public class AllAppsTransitionController } }; - public static final FloatProperty ALL_APPS_PULL_BACK_PROGRESS = - new FloatProperty("allAppsPullBackProgress") { + public static final FloatProperty ALL_APPS_PULL_BACK_TRANSLATION = + new FloatProperty("allAppsPullBackTranslation") { @Override public Float get(AllAppsTransitionController controller) { - return controller.mPullBackProgress; + if (controller.mIsTablet) { + return controller.mAppsView.getRecyclerViewContainer().getTranslationY(); + } else { + return controller.getAppsViewPullbackTranslationY().get( + controller.mAppsView); + } } @Override - public void setValue(AllAppsTransitionController controller, float progress) { - controller.setPullBackProgress(progress); + public void setValue(AllAppsTransitionController controller, float translation) { + if (controller.mIsTablet) { + controller.mAppsView.getRecyclerViewContainer().setTranslationY( + translation); + } else { + controller.getAppsViewPullbackTranslationY().set(controller.mAppsView, + translation); + } } }; + public static final FloatProperty ALL_APPS_PULL_BACK_ALPHA = + new FloatProperty("allAppsPullBackAlpha") { + + @Override + public Float get(AllAppsTransitionController controller) { + if (controller.mIsTablet) { + return controller.mAppsView.getRecyclerViewContainer().getAlpha(); + } else { + return controller.getAppsViewPullbackAlpha().getValue(); + } + } + + @Override + public void setValue(AllAppsTransitionController controller, float alpha) { + if (controller.mIsTablet) { + controller.mAppsView.getRecyclerViewContainer().setAlpha(alpha); + } else { + controller.getAppsViewPullbackAlpha().setValue(alpha); + } + } + }; + + private static final int INDEX_APPS_VIEW_PROGRESS = 0; + private static final int INDEX_APPS_VIEW_PULLBACK = 1; + private static final int APPS_VIEW_INDEX_COUNT = 2; private ActivityAllAppsContainerView mAppsView; @@ -104,18 +142,23 @@ public class AllAppsTransitionController // When {@link mProgress} is 1, all apps container is pulled down. private float mShiftRange; // changes depending on the orientation private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent - private float mPullBackProgress; // [0, 1], mShiftRange * mPullBackProgress = shiftCurrent private ScrimView mScrimView; - private View mPullBackView; + + private final MultiAdditivePropertyFactory + mAppsViewTranslationYPropertyFactory = new MultiAdditivePropertyFactory<>( + "appsViewTranslationY", View.TRANSLATION_Y); + private MultiValueAlpha mAppsViewAlpha; + + private boolean mIsTablet; public AllAppsTransitionController(Launcher l) { mLauncher = l; DeviceProfile dp = mLauncher.getDeviceProfile(); setShiftRange(dp.allAppsShiftRange); mProgress = 1f; - mPullBackProgress = 1f; mIsVerticalLayout = dp.isVerticalBarLayout(); + mIsTablet = dp.isTablet; mLauncher.addOnDeviceProfileChangeListener(this); } @@ -133,7 +176,7 @@ public class AllAppsTransitionController mLauncher.getWorkspace().getPageIndicator().setTranslationY(0); } - mPullBackView = dp.isTablet ? mAppsView.getRecyclerViewContainer() : mAppsView; + mIsTablet = dp.isTablet; } /** @@ -146,16 +189,27 @@ public class AllAppsTransitionController */ public void setProgress(float progress) { mProgress = progress; - mAppsView.setTranslationY(mProgress * mShiftRange); + getAppsViewProgressTranslationY().set(mAppsView, mProgress * mShiftRange); } public float getProgress() { return mProgress; } - private void setPullBackProgress(float progress) { - mPullBackProgress = progress; - mPullBackView.setTranslationY(mPullBackProgress * mShiftRange); + private FloatProperty getAppsViewProgressTranslationY() { + return mAppsViewTranslationYPropertyFactory.get(INDEX_APPS_VIEW_PROGRESS); + } + + private FloatProperty getAppsViewPullbackTranslationY() { + return mAppsViewTranslationYPropertyFactory.get(INDEX_APPS_VIEW_PULLBACK); + } + + private MultiValueAlpha.AlphaProperty getAppsViewProgressAlpha() { + return mAppsViewAlpha.getProperty(INDEX_APPS_VIEW_PROGRESS); + } + + private MultiValueAlpha.AlphaProperty getAppsViewPullbackAlpha() { + return mAppsViewAlpha.getProperty(INDEX_APPS_VIEW_PULLBACK); } /** @@ -164,8 +218,6 @@ public class AllAppsTransitionController */ @Override public void setState(LauncherState state) { - // Always reset pull back progress when switching states. - setPullBackProgress(0f); setProgress(state.getVerticalProgress(mLauncher)); setAlphas(state, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER); onProgressAnimationEnd(); @@ -180,10 +232,13 @@ public class AllAppsTransitionController StateAnimationConfig config, PendingAnimation builder) { if (NORMAL.equals(toState) && mLauncher.isInState(ALL_APPS)) { UiThreadHelper.hideKeyboardAsync(mLauncher, mLauncher.getAppsView().getWindowToken()); + builder.addEndListener(success -> { + // Reset pull back progress and alpha after switching states. + ALL_APPS_PULL_BACK_TRANSLATION.set(this, 0f); + ALL_APPS_PULL_BACK_ALPHA.set(this, 1f); + }); } - // Always reset pull back progress when switching states. - setPullBackProgress(0f); float targetProgress = toState.getVerticalProgress(mLauncher); if (Float.compare(mProgress, targetProgress) == 0) { setAlphas(toState, config, builder); @@ -222,7 +277,8 @@ public class AllAppsTransitionController boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0; Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR); - setter.setViewAlpha(mAppsView, hasAllAppsContent ? 1 : 0, allAppsFade); + setter.setFloat(getAppsViewProgressAlpha(), MultiValueAlpha.VALUE, + hasAllAppsContent ? 1 : 0, allAppsFade); boolean shouldProtectHeader = ALL_APPS == state || mLauncher.getStateManager().getState() == ALL_APPS; @@ -245,8 +301,8 @@ public class AllAppsTransitionController | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); } mAppsView.setScrimView(scrimView); - mPullBackView = mLauncher.getDeviceProfile().isTablet - ? mAppsView.getRecyclerViewContainer() : mAppsView; + mAppsViewAlpha = new MultiValueAlpha(mAppsView, APPS_VIEW_INDEX_COUNT); + mAppsViewAlpha.setUpdateVisibility(true); } /** diff --git a/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java b/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java new file mode 100644 index 0000000000..50f7027407 --- /dev/null +++ b/src/com/android/launcher3/util/MultiAdditivePropertyFactory.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util; + +import android.util.ArrayMap; +import android.util.FloatProperty; +import android.util.Log; +import android.util.Property; +import android.view.View; + +/** + * Allows to combine multiple values set by several sources. + * + * The various sources are meant to use [set], providing different `setterIndex` params. When it is + * not set, 0 is used. This is meant to cover the case multiple animations are going on at the same + * time. + * + * This class behaves similarly to [MultiValueAlpha], but is meant to be more abstract and reusable. + * It sets the addition of all values. + * + * @param Type where to apply the property. + */ +public class MultiAdditivePropertyFactory { + + private static final boolean DEBUG = false; + private static final String TAG = "MultiAdditivePropertyFactory"; + private final String mName; + private final ArrayMap mProperties = + new ArrayMap<>(); + + // This is an optimization for cases when set is called repeatedly with the same setterIndex. + private float mAggregationOfOthers = 0f; + private Integer mLastIndexSet = -1; + private final Property mProperty; + + public MultiAdditivePropertyFactory(String name, Property property) { + mName = name; + mProperty = property; + } + + /** Returns the [MultiFloatProperty] associated with [inx], creating it if not present. */ + public MultiAdditiveProperty get(Integer index) { + return mProperties.computeIfAbsent(index, + (k) -> new MultiAdditiveProperty(index, mName + "_" + index)); + } + + /** + * Each [setValue] will be aggregated with the other properties values created by the + * corresponding factory. + */ + class MultiAdditiveProperty extends FloatProperty { + private final int mInx; + private float mValue = 0f; + + MultiAdditiveProperty(int inx, String name) { + super(name); + mInx = inx; + } + + @Override + public void setValue(T obj, float newValue) { + if (mLastIndexSet != mInx) { + mAggregationOfOthers = 0f; + mProperties.forEach((key, property) -> { + if (key != mInx) { + mAggregationOfOthers += property.mValue; + } + }); + mLastIndexSet = mInx; + } + float lastAggregatedValue = mAggregationOfOthers + newValue; + mValue = newValue; + apply(obj, lastAggregatedValue); + + if (DEBUG) { + Log.d(TAG, "name=" + mName + + " newValue=" + newValue + " mInx=" + mInx + + " aggregated=" + lastAggregatedValue + " others= " + mProperties); + } + } + + @Override + public Float get(T view) { + // The scale of the view should match mLastAggregatedValue. Still, if it has been + // changed without using this property, it can differ. As this get method is usually + // used to set the starting point on an animation, this would result in some jumps + // when the view scale is different than the last aggregated value. To stay on the + // safe side, let's return the real view scale. + return mProperty.get(view); + } + + @Override + public String toString() { + return String.valueOf(mValue); + } + } + + protected void apply(View view, float value) { + mProperty.set(view, value); + } +} diff --git a/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt new file mode 100644 index 0000000000..309d055bad --- /dev/null +++ b/tests/src/com/android/launcher3/util/MultiAdditivePropertyTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util + +import android.view.View +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +/** Unit tests for [MultiAdditivePropertyFactory] */ +@SmallTest +@RunWith(AndroidJUnit4::class) +class MultiAdditivePropertyTest { + + private val received = mutableListOf() + + private val factory = + object : MultiAdditivePropertyFactory("Test", View.TRANSLATION_X) { + override fun apply(obj: View?, value: Float) { + received.add(value) + } + } + + private val p1 = factory.get(1) + private val p2 = factory.get(2) + private val p3 = factory.get(3) + + @Test + fun set_sameIndexes_allApplied() { + val v1 = 50f + val v2 = 100f + p1.set(null, v1) + p1.set(null, v1) + p1.set(null, v2) + + assertThat(received).containsExactly(v1, v1, v2) + } + + @Test + fun set_differentIndexes_aggregationApplied() { + val v1 = 50f + val v2 = 100f + val v3 = 150f + p1.set(null, v1) + p2.set(null, v2) + p3.set(null, v3) + + assertThat(received).containsExactly(v1, v1 + v2, v1 + v2 + v3) + } +} diff --git a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt index 6099987172..7d92214d9b 100644 --- a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt +++ b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.launcher3.util import android.view.View From 7b8d63fcf88c3054fc28a2aced4a8b450f406e7e Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 14 Apr 2022 16:37:32 -0700 Subject: [PATCH 12/15] Removing fade in logic during load. Launcher already blocks the draw during load, which ensures that system draws the loading screen. Additional fade animation is not visible since the Launcher window is already getting fade in Bug: 199120420 Bug: 199120420 Test: Verified on device Change-Id: I7089cea4c5f97f6ef92eabcba56451de407c98b8 --- .../launcher3/QuickstepTransitionManager.java | 5 -- src/com/android/launcher3/Launcher.java | 73 ++++--------------- .../launcher3/dragndrop/DragLayer.java | 4 +- 3 files changed, 15 insertions(+), 67 deletions(-) diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 097609f2d9..0f3474eb19 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -42,7 +42,6 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_BACK_SWIPE_HOME_A import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAUNCH; import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION; import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY; -import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; import static com.android.launcher3.statehandlers.DepthController.DEPTH; import static com.android.launcher3.testing.TestProtocol.BAD_STATE; @@ -105,7 +104,6 @@ import com.android.launcher3.taskbar.LauncherTaskbarUIController; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.ActivityOptionsWrapper; import com.android.launcher3.util.DynamicResource; -import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.ObjectWrapper; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.Themes; @@ -195,9 +193,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener private static final int WIDGET_CROSSFADE_DURATION_MILLIS = 125; protected final BaseQuickstepLauncher mLauncher; - private final DragLayer mDragLayer; - private final AlphaProperty mDragLayerAlpha; final Handler mHandler; @@ -241,7 +237,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener public QuickstepTransitionManager(Context context) { mLauncher = Launcher.cast(Launcher.getLauncher(context)); mDragLayer = mLauncher.getDragLayer(); - mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS); mHandler = new Handler(Looper.getMainLooper()); mDeviceProfile = mLauncher.getDeviceProfile(); mBackAnimationController = new LauncherBackAnimationController(mLauncher, this); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index b6a05b02d4..4b42ecbae0 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -42,7 +42,6 @@ import static com.android.launcher3.LauncherState.NO_SCALE; import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions; -import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD; import static com.android.launcher3.logging.StatsLogManager.EventEnum; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME; @@ -65,7 +64,6 @@ import static com.android.launcher3.util.ItemInfoMatcher.forFolderMatch; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.Notification; @@ -109,7 +107,7 @@ import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.OnPreDrawListener; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.animation.OvershootInterpolator; @@ -130,7 +128,6 @@ import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.BaseAllAppsContainerView; import com.android.launcher3.allapps.DiscoveryBounce; -import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; @@ -186,8 +183,6 @@ import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; -import com.android.launcher3.util.MultiValueAlpha; -import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; @@ -341,6 +336,7 @@ public class Launcher extends StatefulActivity private Runnable mOnDeferredActivityLaunchCallback; private ViewOnDrawExecutor mPendingExecutor; + private OnPreDrawListener mOnInitialBindListener; private LauncherModel mModel; private ModelWriter mModelWriter; @@ -503,11 +499,10 @@ public class Launcher extends StatefulActivity if (!mModel.addCallbacksAndLoad(this)) { if (!internalStateHandled) { - Log.d(BAD_STATE, "Launcher onCreate not binding sync, setting DragLayer alpha " - + "ALPHA_INDEX_LAUNCHER_LOAD to 0"); - // If we are not binding synchronously, show a fade in animation when - // the first page bind completes. - mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0); + Log.d(BAD_STATE, "Launcher onCreate not binding sync, prevent drawing"); + // If we are not binding synchronously, pause drawing until initial bind complete, + // so that the system could continue to show the device loading prompt + mOnInitialBindListener = Boolean.FALSE::booleanValue; } } @@ -515,25 +510,9 @@ public class Launcher extends StatefulActivity setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); setContentView(getRootView()); - getRootView().getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - // Checks the status of fade in animation. - final AlphaProperty property = - mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD); - if (property.getValue() == 0) { - Log.d(BAD_STATE, "Launcher onPreDraw ALPHA_INDEX_LAUNCHER_LOAD not" - + " started yet, cancelling draw."); - // Animation haven't started yet; suspend. - return false; - } else { - // The animation is started; start drawing. - getRootView().getViewTreeObserver().removeOnPreDrawListener(this); - return true; - } - } - }); + if (mOnInitialBindListener != null) { + getRootView().getViewTreeObserver().addOnPreDrawListener(mOnInitialBindListener); + } getRootView().dispatchInsets(); // Listen for broadcasts @@ -2692,36 +2671,12 @@ public class Launcher extends StatefulActivity AllAppsStore.DEFER_UPDATES_NEXT_DRAW)); } - AlphaProperty property = mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD); - if (property.getValue() < 1) { - ObjectAnimator anim = ObjectAnimator.ofFloat(property, MultiValueAlpha.VALUE, 1); - - Log.d(BAD_STATE, "Launcher onInitialBindComplete toAlpha=" + 1); - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - Log.d(BAD_STATE, "Launcher onInitialBindComplete onStart"); - } - - @Override - public void onAnimationCancel(Animator animation) { - float alpha = mDragLayer == null - ? -1 - : mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).getValue(); - Log.d(BAD_STATE, "Launcher onInitialBindComplete onCancel, alpha=" + alpha); - } - - @Override - public void onAnimationEnd(Animator animation) { - Log.d(BAD_STATE, "Launcher onInitialBindComplete onEnd"); - } - }); - - anim.addListener(AnimatorListeners.forEndCallback(executor::onLoadAnimationCompleted)); - anim.start(); - } else { - executor.onLoadAnimationCompleted(); + if (mOnInitialBindListener != null) { + getRootView().getViewTreeObserver().removeOnPreDrawListener(mOnInitialBindListener); + mOnInitialBindListener = null; } + + executor.onLoadAnimationCompleted(); executor.attachTo(this); if (Utilities.ATLEAST_S) { Trace.endAsyncSection(DISPLAY_WORKSPACE_TRACE_METHOD_NAME, diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java index 14e10918b6..8eeca7d6d8 100644 --- a/src/com/android/launcher3/dragndrop/DragLayer.java +++ b/src/com/android/launcher3/dragndrop/DragLayer.java @@ -65,9 +65,7 @@ import java.util.ArrayList; public class DragLayer extends BaseDragLayer { public static final int ALPHA_INDEX_OVERLAY = 0; - public static final int ALPHA_INDEX_LAUNCHER_LOAD = 1; - public static final int ALPHA_INDEX_TRANSITIONS = 2; - private static final int ALPHA_CHANNEL_COUNT = 3; + private static final int ALPHA_CHANNEL_COUNT = 1; public static final int ANIMATION_END_DISAPPEAR = 0; public static final int ANIMATION_END_REMAIN_VISIBLE = 2; From 13ae6784b54ea8878a70900312503211867e15f1 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 22 Apr 2022 19:53:37 +0000 Subject: [PATCH 13/15] Revert "Removing some unused code from All-Apps" Revert submission 17866780-cancel-request Reason for revert: wrong icons Reverted Changes: Iedc98e5ef:Cancelling previous request and clearing UI when a... I72394fb42:Removing some unused code from All-Apps Change-Id: I2ecefcaf07e6105a10f86b8dc19f75089e45a3e0 --- src/com/android/launcher3/BubbleTextView.java | 27 ++++-- .../allapps/AlphabeticalAppsList.java | 95 ++++++++----------- .../launcher3/allapps/BaseAllAppsAdapter.java | 38 ++++---- .../allapps/BaseAllAppsContainerView.java | 7 -- .../launcher3/allapps/DecorationInfo.java | 19 ++++ .../search/DefaultAppSearchAlgorithm.java | 2 +- src/com/android/launcher3/util/Executors.java | 14 ++- 7 files changed, 107 insertions(+), 95 deletions(-) create mode 100644 src/com/android/launcher3/allapps/DecorationInfo.java diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 6302739bc5..74ec7ee327 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -96,6 +96,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private static final int MAX_SEARCH_LOOP_COUNT = 20; private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed}; + private static final float HIGHLIGHT_SCALE = 1.16f; private final PointF mTranslationForReorderBounce = new PointF(0, 0); private final PointF mTranslationForReorderPreview = new PointF(0, 0); @@ -258,12 +259,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, mDotParams.scale = 0f; mForceHideDot = false; setBackground(null); - - setTag(null); - if (mIconLoadRequest != null) { - mIconLoadRequest.cancel(); - mIconLoadRequest = null; - } } private void cancelDotScaleAnim() { @@ -368,7 +363,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } } - public void setBubbleTextHolder(BubbleTextHolder bubbleTextHolder) { + public void setBubbleTextHolder( + BubbleTextHolder bubbleTextHolder) { mBubbleTextHolder = bubbleTextHolder; } @@ -1024,6 +1020,19 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, getIconBounds(mIconSize, bounds); } + private int getIconSizeForDisplay(int display) { + DeviceProfile grid = mActivity.getDeviceProfile(); + switch (display) { + case DISPLAY_ALL_APPS: + return grid.allAppsIconSizePx; + case DISPLAY_FOLDER: + return grid.folderChildIconSizePx; + case DISPLAY_WORKSPACE: + default: + return grid.iconSizePx; + } + } + public void getSourceVisualDragBounds(Rect bounds) { getIconBounds(mIconSize, bounds); } @@ -1036,8 +1045,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, } private void resetIconScale() { - if (mIcon != null) { - mIcon.resetScale(); + if (mIcon instanceof FastBitmapDrawable) { + ((FastBitmapDrawable) mIcon).resetScale(); } } diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 00156b1f8d..7687fea85d 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -18,9 +18,6 @@ package com.android.launcher3.allapps; import android.content.Context; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.DiffUtil.DiffResult; - import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; @@ -46,6 +43,10 @@ public class AlphabeticalAppsList implement public static final String TAG = "AlphabeticalAppsList"; + private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION = 0; + private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1; + + private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS; private final WorkAdapterProvider mWorkAdapterProvider; /** @@ -197,11 +198,8 @@ public class AlphabeticalAppsList implement public boolean appendSearchResults(ArrayList results) { if (hasFilter() && results != null && results.size() > 0) { - int pos = mSearchResults.size(); - updateSearchAdapterItems(results, pos); - if (mAdapter != null) { - mAdapter.notifyItemRangeInserted(pos, results.size()); - } + updateSearchAdapterItems(results, mSearchResults.size()); + refreshRecyclerView(); return true; } return false; @@ -275,6 +273,10 @@ public class AlphabeticalAppsList implement */ public void updateAdapterItems() { refillAdapterItems(); + refreshRecyclerView(); + } + + private void refreshRecyclerView() { if (mAdapter != null) { mAdapter.notifyDataSetChanged(); } @@ -284,9 +286,9 @@ public class AlphabeticalAppsList implement String lastSectionName = null; FastScrollSectionInfo lastFastScrollerSectionInfo = null; int position = 0; + int appIndex = 0; // Prepare to update the list of sections, filtered apps, etc. - ArrayList oldList = new ArrayList<>(mAdapterItems); mAccessibilityResultsCount = 0; mFastScrollerSections.clear(); mAdapterItems.clear(); @@ -313,7 +315,8 @@ public class AlphabeticalAppsList implement } // Create an app item - AdapterItem appItem = AdapterItem.asApp(position++, info); + AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, + appIndex++); if (lastFastScrollerSectionInfo.fastScrollToItem == null) { lastFastScrollerSectionInfo.fastScrollToItem = appItem; } @@ -339,7 +342,6 @@ public class AlphabeticalAppsList implement int numAppsInSection = 0; int numAppsInRow = 0; int rowIndex = -1; - for (AdapterItem item : mAdapterItems) { item.rowIndex = 0; if (BaseAllAppsAdapter.isDividerViewType(item.viewType)) { @@ -358,50 +360,35 @@ public class AlphabeticalAppsList implement mNumAppRowsInAdapter = rowIndex + 1; // Pre-calculate all the fast scroller fractions - float perSectionTouchFraction = 1f / mFastScrollerSections.size(); - float cumulativeTouchFraction = 0f; - for (FastScrollSectionInfo info : mFastScrollerSections) { - AdapterItem item = info.fastScrollToItem; - if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) { - info.touchFraction = 0f; - continue; - } - info.touchFraction = cumulativeTouchFraction; - cumulativeTouchFraction += perSectionTouchFraction; + switch (mFastScrollDistributionMode) { + case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION: + float rowFraction = 1f / mNumAppRowsInAdapter; + for (FastScrollSectionInfo info : mFastScrollerSections) { + AdapterItem item = info.fastScrollToItem; + if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) { + info.touchFraction = 0f; + continue; + } + + float subRowFraction = + item.rowAppIndex * (rowFraction / mNumAppsPerRowAllApps); + info.touchFraction = item.rowIndex * rowFraction + subRowFraction; + } + break; + case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS: + float perSectionTouchFraction = 1f / mFastScrollerSections.size(); + float cumulativeTouchFraction = 0f; + for (FastScrollSectionInfo info : mFastScrollerSections) { + AdapterItem item = info.fastScrollToItem; + if (!BaseAllAppsAdapter.isIconViewType(item.viewType)) { + info.touchFraction = 0f; + continue; + } + info.touchFraction = cumulativeTouchFraction; + cumulativeTouchFraction += perSectionTouchFraction; + } + break; } } - - DiffResult result = DiffUtil.calculateDiff(new DiffCallback(oldList, mAdapterItems)); - } - - private static class DiffCallback extends DiffUtil.Callback { - private final List mOldItems; - private final List mNewItems; - - DiffCallback(List oldItems, List newItems) { - mOldItems = oldItems; - mNewItems = newItems; - } - - @Override - public int getOldListSize() { - return mOldItems.size(); - } - - @Override - public int getNewListSize() { - return mNewItems.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return mOldItems.get(oldItemPosition).getStableId() - == mNewItems.get(newItemPosition).getStableId(); - } - - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return mOldItems.get(oldItemPosition).isContentSame(mNewItems.get(newItemPosition)); - } } } diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java index e912cf22da..976284d947 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java @@ -36,6 +36,7 @@ import com.android.launcher3.BubbleTextView; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; +import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.views.ActivityContext; import java.util.Arrays; @@ -93,21 +94,31 @@ public abstract class BaseAllAppsAdapter ex // The type of this item public int viewType; + // The section name of this item. Note that there can be multiple items with different + // sectionNames in the same section + public String sectionName = null; // The row that this item shows up on public int rowIndex; // The index of this app in the row public int rowAppIndex; // The associated ItemInfoWithIcon for the item - public AppInfo itemInfo = null; + public ItemInfoWithIcon itemInfo = null; + // The index of this app not including sections + public int appIndex = -1; + // Search section associated to result + public DecorationInfo decorationInfo = null; /** * Factory method for AppIcon AdapterItem */ - public static AdapterItem asApp(int pos, AppInfo appInfo) { + public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo, + int appIndex) { AdapterItem item = new AdapterItem(); item.viewType = VIEW_TYPE_ICON; item.position = pos; + item.sectionName = sectionName; item.itemInfo = appInfo; + item.appIndex = appIndex; return item; } @@ -144,23 +155,6 @@ public abstract class BaseAllAppsAdapter ex protected boolean isCountedForAccessibility() { return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_SEARCH_MARKET; } - - public long getStableId() { - return viewType; - } - - /** - * Called to check if the content of the item is same as the other item. This is called only - * if the {@link #getStableId()} matches for both the items. - */ - public boolean isContentSame(AdapterItem other) { - // We can use itemInfo for diff, but since ItemInfo objects are singleton per Model, - // this could prevent updates within this itemInfo object itself (like title change - // or flag changes). We can create a better diffing logic if we store a clone a snapshot - // of the itemInfo, but that would cause icons to be loaded lazily on the cloned object - // instead of the singleton object. - return false; - } } protected final T mActivityContext; @@ -273,7 +267,11 @@ public abstract class BaseAllAppsAdapter ex AdapterItem adapterItem = mApps.getAdapterItems().get(position); BubbleTextView icon = (BubbleTextView) holder.itemView; icon.reset(); - icon.applyFromApplicationInfo(adapterItem.itemInfo); + if (adapterItem.itemInfo instanceof AppInfo) { + icon.applyFromApplicationInfo((AppInfo) adapterItem.itemInfo); + } else { + icon.applyFromItemInfoWithIcon(adapterItem.itemInfo); + } break; case VIEW_TYPE_EMPTY_SEARCH: TextView emptyViewText = (TextView) holder.itemView; diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index 31c0c69355..f913aa9093 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -45,7 +45,6 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.DeviceProfileListenable; @@ -728,12 +727,6 @@ public abstract class BaseAllAppsContainerView { for (int i = 0; i < total && resultCount < MAX_RESULTS_COUNT; i++) { AppInfo info = apps.get(i); if (StringMatcherUtility.matches(queryTextLower, info.title.toString(), matcher)) { - AdapterItem appItem = AdapterItem.asApp(resultCount, info); + AdapterItem appItem = AdapterItem.asApp(resultCount, "", info, resultCount); result.add(appItem); resultCount++; } diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java index 6978e0c2a4..8485371a79 100644 --- a/src/com/android/launcher3/util/Executors.java +++ b/src/com/android/launcher3/util/Executors.java @@ -15,12 +15,17 @@ */ package com.android.launcher3.util; +import static android.os.Process.THREAD_PRIORITY_BACKGROUND; + +import static java.util.concurrent.Executors.newSingleThreadExecutor; + import android.os.HandlerThread; import android.os.Looper; import android.os.Process; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; @@ -37,7 +42,7 @@ public class Executors { private static final int KEEP_ALIVE = 1; /** Dedicated executor instances for work depending on other packages. */ - private static final Map PACKAGE_EXECUTORS = new ConcurrentHashMap<>(); + private static final Map PACKAGE_EXECUTORS = new ConcurrentHashMap<>(); /** * An {@link ThreadPoolExecutor} to be used with async task with no limit on the queue size. @@ -85,10 +90,11 @@ public class Executors { * * @param packageName Package associated with the executor. */ - public static LooperExecutor getPackageExecutor(String packageName) { + public static ExecutorService getPackageExecutor(String packageName) { return PACKAGE_EXECUTORS.computeIfAbsent( - packageName, p -> new LooperExecutor( - createAndStartNewLooper(p, Process.THREAD_PRIORITY_DEFAULT))); + packageName, + p -> newSingleThreadExecutor( + new SimpleThreadFactory(p, THREAD_PRIORITY_BACKGROUND))); } /** From 42276318b9682389f1b3c5efde6c323aa066fc82 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Mon, 18 Apr 2022 17:21:33 -0700 Subject: [PATCH 14/15] Fix crash bug when splitting with animations disabled Fixes a bug where disabling animations (through Settings) would cause split staging to crash. The crash occurs because when animations are disabled, StateManager advances to OVERVIEW_SPLIT_SELECT too quickly, and does not trigger the appropriate code block in RecentsViewStateController#handleSplitSelectionState(). This causes a crash. Fixed by changing the conditional so that it always runs when OVERVIEW_SPLIT_SELECT is the target state, no matter the starting state. Note: If more animations are added for this state in the future, the conditional may need to be tweaked further. Fixes: 223598955 Test: Confirmed not crashing on 2 devices when splitting in a variety of ways. Change-Id: I7f3def88f124fa1babe9a943adf72c10f58b7131 --- .../RecentsViewStateController.java | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 947d3e26da..86f26c3673 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -107,7 +107,6 @@ public final class RecentsViewStateController extends */ private void handleSplitSelectionState(@NonNull LauncherState toState, @Nullable PendingAnimation builder) { - LauncherState currentState = mLauncher.getStateManager().getState(); boolean animate = builder != null; PagedOrientationHandler orientationHandler = ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler(); @@ -116,7 +115,7 @@ public final class RecentsViewStateController extends TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, mLauncher.getDeviceProfile()); - if (isSplitSelectionState(currentState, toState)) { + if (toState == OVERVIEW_SPLIT_SELECT) { // Animation to "dismiss" selected taskView PendingAnimation splitSelectInitAnimation = mRecentsView.createSplitSelectInitAnimation( toState.getTransitionDuration(mLauncher)); @@ -125,30 +124,18 @@ public final class RecentsViewStateController extends toState.getSplitSelectTranslation(mLauncher), LINEAR); splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR); - if (!animate && isSplitSelectionState(currentState, toState)) { + if (!animate) { splitSelectInitAnimation.buildAnim().start(); - } else if (animate && - isSplitSelectionState(currentState, toState)) { + } else { builder.add(splitSelectInitAnimation.buildAnim()); } - } - if (isSplitSelectionState(currentState, toState)) { mRecentsView.applySplitPrimaryScrollOffset(); } else { mRecentsView.resetSplitPrimaryScrollOffset(); } } - /** - * @return true if {@param toState} is {@link LauncherState#OVERVIEW_SPLIT_SELECT} - * and {@param fromState} is not {@link LauncherState#OVERVIEW_SPLIT_SELECT} - */ - private boolean isSplitSelectionState(@NonNull LauncherState fromState, - @NonNull LauncherState toState) { - return fromState != OVERVIEW_SPLIT_SELECT && toState == OVERVIEW_SPLIT_SELECT; - } - private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config, LauncherState state) { float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0; From b8ad6e08cf8934f31783f4da704342cbc46c5574 Mon Sep 17 00:00:00 2001 From: Santiago Etchebehere Date: Fri, 22 Apr 2022 21:02:22 +0000 Subject: [PATCH 15/15] Revert "Use new onStartSplitLegacy when starting split from overview" Revert submission 17779173-startSplitLegacy Reason for revert: Broken build: b/230129218 Reverted Changes: I01590e53c:Remove check for preventing re-parenting non-split... I696749f76:Use new onStartSplitLegacy when starting split fro... Change-Id: I6d81e0584bbfda3694772dcf293a4d064b2e8517 --- .../quickstep/RecentsAnimationCallbacks.java | 3 ++- .../com/android/quickstep/SystemUiProxy.java | 17 ++++------------- .../android/quickstep/TaskAnimationManager.java | 5 ++--- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index 51ae56b96d..fe31f1d8bb 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -104,7 +104,8 @@ public class RecentsAnimationCallbacks implements .map(RemoteAnimationTargetCompat::unwrap) .toArray(RemoteAnimationTarget[]::new); - RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(nonHomeApps); + RemoteAnimationTarget[] nonAppTargets = + mSystemUiProxy.onGoingToRecentsLegacy(mCancelled, nonHomeApps); RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets, wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets), diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 5e12f319ba..5ef89d309a 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -676,12 +676,14 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI * Call this when going to recents so that shell can set-up and provide appropriate leashes * for animation (eg. DividerBar). * + * @param cancel true if recents starting is being cancelled. * @return RemoteAnimationTargets of windows that need to animate but only exist in shell. */ - public RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) { + public RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, + RemoteAnimationTarget[] apps) { if (mSplitScreen != null) { try { - return mSplitScreen.onGoingToRecentsLegacy(apps); + return mSplitScreen.onGoingToRecentsLegacy(cancel, apps); } catch (RemoteException e) { Log.w(TAG, "Failed call onGoingToRecentsLegacy"); } @@ -689,17 +691,6 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI return null; } - public RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) { - if (mSplitScreen != null) { - try { - return mSplitScreen.onStartingSplitLegacy(apps); - } catch (RemoteException e) { - Log.w(TAG, "Failed call onStartingSplitLegacy"); - } - } - return null; - } - // // One handed // diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 2565674763..f094d712a1 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -177,9 +177,8 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn ((RecentsActivity) activityInterface.getCreatedActivity()).startHome(); return; } - - RemoteAnimationTarget[] nonAppTargets = - SystemUiProxy.INSTANCE.getNoCreate().onStartingSplitLegacy(nonHomeApps); + RemoteAnimationTarget[] nonAppTargets = SystemUiProxy.INSTANCE.get(mCtx) + .onGoingToRecentsLegacy(false, nonHomeApps); if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode() && activityInterface.getCreatedActivity() != null) {