From 5e19073c237963a3f69c229e3778710077613fc8 Mon Sep 17 00:00:00 2001 From: Sreyas Date: Mon, 6 Jul 2020 17:45:59 -0700 Subject: [PATCH 01/51] Fixing oav text overlap. Bug: 159240113 Change-Id: I89d8249c21cca86f21cdf57a017745237b4b6cf1 --- quickstep/res/layout/overview_actions_container.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml index e05688eca3..258f24a54e 100644 --- a/quickstep/res/layout/overview_actions_container.xml +++ b/quickstep/res/layout/overview_actions_container.xml @@ -17,9 +17,7 @@ + android:layout_gravity="center_horizontal|bottom"> Date: Thu, 16 Jul 2020 17:32:29 -0700 Subject: [PATCH 02/51] Fix bug where double swipe gets us stuck in Hint state while in Overview. With the second swipe, we never complete the swipe to Overview NoButtonNavbarToOverviewTouchController#maybeSwipeInteractionToOverviewComplete - mReachedOverview = true - mDetector.isSettlingState = false And then the second swipe starts the state transition to Hint but then it never gets completed because: 1. The animation starts 2. Gets cancelled 3. Starts again 4. Finishes, but is not marked as success since the cancel in #2 was never set back to false Bug: 160759508 Change-Id: I8c3972e6209c3d5a4a0bdd9f9b7683de18105d57 --- .../src/com/android/quickstep/BaseSwipeUpHandlerV2.java | 1 + .../src/com/android/quickstep/SwipeUpAnimationLogic.java | 1 + .../src/com/android/quickstep/views/TaskMenuView.java | 1 + src/com/android/launcher3/anim/AlphaUpdateListener.java | 3 ++- .../android/launcher3/anim/AnimationSuccessListener.java | 8 ++++++++ .../launcher3/anim/AnimatorPlaybackController.java | 1 + src/com/android/launcher3/statemanager/StateManager.java | 1 + 7 files changed, 15 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index a3f1dd4c5f..e084de1acb 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -1090,6 +1090,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); if (mActivity != null) { removeLiveTileOverlay(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java index e54a21c073..07faab7aeb 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -287,6 +287,7 @@ public abstract class SwipeUpAnimationLogic { @Override public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); mHomeAnim.dispatchOnStart(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java index 8b49f2c212..9b2048e4ac 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java @@ -282,6 +282,7 @@ public class TaskMenuView extends AbstractFloatingView { mOpenCloseAnimator.addListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); setVisibility(VISIBLE); } diff --git a/src/com/android/launcher3/anim/AlphaUpdateListener.java b/src/com/android/launcher3/anim/AlphaUpdateListener.java index eabd283699..69716eabf1 100644 --- a/src/com/android/launcher3/anim/AlphaUpdateListener.java +++ b/src/com/android/launcher3/anim/AlphaUpdateListener.java @@ -46,7 +46,8 @@ public class AlphaUpdateListener extends AnimationSuccessListener } @Override - public void onAnimationStart(Animator arg0) { + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); // We want the views to be visible for animation, so fade-in/out is visible mView.setVisibility(View.VISIBLE); } diff --git a/src/com/android/launcher3/anim/AnimationSuccessListener.java b/src/com/android/launcher3/anim/AnimationSuccessListener.java index 9905e81638..b83417c2eb 100644 --- a/src/com/android/launcher3/anim/AnimationSuccessListener.java +++ b/src/com/android/launcher3/anim/AnimationSuccessListener.java @@ -19,6 +19,8 @@ package com.android.launcher3.anim; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import androidx.annotation.CallSuper; + /** * Extension of {@link AnimatorListenerAdapter} for listening for non-cancelled animations */ @@ -26,6 +28,12 @@ public abstract class AnimationSuccessListener extends AnimatorListenerAdapter { protected boolean mCancelled = false; + @Override + @CallSuper + public void onAnimationStart(Animator animation) { + mCancelled = false; + } + @Override public void onAnimationCancel(Animator animation) { mCancelled = true; diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java index ea0ff8b687..31e0418571 100644 --- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java +++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java @@ -335,6 +335,7 @@ public class AnimatorPlaybackController implements ValueAnimator.AnimatorUpdateL @Override public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); mCancelled = false; mDispatched = false; } diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java index 60b87d984b..f1e7f166e5 100644 --- a/src/com/android/launcher3/statemanager/StateManager.java +++ b/src/com/android/launcher3/statemanager/StateManager.java @@ -315,6 +315,7 @@ public class StateManager> { @Override public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); // Change the internal state only when the transition actually starts onStateTransitionStart(state); } From e47896cb915a0d7f1e7fb14901ec4f9b6649366a Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 20 Jul 2020 12:30:02 -0700 Subject: [PATCH 03/51] Invalidate stale BgDataModel when predictions are disabled Launcher stores ItemInfos for cached predictions in list BgDataModel.cachedPredictedItems on Launcher start (LoaderTask#run). The list reused if launcher has to rebind UI. Hence, the list should be cleared if launcher receives empty predictions. Bug: 161245294 Test: Manual Change-Id: I275655d5f52f6a6e5297473dd2f642728c1964a6 --- src/com/android/launcher3/model/PredictionModel.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/com/android/launcher3/model/PredictionModel.java b/src/com/android/launcher3/model/PredictionModel.java index 1429843b7e..cb3903d4ed 100644 --- a/src/com/android/launcher3/model/PredictionModel.java +++ b/src/com/android/launcher3/model/PredictionModel.java @@ -14,6 +14,7 @@ * limitations under the License. */ package com.android.launcher3.model; + import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.content.ComponentName; @@ -24,6 +25,7 @@ import android.os.UserHandle; import androidx.annotation.AnyThread; import androidx.annotation.WorkerThread; +import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.pm.UserCache; @@ -64,18 +66,28 @@ public class PredictionModel implements ResourceBasedOverride { mUserCache = UserCache.INSTANCE.get(mContext); } + /** * Formats and stores a list of component key in device preferences. */ @AnyThread public void cachePredictionComponentKeys(List componentKeys) { MODEL_EXECUTOR.execute(() -> { + LauncherAppState appState = LauncherAppState.getInstance(mContext); StringBuilder builder = new StringBuilder(); int count = Math.min(componentKeys.size(), MAX_CACHE_ITEMS); for (int i = 0; i < count; i++) { builder.append(serializeComponentKeyToString(componentKeys.get(i))); builder.append("\n"); } + if (componentKeys.isEmpty() /* should invalidate loader items */) { + appState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() { + @Override + public void execute(LauncherAppState app, BgDataModel model, AllAppsList apps) { + model.cachedPredictedItems.clear(); + } + }); + } mDevicePrefs.edit().putString(CACHED_ITEMS_KEY, builder.toString()).apply(); }); } From 453475d568f8a0223b8e7e1bc2dc9472eb487551 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 20 Jul 2020 12:46:18 -0700 Subject: [PATCH 04/51] Fix hotseat file log name formatting Bug: 161001172 Test: Manual Change-Id: Ia03eeb897003267ce608430c94b3b01876939234 --- .../com/android/launcher3/hybridhotseat/HotseatFileLog.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java index c15a5963f6..20e1edc05f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java @@ -71,10 +71,9 @@ public class HotseatFileLog { } private PrintWriter getWriter() { - String fName = FILE_NAME_PREFIX + (LOG_DAYS % 10); - if (fName.equals(mFileName)) return mCurrentWriter; - Calendar cal = Calendar.getInstance(); + String fName = FILE_NAME_PREFIX + (cal.get(Calendar.DAY_OF_YEAR) % 10); + if (fName.equals(mFileName)) return mCurrentWriter; boolean append = false; File logFile = new File(mLogsDir, fName); From a92c6bb53121c23ef3c4e192cbbfcc921e8c41da Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 20 Jul 2020 14:00:14 -0700 Subject: [PATCH 05/51] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I2ac85ce81a99d87d613ed1490c591d90323889f2 --- quickstep/res/values-ar/strings.xml | 2 +- quickstep/res/values-bg/strings.xml | 2 +- quickstep/res/values-bn/strings.xml | 2 +- quickstep/res/values-ca/strings.xml | 8 ++++---- quickstep/res/values-de/strings.xml | 6 +++--- quickstep/res/values-es-rUS/strings.xml | 2 +- quickstep/res/values-es/strings.xml | 10 +++++----- quickstep/res/values-fr-rCA/strings.xml | 2 +- quickstep/res/values-hi/strings.xml | 2 +- quickstep/res/values-hr/strings.xml | 10 +++++----- quickstep/res/values-is/strings.xml | 2 +- quickstep/res/values-it/strings.xml | 2 +- quickstep/res/values-kk/strings.xml | 10 +++++----- quickstep/res/values-km/strings.xml | 2 +- quickstep/res/values-lv/strings.xml | 2 +- quickstep/res/values-mn/strings.xml | 4 ++-- quickstep/res/values-my/strings.xml | 4 ++-- quickstep/res/values-nb/strings.xml | 2 +- quickstep/res/values-ne/strings.xml | 2 +- quickstep/res/values-pt-rPT/strings.xml | 2 +- quickstep/res/values-sq/strings.xml | 2 +- quickstep/res/values-sv/strings.xml | 6 +++--- quickstep/res/values-sw/strings.xml | 4 ++-- quickstep/res/values-te/strings.xml | 2 +- quickstep/res/values-th/strings.xml | 8 ++++---- quickstep/res/values-tl/strings.xml | 4 ++-- quickstep/res/values-uz/strings.xml | 10 +++++----- quickstep/res/values-zh-rCN/strings.xml | 4 ++-- quickstep/res/values-zh-rHK/strings.xml | 4 ++-- quickstep/res/values-zh-rTW/strings.xml | 2 +- 30 files changed, 62 insertions(+), 62 deletions(-) diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 780104b326..c2348ecf50 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -34,7 +34,7 @@ "تطبيقاتك المتوقّعة" "رؤية التطبيقات المقترحة في الصف السفلي من الشاشة الرئيسية" "رؤية التطبيقات المقترحة في صف التطبيقات المفضّلة في الشاشة الرئيسية" - "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى سلاسل الإجراءات. سيتم نقل التطبيقات من الصف السفلي للعلوي في الشاشة الرئيسية." + "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى استخدامك الروتيني. وسيتم نقل التطبيقات من الصف السفلي في الشاشة الرئيسية إلى الصف الأعلى." "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى سلاسل الإجراءات. سيتم نقل التطبيقات من صف التطبيقات المفضّلة إلى الشاشة الرئيسية." "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى سلاسل الإجراءات. سيتم نقل التطبيقات من الصف الأسفل إلى مجلد جديد." "رؤية تطبيقات مقترحة" diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index db7006f564..5484bc9e8b 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -43,7 +43,7 @@ "Най-използваните приложения се показват тук и се променят въз основа на поредиците" "За да получавате предложения за приложения, с плъзгане премахнете приложенията от най-долния ред" "Предложенията за приложения са добавени на празното място" - "Функцията „Предложения за приложения“ е активирана" + "Предложенията за приложения са активирани" "Функцията „Предложения за приложения“ е деактивирана" "Предвидено приложение: %1$s" "Споделяне" diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml index b230ec5611..9212a4b827 100644 --- a/quickstep/res/values-bn/strings.xml +++ b/quickstep/res/values-bn/strings.xml @@ -47,6 +47,6 @@ "অ্যাপ সাজেশন বন্ধ করা আছে" "আপনার প্রয়োজন হতে পারে এমন অ্যাপ: %1$s" "শেয়ার করুন" - "স্ক্রিনশট" + "স্ক্রিনশট নিন" "এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি" diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index 657239ce0d..4b0acca10e 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -34,13 +34,13 @@ "Prediccions d\'aplicacions" "Obtén suggeriments d\'aplicacions a la fila inferior de la pantalla d\'inici" "Obtén suggeriments d\'aplicacions a la fila Preferides de la teva pantalla d\'inici" - "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció de la teva rutina. Les aplicacions de la fila inferior pujaran a la pantalla d\'inici." - "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció de la teva rutina. Les aplicacions de la fila Preferides es mouran a la teva pantalla d\'inici." - "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció de la teva rutina. Les aplicacions de la fila inferior es mouran a una carpeta nova." + "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció dels teus hàbits. Les aplicacions de la fila inferior pujaran a la pantalla d\'inici." + "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció dels teus hàbits. Les aplicacions de la fila Preferides es mouran a la teva pantalla d\'inici." + "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció dels teus hàbits. Les aplicacions de la fila inferior es mouran a una carpeta nova." "Mostra suggeriments d\'aplicacions" "No, gràcies" "Configuració" - "Les aplicacions que més utilitzes apareixen aquí i poden variar en funció de la teva rutina" + "Les aplicacions que més utilitzes apareixen aquí i poden variar en funció dels teus hàbits" "Arrossega les aplicacions fora de la fila inferior per obtenir suggeriments d\'aplicacions" "S\'han afegit suggeriments d\'aplicacions en un espai buit" "Els suggeriments d\'aplicacions estan activats" diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index 17ba8ad457..b51f04de98 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -35,17 +35,17 @@ "Lass dir in der unteren Reihe auf deinem Startbildschirm Vorschläge für Apps anzeigen" "Lass dir in der Favoritenleiste auf dem Startbildschirm App-Vorschläge anzeigen" "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge werden deiner Nutzung entsprechend laufend angepasst. Apps in der unteren Reihe werden nach oben auf den Startbildschirm verschoben." - "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge richten sich nach deiner gewöhnlichen Nutzung. Apps der Favoritenleiste werden auf den Startbildschirm verschoben." + "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge werden deiner Nutzung entsprechend laufend angepasst. Apps der Favoritenleiste werden auf den Startbildschirm verschoben." "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge werden deiner Nutzung entsprechend laufend angepasst. Apps in der unteren Reihe werden in einen neuen Ordner verschoben." "App-Vorschläge erhalten" "Nein danke" "Einstellungen" "Hier erscheinen die meistverwendeten Apps. Die Angaben können sich je nach deiner gewöhnlichen Nutzung ändern" - "Ziehe Apps aus der unteren Reihe heraus, um Vorschläge für Apps zu bekommen" + "Ziehe Apps aus der unteren Reihe heraus, um Vorschläge für Apps zu erhalten" "App-Vorschläge in freiem Bereich hinzugefügt" "Funktion \"App-Vorschläge\" aktiviert" "Funktion \"App-Vorschläge\" deaktiviert" - "App-Vorhersage: %1$s" + "Vorgeschlagene App: %1$s" "Teilen" "Screenshot" "Die App oder deine Organisation lässt diese Aktion nicht zu" diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index d62c8b3c82..1191becfa1 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -43,7 +43,7 @@ "Las apps que más se usan se muestran aquí y cambian según las rutinas" "Arrastra apps fuera de la fila inferior para obtener sugerencias" "Se agregaron sugerencias de aplicaciones a un espacio vacío" - "Las sugerencias de aplicaciones están habilitadas" + "Sugerencias de apps habilitadas" "Las sugerencias de aplicaciones están inhabilitadas" "Predicción de app: %1$s" "Compartir" diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index 1a8cbd2388..a2b930d068 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -32,12 +32,12 @@ "Sugerencias de aplicaciones" "Todas las aplicaciones" "Predicción de aplicaciones" - "Haz que aparezcan sugerencias de aplicaciones en la fila inferior de la pantalla de inicio" + "Obtén sugerencias de aplicaciones en la fila inferior de la pantalla de inicio" "Recibe sugerencias de aplicaciones en la fila de aplicaciones favoritas de la pantalla de inicio" - "Accede fácilmente desde la pantalla de inicio a las aplicaciones que más usas. Las sugerencias cambiarán según tus rutinas. Las aplicaciones de la fila inferior pasarán a mostrarse en la pantalla de inicio." - "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus rutinas. Las aplicaciones de la fila de aplicaciones favoritas se moverán a la pantalla de inicio." - "Accede fácilmente desde la pantalla de inicio a las aplicaciones que más usas. Las sugerencias cambiarán según tus rutinas. Las aplicaciones de la fila inferior se pondrán en una carpeta nueva." - "Ver sugerencias de aplicaciones" + "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus hábitos. Las aplicaciones de la fila inferior pasarán a mostrarse en la pantalla de inicio." + "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus hábitos. Las aplicaciones de la fila de aplicaciones favoritas se moverán a la pantalla de inicio." + "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus hábitos. Las aplicaciones de la fila inferior se pondrán en una carpeta nueva." + "Sí, obtener sugerencias" "No, gracias" "Ajustes" "Las aplicaciones que más usas aparecen aquí, y van variando según tus rutinas" diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index 8ae00237d2..46096f5263 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -32,7 +32,7 @@ "Suggestions d\'applications" "Toutes les applications" "Vos prédictions d\'applications" - "Obtenez des applications suggérées dans la rangée du bas de votre écran d\'accueil" + "Obtenir des suggestions d\'applications dans la rangée du bas de votre écran d\'accueil" "Retrouvez des suggestions d\'applications dans la rangée des favoris de votre écran d\'accueil" "Accédez facilement aux applications que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applications dans la rangée du bas seront déplacées vers votre écran d\'accueil." "Accédez facilement aux applications que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applications dans la rangée des favoris seront déplacées vers votre écran d\'accueil." diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 8bf208f1aa..d98cc770a1 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -36,7 +36,7 @@ "अपने होम स्क्रीन की सबसे नीचे वाली पंक्ति में पसंदीदा ऐप्लिकेशन के सुझाव पाएं" "आप जिन ऐप्लिकेशन का ज़्यादा इस्तेमाल करते हैं उन्हें सीधा अपने होम स्क्रीन पर पाएं. ऐप्लिकेशन इस्तेमाल करने के आपके रूटीन के हिसाब से सुझाव बदलते रहते हैं. नीचे की पंक्ति के ऐप्लिकेशन होम स्क्रीन पर आ जाएंगे." "सबसे ज़्यादा इस्तेमाल होने वाले ऐप्लिकेशन सीधे होम स्क्रीन पर देखें. आप ऐप्लिकेशन का कितना इस्तेमाल कर रहे हैं, उसके हिसाब से सुझाव बदलते रहते हैं. आपके पसंदीदा ऐप्लिकेशन, होम स्क्रीन पर नीचे की पंक्ति में दिखाई देंगे." - "सबसे ज़्यादा इस्तेमाल होने वाले ऐप्लिकेशन, सीधे होम स्क्रीन पर देखें. ऐप्लिकेशन इस्तेमाल करने के आपके रूटीन के हिसाब से सुझाव बदलते रहते हैं. नीचे की पंक्ति के ऐप्लिकेशन एक नए फ़ोल्डर में चले जाएंगे." + "सबसे ज़्यादा इस्तेमाल होने वाले ऐप्लिकेशन, सीधे होम स्क्रीन पर पाएं. आपके ऐप्लिकेशन इस्तेमाल करने के रूटीन के हिसाब से सुझाव बदलते रहते हैं. नीचे की पंक्ति के ऐप्लिकेशन एक नए फ़ोल्डर में चले जाएंगे." "ऐप्लिकेशन के बारे में सुझाव पाएं" "रहने दें" "सेटिंग" diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index 21920a7113..a026ef8012 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -32,21 +32,21 @@ "Predložene aplikacije" "Sve aplikacije" "Vaše predviđene aplikacije" - "Prikažite predložene aplikacije u donjem retku početnog zaslona" + "Prijedloge aplikacija vidjet ćete u donjem retku početnog zaslona" "Primajte prijedloge aplikacija u retku omiljenih na početnom zaslonu" "Lako pristupite najčešće upotrebljavanim aplikacijama s početnog zaslona. Prijedlozi će se mijenjati na temelju vaših rutina. Aplikacije iz donjeg retka pomaknut će se na početni zaslon." "Lako pristupite najčešće upotrebljavanim aplikacijama s početnog zaslona. Prijedlozi će se mijenjati na temelju vaših rutina. Aplikacije koje se nalaze u retku omiljenih pomaknut će se na početni zaslon." "Lako pristupite najčešće upotrebljavanim aplikacijama s početnog zaslona. Prijedlozi će se mijenjati na temelju vaših rutina. Aplikacije iz donjeg retka pomaknut će se u novu mapu." - "Prikaži predložene aplikacije" + "Predloži mi aplikacije" "Ne, hvala" "Postavke" "Ovdje se prikazuju najčešće upotrebljavane aplikacije i mijenjaju se na temelju rutina" "Povucite aplikacije iz donjeg retka da biste dobili prijedloge aplikacija" "Predložene aplikacije dodane u prazan prostor" - "Predlaganje aplikacija je omogućeno" - "Predlaganje aplikacija je onemogućeno" + "Predlaganje apl. omogućeno" + "Predlaganje apl. onemogućeno" "Predviđena aplikacija: %1$s" - "Udio" + "Podijeli" "Snimka zaslona" "Aplikacija ili vaša organizacija ne dopuštaju ovu radnju" diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index f8b63fb64a..824fd7fb31 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -43,7 +43,7 @@ "Mest notuðu forritin birtast hér og breytast í samræmi við rútínur" "Dragðu forrit af neðstu röð til að fá tillögð forrit" "Tillögðum forritum bætt við autt svæði" - "Kveikt á tillögðum forritum" + "Kveikt á tillögum að forritum" "Slökkt er á tillögðum forritum" "Tillaga að forriti: %1$s" "Deila" diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index e0a78b2301..4038966102 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -41,7 +41,7 @@ "No, grazie" "Impostazioni" "Le app più utilizzate vengono visualizzate qui e variano in base alle routine" - "Trascina le app fuori dalla fila in basso per vedere le app suggerite" + "Trascina le app fuori dalla riga inferiore per visualizzare le app suggerite" "App suggerite aggiunte a uno spazio vuoto" "La funzionalità app suggerite è attiva" "La funzionalità app suggerite è disattivata" diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index 1bb1684dde..fb76660b1f 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -32,16 +32,16 @@ "Ұсынылған қолданбалар" "Барлық қолданбалар" "Ұсынылатын қолданбалар" - "Негізгі экранның төменгі жолында ұсынылған қолданбаларды алу" + "Негізгі экранның төменгі жолында қолданбаларды ұсыну" "Ұсынылған қолданбалар негізгі экранда таңдаулылар арасында көрсетілетін болады" - "Жиі пайдаланылатын қолданбаларға негізгі экраннан оңай кіріңіз. Ұсыныстар әрекеттер тізімі негізінде өзгереді. Төменгі жолдағы қолданбалар негізгі экраныңызға қарай жоғары жылжиды." + "Жиі пайдаланылатын қолданбаларға негізгі экраннан кіруге болады. Ұсыныстар күнделікті әрекеттеріңізге сәйкес өзгереді. Төменгі қатардағы қолданбалар негізгі экранға қарай жоғары жылжиды." "Жиі пайдаланылатын қолданбаларға негізгі экраннан оңай кіре аласыз. Ұсыныстар күнделікті әрекеттеріңізге сәйкес өзгереді. Таңдаулылар жолындағы қолданбалар негізгі экранға ауысады." - "Жиі пайдаланылатын қолданбаларға негізгі экраннан оңай кіріңіз. Ұсыныстар әрекеттер тізімі негізінде өзгереді. Төмендегі қолданбалар жаңа қалтаға жылжиды." + "Жиі пайдаланылатын қолданбаларға негізгі экраннан кіруге болады. Ұсыныстар күнделікті әрекеттеріңізге сәйкес өзгереді. Төменгі қатардағы қолданбалар жаңа қалтаға жылжиды." "Ұсынылған қолданбаларды көру" "Жоқ, рақмет" "Параметрлер" - "Жиі пайдаланылатын қолданбалар осы жерде көрсетіледі және әрекеттер тізімі негізінде өзгереді." - "Ұсынылған қолданбаларды алу үшін қолданбаларды төменгі жолдан жылжытыңыз." + "Жиі пайдаланылатын қолданбалар осы жерде көрсетіледі. Олар күнделікті әрекеттеріңізге сәйкес өзгереді." + "Ұсынылған қолданбаларды көру үшін төменгі қатардан керектерін сүйреп шығарыңыз." "Ұсынылған қолданбалар бос орынға қосылды." "\"Ұсынылған қолданбалар\" функциясы қосулы." "\"Ұсынылған қолданбалар\" функциясы өшірулі." diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index dd2fbacbed..3c3fccc022 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -37,7 +37,7 @@ "ចូលប្រើ​កម្មវិធី​ដែលអ្នកប្រើ​ញឹកញាប់បំផុត​បានយ៉ាង​ងាយស្រួល​នៅលើ​អេក្រង់ដើម​ផ្ទាល់។ ការណែនាំ​នឹងប្រែប្រួល​ទៅតាម​ទម្លាប់​របស់អ្នក។ កម្មវិធី​នៅជួរ​ខាងក្រោម​នឹងផ្លាស់ទីឡើង​ទៅអេក្រង់ដើម​របស់អ្នក។" "ចូលប្រើ​កម្មវិធី​ដែលអ្នកប្រើ​ញឹកញាប់បំផុត​បានយ៉ាង​ងាយស្រួល​នៅលើ​អេក្រង់ដើមដោយផ្ទាល់។ ការណែនាំ​នឹងប្រែប្រួល​ទៅតាម​ទម្លាប់​របស់អ្នក។ កម្មវិធី​នៅក្នុង​ជួរដេក​សំណព្វ​នឹងផ្លាស់ទី​ទៅអេក្រង់ដើម​របស់អ្នក។" "ចូលប្រើ​កម្មវិធី​ដែលអ្នកប្រើ​ញឹកញាប់បំផុត​បានយ៉ាង​ងាយស្រួល​នៅលើ​អេក្រង់ដើម​ផ្ទាល់។ ការណែនាំ​នឹងប្រែប្រួល​ទៅតាម​ទម្លាប់​របស់អ្នក។ កម្មវិធី​នៅជួរ​ខាងក្រោម​នឹងផ្លាស់ទី​ទៅថតថ្មី។" - "ទទួលបាន​ការណែនាំ​កម្មវិធី" + "ទទួលការណែនាំ​កម្មវិធី" "ទេ អរគុណ" "ការកំណត់" "កម្មវិធី​ដែលប្រើ​ញឹកញាប់បំផុត​បង្ហាញ​នៅទីនេះ និង​ប្រែប្រួល​ទៅតាមទម្លាប់" diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml index 82c96fe213..65620c4683 100644 --- a/quickstep/res/values-lv/strings.xml +++ b/quickstep/res/values-lv/strings.xml @@ -47,6 +47,6 @@ "Ieteicamās lietotnes ir atspējotas" "Prognozētā lietotne: %1$s" "Kopīgot" - "Izveidot ekrānuzņēmumu" + "Veikt ekrānuzņēmumu" "Lietotne vai jūsu organizācija neatļauj veikt šo darbību." diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml index f4b9d43e6e..ba083ef0e0 100644 --- a/quickstep/res/values-mn/strings.xml +++ b/quickstep/res/values-mn/strings.xml @@ -34,9 +34,9 @@ "Таны таамагласан аппууд" "Үндсэн нүүрнийхээ доод мөрөнд санал болгож буй аппуудыг аваарай" "Үндсэн нүүрний дуртай мөрнөөсөө санал болгож буй аппуудыг аваарай" - "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөр дэх аппуудыг таны Үндсэн нүүр лүү дээш зөөнө." + "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрнээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөрөнд буй аппуудыг таны Үндсэн нүүр лүү дээш зөөнө." "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрнээсээ хялбархан хандаарай. Санал болголтыг таны хэвшлээс хамааран өөрчилнө. Дуртай мөрөнд буй аппуудыг таны үндсэн нүүр лүү зөөнө." - "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөр дэх аппуудыг шинэ фолдер луу зөөнө." + "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрнээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөрөнд буй аппуудыг шинэ фолдер луу зөөнө." "Санал болгож буй аппуудыг авах" "Үгүй, баярлалаа" "Тохиргоо" diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index 0dc3a165b5..a18c1c451d 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -34,7 +34,7 @@ "သင်၏ ခန့်မှန်းအက်ပ်များ" "သင်၏ \'ပင်မစာမျက်နှာ\' အောက်ခြေအတန်းတွင် အက်ပ်အကြံပြုချက်များ ရယူခြင်း" "သင်၏ \'ပင်မစာမျက်နှာ\' ၏ အနှစ်သက်ဆုံးများအတန်းတွင် အက်ပ်အကြံပြုချက်များ ရယူခြင်း" - "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ သုံးနိုင်သည်။ သင်၏ ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အောက်ခြေအတန်းရှိ အက်ပ်များကို သင်၏ \'ပင်မစာမျက်နှာ\' သို့ရွှေ့လိုက်မည်။" + "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ ဖွင့်နိုင်သည်။ သင်၏ ပုံမှန်လုပ်ဆောင်ချက်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အောက်ခြေအတန်းရှိ အက်ပ်များကို သင်၏ \'ပင်မစာမျက်နှာ\' သို့ရွှေ့လိုက်မည်။" "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ သုံးနိုင်သည်။ သင်၏ ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အနှစ်သက်ဆုံးများအတန်းရှိ အက်ပ်များကို သင်၏ \'ပင်မစာမျက်နှာ\' သို့ရွှေ့လိုက်မည်။" "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ သုံးနိုင်သည်။ သင်၏ ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အောက်ခြေအတန်းရှိ အက်ပ်များကို ဖိုင်တွဲအသစ်သို့ ရွှေ့လိုက်မည်။" "အက်ပ်အကြံပြုချက်များ ရယူရန်" @@ -43,7 +43,7 @@ "အသုံးအများဆုံးအက်ပ်များကို ဤနေရာတွင် ပြပြီး ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ ပြောင်းလဲသည်" "အက်ပ်အကြံပြုချက်များ ရယူရန် အောက်ခြေအတန်းရှိ အက်ပ်များကို ဖိဆွဲထုတ်လိုက်ပါ" "အက်ပ်အကြံပြုချက်များကို နေရာလွတ်သို့ ထည့်လိုက်သည်" - "အက်ပ်အကြံပြုချက်များကို ဖွင့်ထားသည်" + "အက်ပ်အကြံပြုချက်များ ဖွင့်ထားသည်" "အက်ပ်အကြံပြုချက်များကို ပိတ်ထားသည်" "ကြိုတင်မှန်းဆထားသော အက်ပ်− %1$s" "မျှဝေရန်" diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index 161612212b..161d1c4f97 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -43,7 +43,7 @@ "Appene som brukes oftest, vises her og endres basert på rutiner" "Dra appene vekk fra den nederste raden for å få appforslag." "Appforslag er lagt til på et tomt område" - "Appforslag er slått på" + "Appforslag er på" "Appforslag er slått av" "Foreslått app: %1$s" "Del" diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index c8c35a8c80..99a22f922f 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -36,7 +36,7 @@ "आफ्नो होम स्क्रिनको मन पर्ने नामक पङ्क्तिमा सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्" "गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एप सजिलै चलाउनुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू तपाईंको गृह स्क्रिनको सिरानमा सर्ने छन्।" "आफूले सबैभन्दा बढी प्रयोग गर्ने एपहरू गृह स्क्रिनबाटै सजिलैसँग खोल्नुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंको दिनचर्याअनुसार बदलिने छ। मन पर्ने नामक पङ्क्तिमा रहेका एपहरू सारेर होम स्क्रिनमा लगिने छन्।" - "गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एपमाथि सजिलैसँग पहुँच राख्नुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू एउटा नयाँ फोल्डरमा सर्ने छन्।" + "गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एप सजिलै चलाउनुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू एउटा नयाँ फोल्डरमा सर्ने छन्।" "सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्" "पर्दैन धन्यवाद" "सेटिङ" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index 5ac7287f74..cff747fc84 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -25,7 +25,7 @@ "Nenhum item recente" "Definições de utilização de aplicações" "Limpar tudo" - "Aplicações recentes" + "Apps recentes" "%1$s, %2$s" "< 1 minuto" "Resta(m) %1$s hoje." diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml index a4233446ee..a144b92aac 100644 --- a/quickstep/res/values-sq/strings.xml +++ b/quickstep/res/values-sq/strings.xml @@ -43,7 +43,7 @@ "Aplikacionet më të përdorura shfaqen këtu dhe ndryshojnë bazuar në rutinat" "Zvarrit aplikacionet jashtë rreshtit të poshtëm për të marrë aplikacione të sugjeruara" "Aplikacionet e sugjeruara u shtuan në hapësirën bosh" - "Sugjerimet e aplikacioneve janë aktivizuar" + "Aplikacionet e sugjeruara janë aktivizuar" "Sugjerimet e aplikacioneve janë çaktivizuar" "Aplikacioni i parashikuar: %1$s" "Ndaj" diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index 42d7327d1b..8252fec2de 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -34,9 +34,9 @@ "Föreslagna appar" "Få appförslag på den nedersta raden på startskärmen" "Få appförslag på raden Favoriter på startskärmen" - "Kom enkelt åt de appar du använder mest direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas upp till startskärmen." - "Kom enkelt åt de appar du använder mest direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på raden Favoriter flyttas till startskärmen." - "Kom enkelt åt de appar du använder mest direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas till en ny mapp." + "Kom enkelt åt de appar du använder mest, direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas upp till startskärmen." + "Kom enkelt åt de appar du använder mest, direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på raden Favoriter flyttas till startskärmen." + "Kom enkelt åt de appar du använder mest, direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas till en ny mapp." "Få appförslag" "Nej tack" "Inställningar" diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml index 3e949e8ee6..778d558481 100644 --- a/quickstep/res/values-sw/strings.xml +++ b/quickstep/res/values-sw/strings.xml @@ -36,14 +36,14 @@ "Pata mapendekezo ya programu katika safu ya vipendwa ya Skrini yako ya kwanza" "Fikia kwa urahisi programu unazotumia sana moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye sehemu ya chini zitahamishiwa kwenye Skrini yako ya kwanza." "Fikia kwa urahisi programu unazotumia sana moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na utumiaji wako. Programu zilizo katika safu ya vipendwa zitahamishiwa kwenye Skrini yako ya kwanza." - "Fikia kwa urahisi programu unazotumia zaidi, moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye safu mlalo ya chini zitahamishiwa kwenye folda mpya." + "Fikia kwa urahisi programu unazotumia zaidi, moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye safu ya chini zitahamishiwa kwenye folda mpya." "Pata mapendekezo ya programu" "Hapana" "Mipangilio" "Programu zinazotumiwa zaidi huonekana hapa na hubadilika kulingana na ratiba" "Buruta programu kutoka kwenye safu ya chini ili upate mapendekezo ya programu" "Mapendekezo ya programu yamewekwa kwenye nafasi isiyo na kitu" - "Umewasha mapendekezo ya programu" + "Mapendekezo ya programu yamewashwa" "Umezima mapendekezo ya programu" "Programu iliyotabiriwa: %1$s" "Shiriki" diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index 35c455fb2b..b381af994b 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -43,7 +43,7 @@ "ఎక్కువగా ఉపయోగించిన యాప్‌లు ఇక్కడ కనిపిస్తాయి, అవి రోజువారీ కార్యకలాపాలను బట్టి మారుతూ ఉంటాయి" "యాప్ సలహాలను పొందడానికి దిగువ వరుస నుండి యాప్‌లను లాగండి" "యాప్ సూచ‌న‌లు ఖాళీ స్పేస్‌కు జోడించబడ్డాయి" - "యాప్ సూచ‌న‌లు ఎనేబుల్ చేయబడ్డాయి" + "యాప్ సలహాలు ఎనేబుల్ చేయబడ్డాయి" "యాప్ సూచ‌న‌లు డిజేబుల్‌ చేయబడ్డాయి" "సూచించబడిన యాప్: %1$s" "షేర్ చేయండి" diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml index e81a97615e..42e0c5858f 100644 --- a/quickstep/res/values-th/strings.xml +++ b/quickstep/res/values-th/strings.xml @@ -32,18 +32,18 @@ "คำแนะนำเกี่ยวกับแอป" "แอปทั้งหมด" "แอปที่คาดการณ์ไว้" - "รับคำแนะนำเกี่ยวกับแอปที่แถวล่างของหน้าจอหลัก" + "ดูแอปแนะนำที่แถวล่างของหน้าจอหลัก" "รับคำแนะนำเกี่ยวกับแอปในแถวรายการโปรดของหน้าจอหลัก" "เข้าถึงแอปที่คุณใช้มากที่สุดได้อย่างง่ายดายจากหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามแอปที่ใช้งานเป็นประจำ แอปในแถวล่างจะย้ายขึ้นมาอยู่ในหน้าจอหลัก" "เข้าถึงแอปที่ใช้มากที่สุดได้อย่างง่ายดายในหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามการใช้งานประจำ แอปในแถวรายการโปรดจะย้ายไปอยู่ในหน้าจอหลัก" "เข้าถึงแอปที่คุณใช้มากที่สุดได้อย่างง่ายดายจากหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามแอปที่ใช้งานเป็นประจำ แอปในแถวล่างจะย้ายไปอยู่ในโฟลเดอร์ใหม่" - "รับคำแนะนำเกี่ยวกับแอป" + "ดูแอปแนะนำ" "ไม่เป็นไร" "การตั้งค่า" "แอปที่ใช้มากที่สุดจะปรากฎที่นี่และจะเปลี่ยนไปตามการใช้งานประจำ" - "ลากแอปออกจากแถวล่างเพื่อดูคำแนะนำเกี่ยวกับแอป" + "ลากแอปออกจากแถวล่างเพื่อดูแอปแนะนำ" "เพิ่มคำแนะนำเกี่ยวกับแอปในพื้นที่ว่างแล้ว" - "เปิดใช้คำแนะนำเกี่ยวกับแอปอยู่" + "เปิดใช้คำแนะนำเกี่ยวกับแอปแล้ว" "ปิดใช้คำแนะนำเกี่ยวกับแอปอยู่" "แอปที่คาดว่าจะใช้: %1$s" "แชร์" diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml index 5d00b8b6d9..54aa564904 100644 --- a/quickstep/res/values-tl/strings.xml +++ b/quickstep/res/values-tl/strings.xml @@ -32,7 +32,7 @@ "Mga iminumungkahing app" "Lahat ng app" "Iyong mga nahulaang app" - "Makakuha ng mga iminumungkahing app sa ibabang row ng iyong Home screen" + "Makakuha ng mga suhestyon sa app sa ibabang row ng iyong Home screen" "Makakuha ng mga iminumungkahing app sa row ng mga paborito ng iyong Home screen" "Madaling ma-access ang mga pinakaginagamit mong app nang direkta sa Home screen. Magbabago ang mga suhestyon batay sa iyong mga routine. Mapupunta sa iyong Home screen ang mga app na nasa ibabang row." "Madaling ma-access ang mga pinakaginagamit mong app nang direkta sa Home screen. Magbabago ang mga suhestyon batay sa iyong mga routine. Mapupunta sa iyong Home screen ang mga app sa row ng mga paborito." @@ -41,7 +41,7 @@ "Huwag na lang" "Mga Setting" "Ipinapakita ang mga pinakaginagamit na app dito, at nababago ito batay sa mga routine" - "I-drag ang mga app mula sa ibabang row para makakuha ng mga iminumungkahing app" + "I-drag ang mga app mula sa ibabang row para makakuha ng mga suhestyon sa app" "Idinagdag sa bakanteng espasyo ang mga iminumungkahing app" "Naka-enable ang mga iminumungkahing app" "Naka-disable ang mga iminumungkahing app" diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml index d6c0e7994a..737bd20fa0 100644 --- a/quickstep/res/values-uz/strings.xml +++ b/quickstep/res/values-uz/strings.xml @@ -32,18 +32,18 @@ "Tavsiya etiladigan ilovalar" "Barcha ilovalar" "Taklif qilingan ilovalaringiz" - "Ilova takliflari bosh ekran pastidagi qatorda chiqadi" - "Saralanganlar qatorida Bosh ekrandagi ilovalar taklif qilinsin" + "Tavsiya etiladigan ilovalar bosh ekran pastidagi qatorda chiqadi" + "Tavsiya etiladigan ilovalar bosh ekranning saralanganlar ruknida chiqadi" "Faol ishlatiladigan ilovalarga bosh ekrandan osongina kira olasiz. Tavsiyalar oxirgi faoliyatingiz asosida almashib boradi. Pastki qatordagi ilovalar bosh ekranga chiqadi." "Faol ishlatiladigan ilovalarga bosh ekrandan osongina kira olasiz. Tavsiyalar oxirgi faoliyatingiz asosida almashib boradi. Saralanganlar qatoridagi ilovalar bosh ekranga chiqadi." "Faol ishlatiladigan ilovalarga bosh ekrandan osongina kira olasiz. Tavsiyalar oxirgi faoliyatingiz asosida almashib boradi. Pastki qatordagi ilovalar yangi jildga chiqadi." - "Ilova takliflarini olish" + "Tavsiyalarni chiqarish" "Kerak emas" "Sozlamalar" "Faol ishlatiladigan ilovalar bu yerda chiqadi va oxirgi faoliyatingiz asosida almashadi" - "Takliflar olish uchun ilovalarni pastki qatordan tashqariga oling" + "Tavsiyalar olish uchun ilovalarni pastki qatordan tashqariga oling" "Tavsiya etilgan ilovalarni ochiq joylarga kiriting" - "Endi ilova takliflari chiqadi" + "Ilova tavsiyalari yoqildi" "Endi ilova takliflari chiqmaydi" "Taklif etilgan ilova: %1$s" "Ulashish" diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index 1a06aad744..ed65978233 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -32,7 +32,7 @@ "应用建议" "所有应用" "您的预测应用" - "在主屏幕的最下面一排获取应用建议" + "在主屏幕底部获取应用建议" "在主屏幕的收藏行获取应用建议" "直接在主屏幕上轻松访问您最常用的应用。系统会根据您的日常安排提供不同的建议。最下面一排中的应用会向上移动到主屏幕中。" "直接在主屏幕上轻松访问您最常用的应用。建议会因您的日常安排而变化,收藏行中的应用将移到主屏幕上。" @@ -41,7 +41,7 @@ "不用了" "设置" "最常用的应用会显示在此处,显示的项目会根据日常安排而发生变化" - "将应用从最下面一排拖至别处,以获取应用建议" + "将应用拖离底部,以获取应用建议" "应用建议已添加到空白区域" "已启用应用建议" "已停用应用建议" diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index dc9caadd90..d3fd7eefc3 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -36,12 +36,12 @@ "在主畫面「我的最愛」列取得應用程式建議" "在主畫面輕鬆存取常用的應用程式。系統會根據您的日常安排更改建議,並將底部的應用程式移到主畫面。" "在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,「我的最愛」列中的應用程式會移至主畫面。" - "在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,並將底部應用程式列的應用程式移至新資料夾。" + "在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,並將底列的應用程式移至新資料夾。" "取得應用程式建議" "不用了,謝謝" "設定" "最常用的應用程式會在這裡顯示,並會根據日常安排變更" - "將應用程式從底部應用程式列拖曳出來,即可獲取應用程式建議" + "將應用程式從底列拖曳出來,即可獲取應用程式建議" "系統會將應用程式建議新增至空白位置" "已啟用應用程式建議" "已停用應用程式建議" diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index d62629090e..3545a16769 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -41,7 +41,7 @@ "不用了,謝謝" "設定" "最常使用的應用程式會顯示在這裡,顯示的項目會根據日常安排有所不同" - "將應用程式從底部列向外拖曳即可取得應用程式建議" + "將應用程式從底部列向外拖曳,即可取得應用程式建議" "應用程式建議已新增到空白位置" "應用程式建議功能已啟用" "應用程式建議功能已停用" From d5821326f82c984f4759da525faf5fe8c8f6e760 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 20 Jul 2020 14:00:53 -0700 Subject: [PATCH 06/51] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I344fea4e320a851f0d04a3308c9f7f2dca4c934e --- quickstep/res/values-ar/strings.xml | 2 +- quickstep/res/values-bg/strings.xml | 2 +- quickstep/res/values-bn/strings.xml | 2 +- quickstep/res/values-ca/strings.xml | 8 ++++---- quickstep/res/values-de/strings.xml | 6 +++--- quickstep/res/values-es-rUS/strings.xml | 2 +- quickstep/res/values-es/strings.xml | 10 +++++----- quickstep/res/values-fr-rCA/strings.xml | 2 +- quickstep/res/values-hi/strings.xml | 2 +- quickstep/res/values-hr/strings.xml | 10 +++++----- quickstep/res/values-is/strings.xml | 2 +- quickstep/res/values-it/strings.xml | 2 +- quickstep/res/values-kk/strings.xml | 10 +++++----- quickstep/res/values-km/strings.xml | 2 +- quickstep/res/values-lv/strings.xml | 2 +- quickstep/res/values-mn/strings.xml | 4 ++-- quickstep/res/values-my/strings.xml | 4 ++-- quickstep/res/values-nb/strings.xml | 2 +- quickstep/res/values-ne/strings.xml | 2 +- quickstep/res/values-pt-rPT/strings.xml | 2 +- quickstep/res/values-sq/strings.xml | 2 +- quickstep/res/values-sv/strings.xml | 6 +++--- quickstep/res/values-sw/strings.xml | 4 ++-- quickstep/res/values-te/strings.xml | 2 +- quickstep/res/values-th/strings.xml | 8 ++++---- quickstep/res/values-tl/strings.xml | 4 ++-- quickstep/res/values-uz/strings.xml | 10 +++++----- quickstep/res/values-zh-rCN/strings.xml | 4 ++-- quickstep/res/values-zh-rHK/strings.xml | 4 ++-- quickstep/res/values-zh-rTW/strings.xml | 2 +- 30 files changed, 62 insertions(+), 62 deletions(-) diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 780104b326..c2348ecf50 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -34,7 +34,7 @@ "تطبيقاتك المتوقّعة" "رؤية التطبيقات المقترحة في الصف السفلي من الشاشة الرئيسية" "رؤية التطبيقات المقترحة في صف التطبيقات المفضّلة في الشاشة الرئيسية" - "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى سلاسل الإجراءات. سيتم نقل التطبيقات من الصف السفلي للعلوي في الشاشة الرئيسية." + "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى استخدامك الروتيني. وسيتم نقل التطبيقات من الصف السفلي في الشاشة الرئيسية إلى الصف الأعلى." "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى سلاسل الإجراءات. سيتم نقل التطبيقات من صف التطبيقات المفضّلة إلى الشاشة الرئيسية." "يمكنك الوصول إلى التطبيقات الأكثر استخدامًا بسهولة من الشاشة الرئيسية مباشرةً. سيتم تغيير الاقتراحات استنادًا إلى سلاسل الإجراءات. سيتم نقل التطبيقات من الصف الأسفل إلى مجلد جديد." "رؤية تطبيقات مقترحة" diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index db7006f564..5484bc9e8b 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -43,7 +43,7 @@ "Най-използваните приложения се показват тук и се променят въз основа на поредиците" "За да получавате предложения за приложения, с плъзгане премахнете приложенията от най-долния ред" "Предложенията за приложения са добавени на празното място" - "Функцията „Предложения за приложения“ е активирана" + "Предложенията за приложения са активирани" "Функцията „Предложения за приложения“ е деактивирана" "Предвидено приложение: %1$s" "Споделяне" diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml index b230ec5611..9212a4b827 100644 --- a/quickstep/res/values-bn/strings.xml +++ b/quickstep/res/values-bn/strings.xml @@ -47,6 +47,6 @@ "অ্যাপ সাজেশন বন্ধ করা আছে" "আপনার প্রয়োজন হতে পারে এমন অ্যাপ: %1$s" "শেয়ার করুন" - "স্ক্রিনশট" + "স্ক্রিনশট নিন" "এই অ্যাপ বা আপনার প্রতিষ্ঠান এই অ্যাকশনটি পারফর্ম করার অনুমতি দেয়নি" diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index 657239ce0d..4b0acca10e 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -34,13 +34,13 @@ "Prediccions d\'aplicacions" "Obtén suggeriments d\'aplicacions a la fila inferior de la pantalla d\'inici" "Obtén suggeriments d\'aplicacions a la fila Preferides de la teva pantalla d\'inici" - "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció de la teva rutina. Les aplicacions de la fila inferior pujaran a la pantalla d\'inici." - "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció de la teva rutina. Les aplicacions de la fila Preferides es mouran a la teva pantalla d\'inici." - "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció de la teva rutina. Les aplicacions de la fila inferior es mouran a una carpeta nova." + "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció dels teus hàbits. Les aplicacions de la fila inferior pujaran a la pantalla d\'inici." + "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció dels teus hàbits. Les aplicacions de la fila Preferides es mouran a la teva pantalla d\'inici." + "Accedeix fàcilment a les aplicacions que més utilitzes des de la pantalla d\'inici. Els suggeriments variaran en funció dels teus hàbits. Les aplicacions de la fila inferior es mouran a una carpeta nova." "Mostra suggeriments d\'aplicacions" "No, gràcies" "Configuració" - "Les aplicacions que més utilitzes apareixen aquí i poden variar en funció de la teva rutina" + "Les aplicacions que més utilitzes apareixen aquí i poden variar en funció dels teus hàbits" "Arrossega les aplicacions fora de la fila inferior per obtenir suggeriments d\'aplicacions" "S\'han afegit suggeriments d\'aplicacions en un espai buit" "Els suggeriments d\'aplicacions estan activats" diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index 17ba8ad457..b51f04de98 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -35,17 +35,17 @@ "Lass dir in der unteren Reihe auf deinem Startbildschirm Vorschläge für Apps anzeigen" "Lass dir in der Favoritenleiste auf dem Startbildschirm App-Vorschläge anzeigen" "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge werden deiner Nutzung entsprechend laufend angepasst. Apps in der unteren Reihe werden nach oben auf den Startbildschirm verschoben." - "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge richten sich nach deiner gewöhnlichen Nutzung. Apps der Favoritenleiste werden auf den Startbildschirm verschoben." + "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge werden deiner Nutzung entsprechend laufend angepasst. Apps der Favoritenleiste werden auf den Startbildschirm verschoben." "Schneller Zugriff auf deine meistverwendeten Apps direkt über den Startbildschirm. Die Vorschläge werden deiner Nutzung entsprechend laufend angepasst. Apps in der unteren Reihe werden in einen neuen Ordner verschoben." "App-Vorschläge erhalten" "Nein danke" "Einstellungen" "Hier erscheinen die meistverwendeten Apps. Die Angaben können sich je nach deiner gewöhnlichen Nutzung ändern" - "Ziehe Apps aus der unteren Reihe heraus, um Vorschläge für Apps zu bekommen" + "Ziehe Apps aus der unteren Reihe heraus, um Vorschläge für Apps zu erhalten" "App-Vorschläge in freiem Bereich hinzugefügt" "Funktion \"App-Vorschläge\" aktiviert" "Funktion \"App-Vorschläge\" deaktiviert" - "App-Vorhersage: %1$s" + "Vorgeschlagene App: %1$s" "Teilen" "Screenshot" "Die App oder deine Organisation lässt diese Aktion nicht zu" diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index d62c8b3c82..1191becfa1 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -43,7 +43,7 @@ "Las apps que más se usan se muestran aquí y cambian según las rutinas" "Arrastra apps fuera de la fila inferior para obtener sugerencias" "Se agregaron sugerencias de aplicaciones a un espacio vacío" - "Las sugerencias de aplicaciones están habilitadas" + "Sugerencias de apps habilitadas" "Las sugerencias de aplicaciones están inhabilitadas" "Predicción de app: %1$s" "Compartir" diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index 1a8cbd2388..a2b930d068 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -32,12 +32,12 @@ "Sugerencias de aplicaciones" "Todas las aplicaciones" "Predicción de aplicaciones" - "Haz que aparezcan sugerencias de aplicaciones en la fila inferior de la pantalla de inicio" + "Obtén sugerencias de aplicaciones en la fila inferior de la pantalla de inicio" "Recibe sugerencias de aplicaciones en la fila de aplicaciones favoritas de la pantalla de inicio" - "Accede fácilmente desde la pantalla de inicio a las aplicaciones que más usas. Las sugerencias cambiarán según tus rutinas. Las aplicaciones de la fila inferior pasarán a mostrarse en la pantalla de inicio." - "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus rutinas. Las aplicaciones de la fila de aplicaciones favoritas se moverán a la pantalla de inicio." - "Accede fácilmente desde la pantalla de inicio a las aplicaciones que más usas. Las sugerencias cambiarán según tus rutinas. Las aplicaciones de la fila inferior se pondrán en una carpeta nueva." - "Ver sugerencias de aplicaciones" + "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus hábitos. Las aplicaciones de la fila inferior pasarán a mostrarse en la pantalla de inicio." + "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus hábitos. Las aplicaciones de la fila de aplicaciones favoritas se moverán a la pantalla de inicio." + "Accede fácilmente a las aplicaciones que más usas desde la pantalla de inicio. Las sugerencias cambiarán según tus hábitos. Las aplicaciones de la fila inferior se pondrán en una carpeta nueva." + "Sí, obtener sugerencias" "No, gracias" "Ajustes" "Las aplicaciones que más usas aparecen aquí, y van variando según tus rutinas" diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index 8ae00237d2..46096f5263 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -32,7 +32,7 @@ "Suggestions d\'applications" "Toutes les applications" "Vos prédictions d\'applications" - "Obtenez des applications suggérées dans la rangée du bas de votre écran d\'accueil" + "Obtenir des suggestions d\'applications dans la rangée du bas de votre écran d\'accueil" "Retrouvez des suggestions d\'applications dans la rangée des favoris de votre écran d\'accueil" "Accédez facilement aux applications que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applications dans la rangée du bas seront déplacées vers votre écran d\'accueil." "Accédez facilement aux applications que vous utilisez le plus, directement à l\'écran d\'accueil. Les suggestions changeront en fonction de vos habitudes. Les applications dans la rangée des favoris seront déplacées vers votre écran d\'accueil." diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index 8bf208f1aa..d98cc770a1 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -36,7 +36,7 @@ "अपने होम स्क्रीन की सबसे नीचे वाली पंक्ति में पसंदीदा ऐप्लिकेशन के सुझाव पाएं" "आप जिन ऐप्लिकेशन का ज़्यादा इस्तेमाल करते हैं उन्हें सीधा अपने होम स्क्रीन पर पाएं. ऐप्लिकेशन इस्तेमाल करने के आपके रूटीन के हिसाब से सुझाव बदलते रहते हैं. नीचे की पंक्ति के ऐप्लिकेशन होम स्क्रीन पर आ जाएंगे." "सबसे ज़्यादा इस्तेमाल होने वाले ऐप्लिकेशन सीधे होम स्क्रीन पर देखें. आप ऐप्लिकेशन का कितना इस्तेमाल कर रहे हैं, उसके हिसाब से सुझाव बदलते रहते हैं. आपके पसंदीदा ऐप्लिकेशन, होम स्क्रीन पर नीचे की पंक्ति में दिखाई देंगे." - "सबसे ज़्यादा इस्तेमाल होने वाले ऐप्लिकेशन, सीधे होम स्क्रीन पर देखें. ऐप्लिकेशन इस्तेमाल करने के आपके रूटीन के हिसाब से सुझाव बदलते रहते हैं. नीचे की पंक्ति के ऐप्लिकेशन एक नए फ़ोल्डर में चले जाएंगे." + "सबसे ज़्यादा इस्तेमाल होने वाले ऐप्लिकेशन, सीधे होम स्क्रीन पर पाएं. आपके ऐप्लिकेशन इस्तेमाल करने के रूटीन के हिसाब से सुझाव बदलते रहते हैं. नीचे की पंक्ति के ऐप्लिकेशन एक नए फ़ोल्डर में चले जाएंगे." "ऐप्लिकेशन के बारे में सुझाव पाएं" "रहने दें" "सेटिंग" diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index 21920a7113..a026ef8012 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -32,21 +32,21 @@ "Predložene aplikacije" "Sve aplikacije" "Vaše predviđene aplikacije" - "Prikažite predložene aplikacije u donjem retku početnog zaslona" + "Prijedloge aplikacija vidjet ćete u donjem retku početnog zaslona" "Primajte prijedloge aplikacija u retku omiljenih na početnom zaslonu" "Lako pristupite najčešće upotrebljavanim aplikacijama s početnog zaslona. Prijedlozi će se mijenjati na temelju vaših rutina. Aplikacije iz donjeg retka pomaknut će se na početni zaslon." "Lako pristupite najčešće upotrebljavanim aplikacijama s početnog zaslona. Prijedlozi će se mijenjati na temelju vaših rutina. Aplikacije koje se nalaze u retku omiljenih pomaknut će se na početni zaslon." "Lako pristupite najčešće upotrebljavanim aplikacijama s početnog zaslona. Prijedlozi će se mijenjati na temelju vaših rutina. Aplikacije iz donjeg retka pomaknut će se u novu mapu." - "Prikaži predložene aplikacije" + "Predloži mi aplikacije" "Ne, hvala" "Postavke" "Ovdje se prikazuju najčešće upotrebljavane aplikacije i mijenjaju se na temelju rutina" "Povucite aplikacije iz donjeg retka da biste dobili prijedloge aplikacija" "Predložene aplikacije dodane u prazan prostor" - "Predlaganje aplikacija je omogućeno" - "Predlaganje aplikacija je onemogućeno" + "Predlaganje apl. omogućeno" + "Predlaganje apl. onemogućeno" "Predviđena aplikacija: %1$s" - "Udio" + "Podijeli" "Snimka zaslona" "Aplikacija ili vaša organizacija ne dopuštaju ovu radnju" diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index f8b63fb64a..824fd7fb31 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -43,7 +43,7 @@ "Mest notuðu forritin birtast hér og breytast í samræmi við rútínur" "Dragðu forrit af neðstu röð til að fá tillögð forrit" "Tillögðum forritum bætt við autt svæði" - "Kveikt á tillögðum forritum" + "Kveikt á tillögum að forritum" "Slökkt er á tillögðum forritum" "Tillaga að forriti: %1$s" "Deila" diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index e0a78b2301..4038966102 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -41,7 +41,7 @@ "No, grazie" "Impostazioni" "Le app più utilizzate vengono visualizzate qui e variano in base alle routine" - "Trascina le app fuori dalla fila in basso per vedere le app suggerite" + "Trascina le app fuori dalla riga inferiore per visualizzare le app suggerite" "App suggerite aggiunte a uno spazio vuoto" "La funzionalità app suggerite è attiva" "La funzionalità app suggerite è disattivata" diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index 1bb1684dde..fb76660b1f 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -32,16 +32,16 @@ "Ұсынылған қолданбалар" "Барлық қолданбалар" "Ұсынылатын қолданбалар" - "Негізгі экранның төменгі жолында ұсынылған қолданбаларды алу" + "Негізгі экранның төменгі жолында қолданбаларды ұсыну" "Ұсынылған қолданбалар негізгі экранда таңдаулылар арасында көрсетілетін болады" - "Жиі пайдаланылатын қолданбаларға негізгі экраннан оңай кіріңіз. Ұсыныстар әрекеттер тізімі негізінде өзгереді. Төменгі жолдағы қолданбалар негізгі экраныңызға қарай жоғары жылжиды." + "Жиі пайдаланылатын қолданбаларға негізгі экраннан кіруге болады. Ұсыныстар күнделікті әрекеттеріңізге сәйкес өзгереді. Төменгі қатардағы қолданбалар негізгі экранға қарай жоғары жылжиды." "Жиі пайдаланылатын қолданбаларға негізгі экраннан оңай кіре аласыз. Ұсыныстар күнделікті әрекеттеріңізге сәйкес өзгереді. Таңдаулылар жолындағы қолданбалар негізгі экранға ауысады." - "Жиі пайдаланылатын қолданбаларға негізгі экраннан оңай кіріңіз. Ұсыныстар әрекеттер тізімі негізінде өзгереді. Төмендегі қолданбалар жаңа қалтаға жылжиды." + "Жиі пайдаланылатын қолданбаларға негізгі экраннан кіруге болады. Ұсыныстар күнделікті әрекеттеріңізге сәйкес өзгереді. Төменгі қатардағы қолданбалар жаңа қалтаға жылжиды." "Ұсынылған қолданбаларды көру" "Жоқ, рақмет" "Параметрлер" - "Жиі пайдаланылатын қолданбалар осы жерде көрсетіледі және әрекеттер тізімі негізінде өзгереді." - "Ұсынылған қолданбаларды алу үшін қолданбаларды төменгі жолдан жылжытыңыз." + "Жиі пайдаланылатын қолданбалар осы жерде көрсетіледі. Олар күнделікті әрекеттеріңізге сәйкес өзгереді." + "Ұсынылған қолданбаларды көру үшін төменгі қатардан керектерін сүйреп шығарыңыз." "Ұсынылған қолданбалар бос орынға қосылды." "\"Ұсынылған қолданбалар\" функциясы қосулы." "\"Ұсынылған қолданбалар\" функциясы өшірулі." diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index dd2fbacbed..3c3fccc022 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -37,7 +37,7 @@ "ចូលប្រើ​កម្មវិធី​ដែលអ្នកប្រើ​ញឹកញាប់បំផុត​បានយ៉ាង​ងាយស្រួល​នៅលើ​អេក្រង់ដើម​ផ្ទាល់។ ការណែនាំ​នឹងប្រែប្រួល​ទៅតាម​ទម្លាប់​របស់អ្នក។ កម្មវិធី​នៅជួរ​ខាងក្រោម​នឹងផ្លាស់ទីឡើង​ទៅអេក្រង់ដើម​របស់អ្នក។" "ចូលប្រើ​កម្មវិធី​ដែលអ្នកប្រើ​ញឹកញាប់បំផុត​បានយ៉ាង​ងាយស្រួល​នៅលើ​អេក្រង់ដើមដោយផ្ទាល់។ ការណែនាំ​នឹងប្រែប្រួល​ទៅតាម​ទម្លាប់​របស់អ្នក។ កម្មវិធី​នៅក្នុង​ជួរដេក​សំណព្វ​នឹងផ្លាស់ទី​ទៅអេក្រង់ដើម​របស់អ្នក។" "ចូលប្រើ​កម្មវិធី​ដែលអ្នកប្រើ​ញឹកញាប់បំផុត​បានយ៉ាង​ងាយស្រួល​នៅលើ​អេក្រង់ដើម​ផ្ទាល់។ ការណែនាំ​នឹងប្រែប្រួល​ទៅតាម​ទម្លាប់​របស់អ្នក។ កម្មវិធី​នៅជួរ​ខាងក្រោម​នឹងផ្លាស់ទី​ទៅថតថ្មី។" - "ទទួលបាន​ការណែនាំ​កម្មវិធី" + "ទទួលការណែនាំ​កម្មវិធី" "ទេ អរគុណ" "ការកំណត់" "កម្មវិធី​ដែលប្រើ​ញឹកញាប់បំផុត​បង្ហាញ​នៅទីនេះ និង​ប្រែប្រួល​ទៅតាមទម្លាប់" diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml index 82c96fe213..65620c4683 100644 --- a/quickstep/res/values-lv/strings.xml +++ b/quickstep/res/values-lv/strings.xml @@ -47,6 +47,6 @@ "Ieteicamās lietotnes ir atspējotas" "Prognozētā lietotne: %1$s" "Kopīgot" - "Izveidot ekrānuzņēmumu" + "Veikt ekrānuzņēmumu" "Lietotne vai jūsu organizācija neatļauj veikt šo darbību." diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml index f4b9d43e6e..ba083ef0e0 100644 --- a/quickstep/res/values-mn/strings.xml +++ b/quickstep/res/values-mn/strings.xml @@ -34,9 +34,9 @@ "Таны таамагласан аппууд" "Үндсэн нүүрнийхээ доод мөрөнд санал болгож буй аппуудыг аваарай" "Үндсэн нүүрний дуртай мөрнөөсөө санал болгож буй аппуудыг аваарай" - "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөр дэх аппуудыг таны Үндсэн нүүр лүү дээш зөөнө." + "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрнээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөрөнд буй аппуудыг таны Үндсэн нүүр лүү дээш зөөнө." "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрнээсээ хялбархан хандаарай. Санал болголтыг таны хэвшлээс хамааран өөрчилнө. Дуртай мөрөнд буй аппуудыг таны үндсэн нүүр лүү зөөнө." - "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөр дэх аппуудыг шинэ фолдер луу зөөнө." + "Хамгийн их ашигладаг аппууддаа Үндсэн нүүрнээс хялбархан хандаарай. Санал болгож буй аппуудыг таны хэвшлээс хамаарч өөрчилнө. Доод мөрөнд буй аппуудыг шинэ фолдер луу зөөнө." "Санал болгож буй аппуудыг авах" "Үгүй, баярлалаа" "Тохиргоо" diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index 0dc3a165b5..a18c1c451d 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -34,7 +34,7 @@ "သင်၏ ခန့်မှန်းအက်ပ်များ" "သင်၏ \'ပင်မစာမျက်နှာ\' အောက်ခြေအတန်းတွင် အက်ပ်အကြံပြုချက်များ ရယူခြင်း" "သင်၏ \'ပင်မစာမျက်နှာ\' ၏ အနှစ်သက်ဆုံးများအတန်းတွင် အက်ပ်အကြံပြုချက်များ ရယူခြင်း" - "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ သုံးနိုင်သည်။ သင်၏ ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အောက်ခြေအတန်းရှိ အက်ပ်များကို သင်၏ \'ပင်မစာမျက်နှာ\' သို့ရွှေ့လိုက်မည်။" + "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ ဖွင့်နိုင်သည်။ သင်၏ ပုံမှန်လုပ်ဆောင်ချက်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အောက်ခြေအတန်းရှိ အက်ပ်များကို သင်၏ \'ပင်မစာမျက်နှာ\' သို့ရွှေ့လိုက်မည်။" "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ သုံးနိုင်သည်။ သင်၏ ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အနှစ်သက်ဆုံးများအတန်းရှိ အက်ပ်များကို သင်၏ \'ပင်မစာမျက်နှာ\' သို့ရွှေ့လိုက်မည်။" "အသုံးအများဆုံးအက်ပ်များကို \'ပင်မစာမျက်နှာ\' တွင် အလွယ်တကူ သုံးနိုင်သည်။ သင်၏ ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ အကြံပြုချက်များ ပြောင်းလဲပါမည်။ အောက်ခြေအတန်းရှိ အက်ပ်များကို ဖိုင်တွဲအသစ်သို့ ရွှေ့လိုက်မည်။" "အက်ပ်အကြံပြုချက်များ ရယူရန်" @@ -43,7 +43,7 @@ "အသုံးအများဆုံးအက်ပ်များကို ဤနေရာတွင် ပြပြီး ပုံမှန်အစီအစဉ်များပေါ် အခြေခံ၍ ပြောင်းလဲသည်" "အက်ပ်အကြံပြုချက်များ ရယူရန် အောက်ခြေအတန်းရှိ အက်ပ်များကို ဖိဆွဲထုတ်လိုက်ပါ" "အက်ပ်အကြံပြုချက်များကို နေရာလွတ်သို့ ထည့်လိုက်သည်" - "အက်ပ်အကြံပြုချက်များကို ဖွင့်ထားသည်" + "အက်ပ်အကြံပြုချက်များ ဖွင့်ထားသည်" "အက်ပ်အကြံပြုချက်များကို ပိတ်ထားသည်" "ကြိုတင်မှန်းဆထားသော အက်ပ်− %1$s" "မျှဝေရန်" diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index 161612212b..161d1c4f97 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -43,7 +43,7 @@ "Appene som brukes oftest, vises her og endres basert på rutiner" "Dra appene vekk fra den nederste raden for å få appforslag." "Appforslag er lagt til på et tomt område" - "Appforslag er slått på" + "Appforslag er på" "Appforslag er slått av" "Foreslått app: %1$s" "Del" diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index c8c35a8c80..99a22f922f 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -36,7 +36,7 @@ "आफ्नो होम स्क्रिनको मन पर्ने नामक पङ्क्तिमा सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्" "गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एप सजिलै चलाउनुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू तपाईंको गृह स्क्रिनको सिरानमा सर्ने छन्।" "आफूले सबैभन्दा बढी प्रयोग गर्ने एपहरू गृह स्क्रिनबाटै सजिलैसँग खोल्नुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंको दिनचर्याअनुसार बदलिने छ। मन पर्ने नामक पङ्क्तिमा रहेका एपहरू सारेर होम स्क्रिनमा लगिने छन्।" - "गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एपमाथि सजिलैसँग पहुँच राख्नुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू एउटा नयाँ फोल्डरमा सर्ने छन्।" + "गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एप सजिलै चलाउनुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू एउटा नयाँ फोल्डरमा सर्ने छन्।" "सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्" "पर्दैन धन्यवाद" "सेटिङ" diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index 5ac7287f74..cff747fc84 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -25,7 +25,7 @@ "Nenhum item recente" "Definições de utilização de aplicações" "Limpar tudo" - "Aplicações recentes" + "Apps recentes" "%1$s, %2$s" "< 1 minuto" "Resta(m) %1$s hoje." diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml index a4233446ee..a144b92aac 100644 --- a/quickstep/res/values-sq/strings.xml +++ b/quickstep/res/values-sq/strings.xml @@ -43,7 +43,7 @@ "Aplikacionet më të përdorura shfaqen këtu dhe ndryshojnë bazuar në rutinat" "Zvarrit aplikacionet jashtë rreshtit të poshtëm për të marrë aplikacione të sugjeruara" "Aplikacionet e sugjeruara u shtuan në hapësirën bosh" - "Sugjerimet e aplikacioneve janë aktivizuar" + "Aplikacionet e sugjeruara janë aktivizuar" "Sugjerimet e aplikacioneve janë çaktivizuar" "Aplikacioni i parashikuar: %1$s" "Ndaj" diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index 42d7327d1b..8252fec2de 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -34,9 +34,9 @@ "Föreslagna appar" "Få appförslag på den nedersta raden på startskärmen" "Få appförslag på raden Favoriter på startskärmen" - "Kom enkelt åt de appar du använder mest direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas upp till startskärmen." - "Kom enkelt åt de appar du använder mest direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på raden Favoriter flyttas till startskärmen." - "Kom enkelt åt de appar du använder mest direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas till en ny mapp." + "Kom enkelt åt de appar du använder mest, direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas upp till startskärmen." + "Kom enkelt åt de appar du använder mest, direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på raden Favoriter flyttas till startskärmen." + "Kom enkelt åt de appar du använder mest, direkt från startskärmen. Förslagen ändras efter dina rutiner. Appar på nedersta raden flyttas till en ny mapp." "Få appförslag" "Nej tack" "Inställningar" diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml index 3e949e8ee6..778d558481 100644 --- a/quickstep/res/values-sw/strings.xml +++ b/quickstep/res/values-sw/strings.xml @@ -36,14 +36,14 @@ "Pata mapendekezo ya programu katika safu ya vipendwa ya Skrini yako ya kwanza" "Fikia kwa urahisi programu unazotumia sana moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye sehemu ya chini zitahamishiwa kwenye Skrini yako ya kwanza." "Fikia kwa urahisi programu unazotumia sana moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na utumiaji wako. Programu zilizo katika safu ya vipendwa zitahamishiwa kwenye Skrini yako ya kwanza." - "Fikia kwa urahisi programu unazotumia zaidi, moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye safu mlalo ya chini zitahamishiwa kwenye folda mpya." + "Fikia kwa urahisi programu unazotumia zaidi, moja kwa moja kwenye Skrini ya kwanza. Mapendekezo yatabadilika kulingana na ratiba zako. Programu zilizo kwenye safu ya chini zitahamishiwa kwenye folda mpya." "Pata mapendekezo ya programu" "Hapana" "Mipangilio" "Programu zinazotumiwa zaidi huonekana hapa na hubadilika kulingana na ratiba" "Buruta programu kutoka kwenye safu ya chini ili upate mapendekezo ya programu" "Mapendekezo ya programu yamewekwa kwenye nafasi isiyo na kitu" - "Umewasha mapendekezo ya programu" + "Mapendekezo ya programu yamewashwa" "Umezima mapendekezo ya programu" "Programu iliyotabiriwa: %1$s" "Shiriki" diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index 35c455fb2b..b381af994b 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -43,7 +43,7 @@ "ఎక్కువగా ఉపయోగించిన యాప్‌లు ఇక్కడ కనిపిస్తాయి, అవి రోజువారీ కార్యకలాపాలను బట్టి మారుతూ ఉంటాయి" "యాప్ సలహాలను పొందడానికి దిగువ వరుస నుండి యాప్‌లను లాగండి" "యాప్ సూచ‌న‌లు ఖాళీ స్పేస్‌కు జోడించబడ్డాయి" - "యాప్ సూచ‌న‌లు ఎనేబుల్ చేయబడ్డాయి" + "యాప్ సలహాలు ఎనేబుల్ చేయబడ్డాయి" "యాప్ సూచ‌న‌లు డిజేబుల్‌ చేయబడ్డాయి" "సూచించబడిన యాప్: %1$s" "షేర్ చేయండి" diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml index e81a97615e..42e0c5858f 100644 --- a/quickstep/res/values-th/strings.xml +++ b/quickstep/res/values-th/strings.xml @@ -32,18 +32,18 @@ "คำแนะนำเกี่ยวกับแอป" "แอปทั้งหมด" "แอปที่คาดการณ์ไว้" - "รับคำแนะนำเกี่ยวกับแอปที่แถวล่างของหน้าจอหลัก" + "ดูแอปแนะนำที่แถวล่างของหน้าจอหลัก" "รับคำแนะนำเกี่ยวกับแอปในแถวรายการโปรดของหน้าจอหลัก" "เข้าถึงแอปที่คุณใช้มากที่สุดได้อย่างง่ายดายจากหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามแอปที่ใช้งานเป็นประจำ แอปในแถวล่างจะย้ายขึ้นมาอยู่ในหน้าจอหลัก" "เข้าถึงแอปที่ใช้มากที่สุดได้อย่างง่ายดายในหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามการใช้งานประจำ แอปในแถวรายการโปรดจะย้ายไปอยู่ในหน้าจอหลัก" "เข้าถึงแอปที่คุณใช้มากที่สุดได้อย่างง่ายดายจากหน้าจอหลัก คำแนะนำจะเปลี่ยนไปตามแอปที่ใช้งานเป็นประจำ แอปในแถวล่างจะย้ายไปอยู่ในโฟลเดอร์ใหม่" - "รับคำแนะนำเกี่ยวกับแอป" + "ดูแอปแนะนำ" "ไม่เป็นไร" "การตั้งค่า" "แอปที่ใช้มากที่สุดจะปรากฎที่นี่และจะเปลี่ยนไปตามการใช้งานประจำ" - "ลากแอปออกจากแถวล่างเพื่อดูคำแนะนำเกี่ยวกับแอป" + "ลากแอปออกจากแถวล่างเพื่อดูแอปแนะนำ" "เพิ่มคำแนะนำเกี่ยวกับแอปในพื้นที่ว่างแล้ว" - "เปิดใช้คำแนะนำเกี่ยวกับแอปอยู่" + "เปิดใช้คำแนะนำเกี่ยวกับแอปแล้ว" "ปิดใช้คำแนะนำเกี่ยวกับแอปอยู่" "แอปที่คาดว่าจะใช้: %1$s" "แชร์" diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml index 5d00b8b6d9..54aa564904 100644 --- a/quickstep/res/values-tl/strings.xml +++ b/quickstep/res/values-tl/strings.xml @@ -32,7 +32,7 @@ "Mga iminumungkahing app" "Lahat ng app" "Iyong mga nahulaang app" - "Makakuha ng mga iminumungkahing app sa ibabang row ng iyong Home screen" + "Makakuha ng mga suhestyon sa app sa ibabang row ng iyong Home screen" "Makakuha ng mga iminumungkahing app sa row ng mga paborito ng iyong Home screen" "Madaling ma-access ang mga pinakaginagamit mong app nang direkta sa Home screen. Magbabago ang mga suhestyon batay sa iyong mga routine. Mapupunta sa iyong Home screen ang mga app na nasa ibabang row." "Madaling ma-access ang mga pinakaginagamit mong app nang direkta sa Home screen. Magbabago ang mga suhestyon batay sa iyong mga routine. Mapupunta sa iyong Home screen ang mga app sa row ng mga paborito." @@ -41,7 +41,7 @@ "Huwag na lang" "Mga Setting" "Ipinapakita ang mga pinakaginagamit na app dito, at nababago ito batay sa mga routine" - "I-drag ang mga app mula sa ibabang row para makakuha ng mga iminumungkahing app" + "I-drag ang mga app mula sa ibabang row para makakuha ng mga suhestyon sa app" "Idinagdag sa bakanteng espasyo ang mga iminumungkahing app" "Naka-enable ang mga iminumungkahing app" "Naka-disable ang mga iminumungkahing app" diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml index d6c0e7994a..737bd20fa0 100644 --- a/quickstep/res/values-uz/strings.xml +++ b/quickstep/res/values-uz/strings.xml @@ -32,18 +32,18 @@ "Tavsiya etiladigan ilovalar" "Barcha ilovalar" "Taklif qilingan ilovalaringiz" - "Ilova takliflari bosh ekran pastidagi qatorda chiqadi" - "Saralanganlar qatorida Bosh ekrandagi ilovalar taklif qilinsin" + "Tavsiya etiladigan ilovalar bosh ekran pastidagi qatorda chiqadi" + "Tavsiya etiladigan ilovalar bosh ekranning saralanganlar ruknida chiqadi" "Faol ishlatiladigan ilovalarga bosh ekrandan osongina kira olasiz. Tavsiyalar oxirgi faoliyatingiz asosida almashib boradi. Pastki qatordagi ilovalar bosh ekranga chiqadi." "Faol ishlatiladigan ilovalarga bosh ekrandan osongina kira olasiz. Tavsiyalar oxirgi faoliyatingiz asosida almashib boradi. Saralanganlar qatoridagi ilovalar bosh ekranga chiqadi." "Faol ishlatiladigan ilovalarga bosh ekrandan osongina kira olasiz. Tavsiyalar oxirgi faoliyatingiz asosida almashib boradi. Pastki qatordagi ilovalar yangi jildga chiqadi." - "Ilova takliflarini olish" + "Tavsiyalarni chiqarish" "Kerak emas" "Sozlamalar" "Faol ishlatiladigan ilovalar bu yerda chiqadi va oxirgi faoliyatingiz asosida almashadi" - "Takliflar olish uchun ilovalarni pastki qatordan tashqariga oling" + "Tavsiyalar olish uchun ilovalarni pastki qatordan tashqariga oling" "Tavsiya etilgan ilovalarni ochiq joylarga kiriting" - "Endi ilova takliflari chiqadi" + "Ilova tavsiyalari yoqildi" "Endi ilova takliflari chiqmaydi" "Taklif etilgan ilova: %1$s" "Ulashish" diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index 1a06aad744..ed65978233 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -32,7 +32,7 @@ "应用建议" "所有应用" "您的预测应用" - "在主屏幕的最下面一排获取应用建议" + "在主屏幕底部获取应用建议" "在主屏幕的收藏行获取应用建议" "直接在主屏幕上轻松访问您最常用的应用。系统会根据您的日常安排提供不同的建议。最下面一排中的应用会向上移动到主屏幕中。" "直接在主屏幕上轻松访问您最常用的应用。建议会因您的日常安排而变化,收藏行中的应用将移到主屏幕上。" @@ -41,7 +41,7 @@ "不用了" "设置" "最常用的应用会显示在此处,显示的项目会根据日常安排而发生变化" - "将应用从最下面一排拖至别处,以获取应用建议" + "将应用拖离底部,以获取应用建议" "应用建议已添加到空白区域" "已启用应用建议" "已停用应用建议" diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index dc9caadd90..d3fd7eefc3 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -36,12 +36,12 @@ "在主畫面「我的最愛」列取得應用程式建議" "在主畫面輕鬆存取常用的應用程式。系統會根據您的日常安排更改建議,並將底部的應用程式移到主畫面。" "在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,「我的最愛」列中的應用程式會移至主畫面。" - "在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,並將底部應用程式列的應用程式移至新資料夾。" + "在主畫面輕鬆存取最常用的應用程式。系統會根據您的日常安排變更建議,並將底列的應用程式移至新資料夾。" "取得應用程式建議" "不用了,謝謝" "設定" "最常用的應用程式會在這裡顯示,並會根據日常安排變更" - "將應用程式從底部應用程式列拖曳出來,即可獲取應用程式建議" + "將應用程式從底列拖曳出來,即可獲取應用程式建議" "系統會將應用程式建議新增至空白位置" "已啟用應用程式建議" "已停用應用程式建議" diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index d62629090e..3545a16769 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -41,7 +41,7 @@ "不用了,謝謝" "設定" "最常使用的應用程式會顯示在這裡,顯示的項目會根據日常安排有所不同" - "將應用程式從底部列向外拖曳即可取得應用程式建議" + "將應用程式從底部列向外拖曳,即可取得應用程式建議" "應用程式建議已新增到空白位置" "應用程式建議功能已啟用" "應用程式建議功能已停用" From 25ed0dce256476bbf260621558da800e153d92f2 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 20 Jul 2020 14:02:54 -0700 Subject: [PATCH 07/51] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ic9168efed903a1cc61b770bc32d754ca1858b3df --- res/values-az/strings.xml | 2 +- res/values-b+sr+Latn/strings.xml | 2 +- res/values-be/strings.xml | 2 +- res/values-bg/strings.xml | 2 +- res/values-bs/strings.xml | 4 ++-- res/values-de/strings.xml | 2 +- res/values-el/strings.xml | 2 +- res/values-fi/strings.xml | 2 +- res/values-fr-rCA/strings.xml | 4 ++-- res/values-gu/strings.xml | 2 +- res/values-hr/strings.xml | 2 +- res/values-hu/strings.xml | 2 +- res/values-in/strings.xml | 2 +- res/values-iw/strings.xml | 4 ++-- res/values-ja/strings.xml | 2 +- res/values-ml/strings.xml | 4 ++-- res/values-my/strings.xml | 2 +- res/values-nb/strings.xml | 2 +- res/values-or/strings.xml | 2 +- res/values-pa/strings.xml | 2 +- res/values-pl/strings.xml | 2 +- res/values-ru/strings.xml | 2 +- res/values-sk/strings.xml | 2 +- res/values-sl/strings.xml | 2 +- res/values-sq/strings.xml | 4 ++-- res/values-sr/strings.xml | 2 +- res/values-te/strings.xml | 2 +- res/values-th/strings.xml | 4 ++-- res/values-uz/strings.xml | 4 ++-- 29 files changed, 36 insertions(+), 36 deletions(-) diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 72d211c44c..aed975ac42 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -52,7 +52,7 @@ "Sistemdən sil" "Tətbiq infosu" "Quraşdırın" - "Tətbiq təklif etməyin" + "Tətbiq təklif olunmasın" "Proqnozlaşdırılan tətbiqi bərkidin" "qısayolları quraşdır" "Tətbiqə istifadəçi müdaxiləsi olmadan qısayolları əlavə etməyə icazə verir." diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 8f6f8c1cb9..e8123688e1 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -50,7 +50,7 @@ "Početna" "Ukloni" "Deinstaliraj" - "Inform. o aplikaciji" + "Infor. o aplikaciji" "Instaliraj" "Ne predlaži aplikaciju" "Zakači predviđanje" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 14bfd8b551..0b2b6f1bc9 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -50,7 +50,7 @@ "Галоўная" "Выдаліць" "Дэінсталяваць" - "Звесткі пра праграмы" + "Пра праграму" "Усталяваць" "Не прапаноўваць праграму" "Замацаваць прапанаваную праграму" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 0d06ead6b7..512a7fc069 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -50,7 +50,7 @@ "Начало" "Премахване" "Деинсталиране" - "Инфо за прилож." + "Информация за прилож." "Инсталиране" "Без предлагане на приложение" "Фиксиране на предвиждането" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index bf07ed5ea8..6ce19d8fe6 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -50,10 +50,10 @@ "Početna" "Ukloni" "Deinstaliraj" - "Informacije o aplikaciji" + "Inform. o aplikaciji" "Instaliraj" "Ne predlaži aplikaciju" - "Predviđanje PIN-a" + "Zakači predviđanje" "instaliraj prečice" "Dopušta aplikaciji dodavanje prečica bez posredovanja korisnika." "čitaj postavke na početnom ekranu i prečice" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 520d64a103..fdd92142ac 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -52,7 +52,7 @@ "Deinstallieren" "App-Info" "Installieren" - "App nicht empfehlen" + "App nicht vorschlagen" "Vorgeschlagene App anpinnen" "Verknüpfungen installieren" "Ermöglicht einer App das Hinzufügen von Verknüpfungen ohne Eingreifen des Nutzers" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 2bb266b771..5d72b77410 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -50,7 +50,7 @@ "Αρχική οθόνη" "Κατάργηση" "Απεγκατάσταση" - "Πληροφορίες εφαρμογής" + "Πληροφ. εφαρμογής" "Εγκατάσταση" "Να μην προτείνεται η εφαρμογή" "Καρφίτσωμα πρόβλεψης" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 2dbc9df998..9fea032da6 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -53,7 +53,7 @@ "Sovelluksen tiedot" "Asenna" "Älä ehdota sovellusta" - "Kiinnitä ennakoitu sovellus" + "Kiinnitä sovellus" "asenna pikakuvakkeita" "Antaa sovelluksen lisätä pikakuvakkeita itsenäisesti ilman käyttäjän valintaa." "lue aloitusruudun asetuksia ja pikakuvakkeita" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 23fd8d849d..aaffbd1a1d 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -50,10 +50,10 @@ "Accueil" "Supprimer" "Désinstaller" - "Détails de l\'application" + "Détails sur l\'appli" "Installer" "Ne pas suggérer d\'application" - "Prédiction d\'épinglage" + "Épingler la prédiction" "installer des raccourcis" "Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur." "lire les paramètres et les raccourcis de la page d\'accueil" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 8f49421bda..01ecf73f02 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -50,7 +50,7 @@ "હોમ" "દૂર કરો" "અનઇન્સ્ટોલ કરો" - "ઍપ્લિકેશન માહિતી" + "ઍપની માહિતી" "ઇન્સ્ટૉલ કરો" "ઍપ સૂચવશો નહીં" "પૂર્વાનુમાનને પિન કરો" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index f24dc06469..dd13ef0caf 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -53,7 +53,7 @@ "Info o aplikaciji" "Instaliraj" "Ne predlaži aplikaciju" - "Prikvači predviđenu aplikaciju" + "Prikvači predviđenu apl." "instaliranje prečaca" "Aplikaciji omogućuje dodavanje prečaca bez intervencije korisnika." "čitanje postavki početnog zaslona i prečaca" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 60c043fbe8..4f03908836 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -53,7 +53,7 @@ "Alkalmazásinformáció" "Telepítés" "Ne javasoljon alkalmazást" - "Várható kitűzés" + "Várható kitűzése" "parancsikonok telepítése" "Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat." "Főoldal beállításainak és parancsikonjainak beolvasása" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 9a49be55de..242e808040 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -53,7 +53,7 @@ "Info aplikasi" "Instal" "Jangan sarankan aplikasi" - "Pasang Pin pada Prediksi" + "Pin Prediksi" "memasang pintasan" "Mengizinkan aplikasi menambahkan pintasan tanpa campur tangan pengguna." "membaca setelan dan pintasan layar Utama" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 17af02335d..a2068aa6ac 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -52,7 +52,7 @@ "להסרת התקנה" "פרטי אפליקציה" "התקנה" - "לא להציע את האפליקציה" + "בלי להציע את האפליקציה" "הצמדת החיזוי" "התקן קיצורי דרך" "מאפשר לאפליקציה להוסיף קיצורי דרך ללא התערבות המשתמש." @@ -132,7 +132,7 @@ "גודל הווידג\'ט שונה - רוחב %1$s גובה %2$s" "קיצורי דרך" "קיצורי דרך והתראות" - "סגור" + "סגירה" "סגירה" "ההתראה נסגרה" "אישיות" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 0be3a0ff54..a6e37c4fb4 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -53,7 +53,7 @@ "アプリ情報" "インストール" "アプリの候補を表示しない" - "予測を固定" + "アプリの候補を固定表示" "ショートカットのインストール" "ユーザー操作なしでショートカットを追加することをアプリに許可します。" "ホームの設定とショートカットの読み取り" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 0d0a9518d4..01d8935672 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -50,10 +50,10 @@ "ഹോം" "നീക്കംചെയ്യുക" "അൺഇൻസ്റ്റാളുചെയ്യുക" - "ആപ്പ് വിവരം" + "ആപ്പ് വിവരങ്ങൾ" "ഇൻസ്‌റ്റാൾ ചെയ്യുക" "ആപ്പ് നിർദ്ദേശിക്കരുത്" - "പിൻ പ്രവചനം" + "പ്രവചനം പിൻ ചെയ്യുക" "കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക" "ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 4e465caf71..d753021886 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -50,7 +50,7 @@ "ပင်မစာမျက်နှာ" "ဖယ်ရှားမည်" "ဖြုတ်ရန်" - "အက်ပ်အချက်အလက်များ" + "အက်ပ်အချက်အလက်" "ထည့်သွင်းရန်" "အက်ပ်ကို အကြံမပြုပါနှင့်" "ခန့်မှန်းချက်ကို ပင်ထိုးရန်" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 5750d26784..47b4635010 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -52,7 +52,7 @@ "Avinstaller" "Info om appen" "Installer" - "Ikke foreslå appen" + "Ikke foreslå app" "Fest forslaget" "installere snarveier" "Gir apper tillatelse til å legge til snarveier uten innblanding fra brukeren." diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index 105c033fc3..c6e2ba1dfe 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -52,7 +52,7 @@ "ଅନଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" "ଆପ୍‌ ସୂଚନା" "ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" - "ଆପ୍ ସୁପାରିଶ କରନ୍ତୁ ନାହିଁ" + "ଆପ୍ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ" "ପୂର୍ବାନୁମାନକୁ ପିନ୍ କରନ୍ତୁ" "ଶର୍ଟକଟ୍‍ ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" "ୟୁଜରଙ୍କ ବିନା ହସ୍ତକ୍ଷେପରେ ଶର୍ଟକଟ୍‌ ଯୋଡ଼ିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 8b90a65394..c1d7dfadb0 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -53,7 +53,7 @@ "ਐਪ ਜਾਣਕਾਰੀ" "ਸਥਾਪਤ ਕਰੋ" "ਐਪ ਦਾ ਸੁਝਾਅ ਨਾ ਦਿਓ" - "ਪਿੰਨ ਦਾ ਪੂਰਵ-ਅਨੁਮਾਨ" + "ਪੂਰਵ-ਅਨੁਮਾਨ ਪਿੰਨ ਕਰੋ" "ਸ਼ਾਰਟਕੱਟ ਸਥਾਪਤ ਕਰੋ" "ਇੱਕ ਐਪ ਨੂੰ ਵਰਤੋਂਕਾਰ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹੋ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 49dceb06e8..24fe6f99ee 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -53,7 +53,7 @@ "O aplikacji" "Zainstaluj" "Nie proponuj aplikacji" - "Podpowiadanie kodu PIN" + "Przypnij podpowiedź" "instalowanie skrótów" "Pozwala aplikacji dodawać skróty bez interwencji użytkownika." "odczytywanie ustawień i skrótów na ekranie głównym" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 9d144294e1..4d8ba8860f 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -52,7 +52,7 @@ "Удалить" "О приложении" "Установить" - "Скрыть рекомендацию" + "Не рекомендовать" "Закрепить рекомендацию" "Создание ярлыков" "Приложение сможет самостоятельно добавлять ярлыки." diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index ab980633d3..e3b7894bf8 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -53,7 +53,7 @@ "Info o aplikácii" "Inštalovať" "Nenavrhovať aplikáciu" - "Pripnúť predpovedanú aplikáciu" + "Pripnúť predpoveď" "inštalovať odkazy" "Povoľuje aplikácii pridať odkazy bez zásahu používateľa." "čítanie nastavení a odkazov plochy" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 91d76b5ec6..7ec3652069 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -52,7 +52,7 @@ "Odmesti" "Podatki o aplikaciji" "Namesti" - "Ne predlagaj aplikacije" + "Ne predlagaj aplikacij" "Predvidevanje pripenjanja" "namestitev bližnjic" "Aplikaciji dovoli dodajanje bližnjic brez posredovanja uporabnika." diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index e3082daf37..c021061f60 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -50,10 +50,10 @@ "Faqja kryesore" "Hiqe" "Çinstalo" - "Informacion mbi aplikacionin" + "Info mbi aplikacionin" "Instalo" "Mos sugjero aplikacion" - "Gozhdo aplikacionin e parashikuar" + "Gozhdo parashikimin" "instalo shkurtore" "Lejon një aplikacion të shtojë shkurtore pa ndërhyrjen e përdoruesit." "lexo cilësimet dhe shkurtoret e ekranit bazë" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 758ec6cf6a..a197f9e5d1 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -50,7 +50,7 @@ "Почетна" "Уклони" "Деинсталирај" - "Информ. о апликацији" + "Инфор. о апликацији" "Инсталирај" "Не предлажи апликацију" "Закачи предвиђање" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 2d3d446179..9816896fd6 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -53,7 +53,7 @@ "యాప్ సమాచారం" "ఇన్‌స్టాల్ చేయండి" "యాప్‌ను సూచించవద్దు" - "పిన్ సూచన" + "సూచనను పిన్ చేయండి" "షార్ట్‌కట్‌లను ఇన్‌స్టాల్ చేయడం" "వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 15498804ff..6a9a485911 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -52,8 +52,8 @@ "ถอนการติดตั้ง" "ข้อมูลแอป" "ติดตั้ง" - "อย่าแนะนำแอป" - "การคาดการณ์ PIN" + "ไม่ต้องแนะนำแอป" + "ตรึงแอปที่คาดการณ์ไว้" "ติดตั้งทางลัด" "อนุญาตให้แอปเพิ่มทางลัดโดยไม่ต้องให้ผู้ใช้จัดการ" "อ่านการตั้งค่าและทางลัดหน้าแรกแล้ว" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 002a75265f..15321244c4 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -52,8 +52,8 @@ "O‘chirib tashlash" "Ilova haqida" "O‘rnatish" - "Ilova taklif qilinmasin" - "Ilovalarni mahkamlash taklifi" + "Tavsiya qilinmasin" + "Tavsiyani mahkamlash" "yorliqlar yaratish" "Ilovalarga foydalanuvchidan so‘ramasdan yorliqlar qo‘shishga ruxsat beradi." "Uy sozlamalari va yorliqlarini o‘qish" From 19496b916b9a994fd8466b09e3c8c9f0f290f2f3 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 20 Jul 2020 14:03:37 -0700 Subject: [PATCH 08/51] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I4c326e8cf15da316393c3be70f6b1c8dfc559a52 --- res/values-az/strings.xml | 2 +- res/values-b+sr+Latn/strings.xml | 2 +- res/values-be/strings.xml | 2 +- res/values-bg/strings.xml | 2 +- res/values-bs/strings.xml | 4 ++-- res/values-de/strings.xml | 2 +- res/values-el/strings.xml | 2 +- res/values-fi/strings.xml | 2 +- res/values-fr-rCA/strings.xml | 4 ++-- res/values-gu/strings.xml | 2 +- res/values-hr/strings.xml | 2 +- res/values-hu/strings.xml | 2 +- res/values-in/strings.xml | 2 +- res/values-iw/strings.xml | 4 ++-- res/values-ja/strings.xml | 2 +- res/values-ml/strings.xml | 4 ++-- res/values-my/strings.xml | 2 +- res/values-nb/strings.xml | 2 +- res/values-or/strings.xml | 2 +- res/values-pa/strings.xml | 2 +- res/values-pl/strings.xml | 2 +- res/values-ru/strings.xml | 2 +- res/values-sk/strings.xml | 2 +- res/values-sl/strings.xml | 2 +- res/values-sq/strings.xml | 4 ++-- res/values-sr/strings.xml | 2 +- res/values-te/strings.xml | 2 +- res/values-th/strings.xml | 4 ++-- res/values-uz/strings.xml | 4 ++-- 29 files changed, 36 insertions(+), 36 deletions(-) diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 72d211c44c..aed975ac42 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -52,7 +52,7 @@ "Sistemdən sil" "Tətbiq infosu" "Quraşdırın" - "Tətbiq təklif etməyin" + "Tətbiq təklif olunmasın" "Proqnozlaşdırılan tətbiqi bərkidin" "qısayolları quraşdır" "Tətbiqə istifadəçi müdaxiləsi olmadan qısayolları əlavə etməyə icazə verir." diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 8f6f8c1cb9..e8123688e1 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -50,7 +50,7 @@ "Početna" "Ukloni" "Deinstaliraj" - "Inform. o aplikaciji" + "Infor. o aplikaciji" "Instaliraj" "Ne predlaži aplikaciju" "Zakači predviđanje" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 14bfd8b551..0b2b6f1bc9 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -50,7 +50,7 @@ "Галоўная" "Выдаліць" "Дэінсталяваць" - "Звесткі пра праграмы" + "Пра праграму" "Усталяваць" "Не прапаноўваць праграму" "Замацаваць прапанаваную праграму" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 0d06ead6b7..512a7fc069 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -50,7 +50,7 @@ "Начало" "Премахване" "Деинсталиране" - "Инфо за прилож." + "Информация за прилож." "Инсталиране" "Без предлагане на приложение" "Фиксиране на предвиждането" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index bf07ed5ea8..6ce19d8fe6 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -50,10 +50,10 @@ "Početna" "Ukloni" "Deinstaliraj" - "Informacije o aplikaciji" + "Inform. o aplikaciji" "Instaliraj" "Ne predlaži aplikaciju" - "Predviđanje PIN-a" + "Zakači predviđanje" "instaliraj prečice" "Dopušta aplikaciji dodavanje prečica bez posredovanja korisnika." "čitaj postavke na početnom ekranu i prečice" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 520d64a103..fdd92142ac 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -52,7 +52,7 @@ "Deinstallieren" "App-Info" "Installieren" - "App nicht empfehlen" + "App nicht vorschlagen" "Vorgeschlagene App anpinnen" "Verknüpfungen installieren" "Ermöglicht einer App das Hinzufügen von Verknüpfungen ohne Eingreifen des Nutzers" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 2bb266b771..5d72b77410 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -50,7 +50,7 @@ "Αρχική οθόνη" "Κατάργηση" "Απεγκατάσταση" - "Πληροφορίες εφαρμογής" + "Πληροφ. εφαρμογής" "Εγκατάσταση" "Να μην προτείνεται η εφαρμογή" "Καρφίτσωμα πρόβλεψης" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 2dbc9df998..9fea032da6 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -53,7 +53,7 @@ "Sovelluksen tiedot" "Asenna" "Älä ehdota sovellusta" - "Kiinnitä ennakoitu sovellus" + "Kiinnitä sovellus" "asenna pikakuvakkeita" "Antaa sovelluksen lisätä pikakuvakkeita itsenäisesti ilman käyttäjän valintaa." "lue aloitusruudun asetuksia ja pikakuvakkeita" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 23fd8d849d..aaffbd1a1d 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -50,10 +50,10 @@ "Accueil" "Supprimer" "Désinstaller" - "Détails de l\'application" + "Détails sur l\'appli" "Installer" "Ne pas suggérer d\'application" - "Prédiction d\'épinglage" + "Épingler la prédiction" "installer des raccourcis" "Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur." "lire les paramètres et les raccourcis de la page d\'accueil" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 8f49421bda..01ecf73f02 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -50,7 +50,7 @@ "હોમ" "દૂર કરો" "અનઇન્સ્ટોલ કરો" - "ઍપ્લિકેશન માહિતી" + "ઍપની માહિતી" "ઇન્સ્ટૉલ કરો" "ઍપ સૂચવશો નહીં" "પૂર્વાનુમાનને પિન કરો" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index f24dc06469..dd13ef0caf 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -53,7 +53,7 @@ "Info o aplikaciji" "Instaliraj" "Ne predlaži aplikaciju" - "Prikvači predviđenu aplikaciju" + "Prikvači predviđenu apl." "instaliranje prečaca" "Aplikaciji omogućuje dodavanje prečaca bez intervencije korisnika." "čitanje postavki početnog zaslona i prečaca" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 60c043fbe8..4f03908836 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -53,7 +53,7 @@ "Alkalmazásinformáció" "Telepítés" "Ne javasoljon alkalmazást" - "Várható kitűzés" + "Várható kitűzése" "parancsikonok telepítése" "Lehetővé teszi egy alkalmazás számára, hogy felhasználói beavatkozás nélkül adjon hozzá parancsikonokat." "Főoldal beállításainak és parancsikonjainak beolvasása" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 9a49be55de..242e808040 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -53,7 +53,7 @@ "Info aplikasi" "Instal" "Jangan sarankan aplikasi" - "Pasang Pin pada Prediksi" + "Pin Prediksi" "memasang pintasan" "Mengizinkan aplikasi menambahkan pintasan tanpa campur tangan pengguna." "membaca setelan dan pintasan layar Utama" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 17af02335d..a2068aa6ac 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -52,7 +52,7 @@ "להסרת התקנה" "פרטי אפליקציה" "התקנה" - "לא להציע את האפליקציה" + "בלי להציע את האפליקציה" "הצמדת החיזוי" "התקן קיצורי דרך" "מאפשר לאפליקציה להוסיף קיצורי דרך ללא התערבות המשתמש." @@ -132,7 +132,7 @@ "גודל הווידג\'ט שונה - רוחב %1$s גובה %2$s" "קיצורי דרך" "קיצורי דרך והתראות" - "סגור" + "סגירה" "סגירה" "ההתראה נסגרה" "אישיות" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 0be3a0ff54..a6e37c4fb4 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -53,7 +53,7 @@ "アプリ情報" "インストール" "アプリの候補を表示しない" - "予測を固定" + "アプリの候補を固定表示" "ショートカットのインストール" "ユーザー操作なしでショートカットを追加することをアプリに許可します。" "ホームの設定とショートカットの読み取り" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 0d0a9518d4..01d8935672 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -50,10 +50,10 @@ "ഹോം" "നീക്കംചെയ്യുക" "അൺഇൻസ്റ്റാളുചെയ്യുക" - "ആപ്പ് വിവരം" + "ആപ്പ് വിവരങ്ങൾ" "ഇൻസ്‌റ്റാൾ ചെയ്യുക" "ആപ്പ് നിർദ്ദേശിക്കരുത്" - "പിൻ പ്രവചനം" + "പ്രവചനം പിൻ ചെയ്യുക" "കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക" "ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." "ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 4e465caf71..d753021886 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -50,7 +50,7 @@ "ပင်မစာမျက်နှာ" "ဖယ်ရှားမည်" "ဖြုတ်ရန်" - "အက်ပ်အချက်အလက်များ" + "အက်ပ်အချက်အလက်" "ထည့်သွင်းရန်" "အက်ပ်ကို အကြံမပြုပါနှင့်" "ခန့်မှန်းချက်ကို ပင်ထိုးရန်" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 5750d26784..47b4635010 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -52,7 +52,7 @@ "Avinstaller" "Info om appen" "Installer" - "Ikke foreslå appen" + "Ikke foreslå app" "Fest forslaget" "installere snarveier" "Gir apper tillatelse til å legge til snarveier uten innblanding fra brukeren." diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index 105c033fc3..c6e2ba1dfe 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -52,7 +52,7 @@ "ଅନଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" "ଆପ୍‌ ସୂଚନା" "ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" - "ଆପ୍ ସୁପାରିଶ କରନ୍ତୁ ନାହିଁ" + "ଆପ୍ ପରାମର୍ଶ ଦିଅନ୍ତୁ ନାହିଁ" "ପୂର୍ବାନୁମାନକୁ ପିନ୍ କରନ୍ତୁ" "ଶର୍ଟକଟ୍‍ ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" "ୟୁଜରଙ୍କ ବିନା ହସ୍ତକ୍ଷେପରେ ଶର୍ଟକଟ୍‌ ଯୋଡ଼ିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 8b90a65394..c1d7dfadb0 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -53,7 +53,7 @@ "ਐਪ ਜਾਣਕਾਰੀ" "ਸਥਾਪਤ ਕਰੋ" "ਐਪ ਦਾ ਸੁਝਾਅ ਨਾ ਦਿਓ" - "ਪਿੰਨ ਦਾ ਪੂਰਵ-ਅਨੁਮਾਨ" + "ਪੂਰਵ-ਅਨੁਮਾਨ ਪਿੰਨ ਕਰੋ" "ਸ਼ਾਰਟਕੱਟ ਸਥਾਪਤ ਕਰੋ" "ਇੱਕ ਐਪ ਨੂੰ ਵਰਤੋਂਕਾਰ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" "ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹੋ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 49dceb06e8..24fe6f99ee 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -53,7 +53,7 @@ "O aplikacji" "Zainstaluj" "Nie proponuj aplikacji" - "Podpowiadanie kodu PIN" + "Przypnij podpowiedź" "instalowanie skrótów" "Pozwala aplikacji dodawać skróty bez interwencji użytkownika." "odczytywanie ustawień i skrótów na ekranie głównym" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 9d144294e1..4d8ba8860f 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -52,7 +52,7 @@ "Удалить" "О приложении" "Установить" - "Скрыть рекомендацию" + "Не рекомендовать" "Закрепить рекомендацию" "Создание ярлыков" "Приложение сможет самостоятельно добавлять ярлыки." diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index ab980633d3..e3b7894bf8 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -53,7 +53,7 @@ "Info o aplikácii" "Inštalovať" "Nenavrhovať aplikáciu" - "Pripnúť predpovedanú aplikáciu" + "Pripnúť predpoveď" "inštalovať odkazy" "Povoľuje aplikácii pridať odkazy bez zásahu používateľa." "čítanie nastavení a odkazov plochy" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 91d76b5ec6..7ec3652069 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -52,7 +52,7 @@ "Odmesti" "Podatki o aplikaciji" "Namesti" - "Ne predlagaj aplikacije" + "Ne predlagaj aplikacij" "Predvidevanje pripenjanja" "namestitev bližnjic" "Aplikaciji dovoli dodajanje bližnjic brez posredovanja uporabnika." diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index e3082daf37..c021061f60 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -50,10 +50,10 @@ "Faqja kryesore" "Hiqe" "Çinstalo" - "Informacion mbi aplikacionin" + "Info mbi aplikacionin" "Instalo" "Mos sugjero aplikacion" - "Gozhdo aplikacionin e parashikuar" + "Gozhdo parashikimin" "instalo shkurtore" "Lejon një aplikacion të shtojë shkurtore pa ndërhyrjen e përdoruesit." "lexo cilësimet dhe shkurtoret e ekranit bazë" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 758ec6cf6a..a197f9e5d1 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -50,7 +50,7 @@ "Почетна" "Уклони" "Деинсталирај" - "Информ. о апликацији" + "Инфор. о апликацији" "Инсталирај" "Не предлажи апликацију" "Закачи предвиђање" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 2d3d446179..9816896fd6 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -53,7 +53,7 @@ "యాప్ సమాచారం" "ఇన్‌స్టాల్ చేయండి" "యాప్‌ను సూచించవద్దు" - "పిన్ సూచన" + "సూచనను పిన్ చేయండి" "షార్ట్‌కట్‌లను ఇన్‌స్టాల్ చేయడం" "వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." "హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 15498804ff..6a9a485911 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -52,8 +52,8 @@ "ถอนการติดตั้ง" "ข้อมูลแอป" "ติดตั้ง" - "อย่าแนะนำแอป" - "การคาดการณ์ PIN" + "ไม่ต้องแนะนำแอป" + "ตรึงแอปที่คาดการณ์ไว้" "ติดตั้งทางลัด" "อนุญาตให้แอปเพิ่มทางลัดโดยไม่ต้องให้ผู้ใช้จัดการ" "อ่านการตั้งค่าและทางลัดหน้าแรกแล้ว" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 002a75265f..15321244c4 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -52,8 +52,8 @@ "O‘chirib tashlash" "Ilova haqida" "O‘rnatish" - "Ilova taklif qilinmasin" - "Ilovalarni mahkamlash taklifi" + "Tavsiya qilinmasin" + "Tavsiyani mahkamlash" "yorliqlar yaratish" "Ilovalarga foydalanuvchidan so‘ramasdan yorliqlar qo‘shishga ruxsat beradi." "Uy sozlamalari va yorliqlarini o‘qish" From bd1f4c6a76b42246b7edc4d1cc9de733cf1d3eff Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 20 Jul 2020 13:05:13 -0700 Subject: [PATCH 09/51] Allow multiple hotseat restorations in single session restoreBackup uses mBackupRestored to prevent multiple restorations happening at once. This change is required to reset the value of mBackupRestored if a new backup is created. Bug: 160033826 Test: Manual Change-Id: I33836b26cf3876955cc14dcc8ec06202f3fe7fac --- .../android/launcher3/hybridhotseat/HotseatRestoreHelper.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java index 8c1db4e2e7..9e7c9fba6d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java @@ -30,7 +30,6 @@ import com.android.launcher3.provider.LauncherDbUtils; */ public class HotseatRestoreHelper { private final Launcher mLauncher; - private boolean mBackupRestored = false; HotseatRestoreHelper(Launcher context) { mLauncher = context; @@ -62,7 +61,6 @@ public class HotseatRestoreHelper { * Finds and restores a previously saved snapshow of Favorites table */ public void restoreBackup() { - if (mBackupRestored) return; MODEL_EXECUTOR.execute(() -> { try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction) LauncherSettings.Settings.call( @@ -78,7 +76,6 @@ public class HotseatRestoreHelper { idp.numRows); backupTable.restoreFromCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE, true); transaction.commit(); - mBackupRestored = true; mLauncher.getModel().forceReload(); } }); From 5b7bf9147b7cf99116f4ed28dd367444b4876d26 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 20 Jul 2020 13:57:56 -0700 Subject: [PATCH 10/51] Create a new instance of rotation touch helper per device state Change-Id: I4e4288eaf37aab5bf0b8115f5e06e64459c20f00 (cherry picked from commit 00850fb588bf7b33b49d4771883039d5fd70be81) --- .../com/android/quickstep/RecentsAnimationDeviceState.java | 2 +- quickstep/src/com/android/quickstep/RotationTouchHelper.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index dd80bd758e..7a6bbb4ab9 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -114,7 +114,7 @@ public class RecentsAnimationDeviceState implements mDefaultDisplay = DefaultDisplay.INSTANCE.get(context); mDisplayId = mDefaultDisplay.getInfo().id; runOnDestroy(() -> mDefaultDisplay.removeChangeListener(this)); - mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context); + mRotationTouchHelper = new RotationTouchHelper(context); runOnDestroy(mRotationTouchHelper::destroy); // Register for user unlocked if necessary diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java index d89ca10b69..5f3c02205e 100644 --- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java +++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java @@ -41,8 +41,6 @@ import java.util.ArrayList; public class RotationTouchHelper implements SysUINavigationMode.NavigationModeChangeListener, DefaultDisplay.DisplayInfoChangeListener { - public static final MainThreadInitializedObject INSTANCE = - new MainThreadInitializedObject<>(RotationTouchHelper::new); private final OrientationTouchTransformer mOrientationTouchTransformer; private final DefaultDisplay mDefaultDisplay; @@ -122,7 +120,7 @@ public class RotationTouchHelper implements private final Context mContext; - private RotationTouchHelper(Context context) { + public RotationTouchHelper(Context context) { mContext = context; Resources resources = mContext.getResources(); mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context); From 0f620500b06342d496fa69d9f1677f4b883ddf40 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 20 Jul 2020 15:28:25 -0700 Subject: [PATCH 11/51] Fix bug where realtimeReorder is called after views have been unbound. Bug: 161498651 Change-Id: I89beaad9a91bfa1763454965bf95ba1a94d29902 --- src/com/android/launcher3/folder/FolderPagedView.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index 32531c040f..a08dd3064a 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -500,6 +500,9 @@ public class FolderPagedView extends PagedView { * Reorders the items such that the {@param empty} spot moves to {@param target} */ public void realTimeReorder(int empty, int target) { + if (!mViewsBound) { + return; + } completePendingPageChanges(); int delay = 0; float delayAmount = START_VIEW_REORDER_DELAY; From 447ea429cd9f48a608c11dbef7dec1d2ab22d1ef Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 20 Jul 2020 16:54:17 -0700 Subject: [PATCH 12/51] Fix folder crash where view is added when it already has a parent. The fix is to prevent re-arrangement if the views are already unbound. This is caused when: - Folder is open - Item has deep shortcuts - Long press on deep shortcut to create DragView that could land in the folder if the folder did not auto close. This is important because it starts a drag within the folder The folder unbinds all views as part of the Folder close complete callback. And then the folder exit alarm gets triggered (because we drag DragView outside of the folder) which causes the folder items to get rearranged and added back to the folder's CellLayout. Bug: 161559911 Change-Id: I142589b2c541dc21c47a67c20a93e627732107ef --- src/com/android/launcher3/folder/Folder.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index de2b5da6ad..b91d1c3260 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -1135,6 +1135,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo * Rearranges the children based on their rank. */ public void rearrangeChildren() { + if (!mContent.areViewsBound()) { + return; + } mContent.arrangeChildren(getIconsInReadingOrder()); mItemsInvalidated = true; } From f1af0171b7c6b8f82179f2bfffda33f82ee16399 Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Mon, 20 Jul 2020 11:54:38 -0700 Subject: [PATCH 13/51] Fix launcher crash after restore with some specific widgets. The internal implementation of PendingAppWidgetHostView#getDefaultViews uses the same view across updates which causes the exception in AppWidgetHostView#applyContent when it tries to call addView() because the view has already been added to its parent view in previous iteration. Bug: 151901506 Test: manual Change-Id: Ieccec814ac514e592d0d4f196b60ba89aec0d661 --- .../launcher3/widget/PendingAppWidgetHostView.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java index 9021d9eb21..ca47728020 100644 --- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java @@ -52,7 +52,6 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView private static final float MIN_SATUNATION = 0.7f; private final Rect mRect = new Rect(); - private View mDefaultView; private OnClickListener mClickListener; private final LauncherAppWidgetInfo mInfo; private final int mStartState; @@ -111,12 +110,11 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView @Override protected View getDefaultView() { - if (mDefaultView == null) { - mDefaultView = mInflater.inflate(R.layout.appwidget_not_ready, this, false); - mDefaultView.setOnClickListener(this); - applyState(); - } - return mDefaultView; + View defaultView = mInflater.inflate(R.layout.appwidget_not_ready, this, false); + defaultView.setOnClickListener(this); + applyState(); + invalidate(); + return defaultView; } @Override From 354b8fc0810ae7c965183d3fc31cdc3965da1ac9 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 10 Jul 2020 21:07:55 +0800 Subject: [PATCH 14/51] Use display of activity to get rotation for recents The rotation of WindowConfiguration in Configuration is non-public field. There is no guarantee that the information will be updated. E.g. a 180 degree rotation change won't make difference to the public configurations, so the Resources will keep the old one. The display rotation of activity is accurate to use for its content because even the activity is transformed to different rotation than the physical display, there is FixedRotationAdjustments to adjust the information which will be consistent as how the activity is laid out. Bug: 159877752 Test: 1. Enable auto rotation. 2. Launch some portrait activities. 3. Put device in reverse portrait (upside down). 4. Launch a landscape activity. 5. Swipe to another activity with full-sensor orientation. 6. Return to home and enter recents to check the task views of step 2 don't show upside down. Change-Id: I5e16e71d43b8892a394c06de9e76fb3d4ad55919 --- .../android/quickstep/BaseSwipeUpHandlerV2.java | 2 +- .../quickstep/util/TaskViewSimulator.java | 4 ++-- .../com/android/quickstep/views/RecentsView.java | 4 ++-- .../quickstep/views/TaskThumbnailView.java | 5 ++--- .../quickstep/util/RecentsOrientedState.java | 16 +++++----------- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index e084de1acb..80c145a959 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -333,7 +333,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) { return; } - mTaskViewSimulator.setRecentsConfiguration(mActivity.getResources().getConfiguration()); + mTaskViewSimulator.setRecentsRotation(mActivity.getDisplay().getRotation()); // If we've already ended the gesture and are going home, don't prepare recents UI, // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL. diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java index c9ed498af1..8a6efe4715 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java @@ -129,8 +129,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { /** * @see com.android.quickstep.views.RecentsView#onConfigurationChanged(Configuration) */ - public void setRecentsConfiguration(Configuration configuration) { - mOrientationState.setActivityConfiguration(configuration); + public void setRecentsRotation(int recentsRotation) { + mOrientationState.setRecentsRotation(recentsRotation); mLayoutValid = false; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 027a737cef..49c83e45fc 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -393,7 +393,7 @@ public abstract class RecentsView extends PagedView mActivity = BaseActivity.fromContext(context); mOrientationState = new RecentsOrientedState( context, mSizeStrategy, this::animateRecentsRotationInPlace); - mOrientationState.setActivityConfiguration(context.getResources().getConfiguration()); + mOrientationState.setRecentsRotation(mActivity.getDisplay().getRotation()); mFastFlingVelocity = getResources() .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity); @@ -1657,7 +1657,7 @@ public abstract class RecentsView extends PagedView @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - if (mOrientationState.setActivityConfiguration(newConfig)) { + if (mOrientationState.setRecentsRotation(mActivity.getDisplay().getRotation())) { updateOrientationHandler(); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index 37f6faf523..a8d6442135 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -59,7 +59,6 @@ import com.android.systemui.plugins.OverviewScreenshotActions; import com.android.systemui.plugins.PluginListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; -import com.android.systemui.shared.system.ConfigurationCompat; /** * A task in the Recents view. @@ -385,8 +384,8 @@ public class TaskThumbnailView extends View implements PluginListener Date: Wed, 24 Jun 2020 23:47:46 -0700 Subject: [PATCH 15/51] Adding home animation support for non-system Launcher When user swipes up to home, Launcher will receive a onNewIntent callwith a bundle-extra gesture_nav_contract_v1. It will contain the componentName & UserHandle of the closing app & a callback. Launcher can use the callback to return the final position where the app should animate to and an optional surface to be used for crossFade animation. The surface cleanup can be handled in onEnterAnimationComplete. Change-Id: I76fdd810fdcb80b71f7d7588ccac8976d9dfe278 --- .../quickstep/FallbackSwipeHandler.java | 138 +++++++++- .../launcher3/BaseQuickstepLauncher.java | 7 + res/layout/floating_surface_view.xml | 19 ++ .../launcher3/AbstractFloatingView.java | 9 +- src/com/android/launcher3/BubbleTextView.java | 14 +- .../android/launcher3/GestureNavContract.java | 101 ++++++++ src/com/android/launcher3/Launcher.java | 15 ++ .../launcher3/views/FloatingIconView.java | 20 +- .../launcher3/views/FloatingSurfaceView.java | 241 ++++++++++++++++++ 9 files changed, 546 insertions(+), 18 deletions(-) create mode 100644 res/layout/floating_surface_view.xml create mode 100644 src/com/android/launcher3/GestureNavContract.java create mode 100644 src/com/android/launcher3/views/FloatingSurfaceView.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java index 1909f4772e..f60a50bb43 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java @@ -15,14 +15,35 @@ */ package com.android.quickstep; +import static android.content.Intent.EXTRA_COMPONENT_NAME; +import static android.content.Intent.EXTRA_USER; + +import static com.android.launcher3.GestureNavContract.EXTRA_GESTURE_CONTRACT; +import static com.android.launcher3.GestureNavContract.EXTRA_ICON_POSITION; +import static com.android.launcher3.GestureNavContract.EXTRA_ICON_SURFACE; +import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; import android.animation.ObjectAnimator; +import android.annotation.TargetApi; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.graphics.Matrix; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.ParcelUuid; +import android.os.UserHandle; +import android.view.Surface; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; import androidx.annotation.NonNull; @@ -32,19 +53,33 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.SpringAnimationBuilder; import com.android.quickstep.fallback.FallbackRecentsView; +import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.TransformParams; import com.android.quickstep.util.TransformParams.BuilderProxy; +import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; +import java.lang.ref.WeakReference; +import java.util.UUID; +import java.util.function.Consumer; + /** * Handles the navigation gestures when a 3rd party launcher is the default home activity. */ +@TargetApi(Build.VERSION_CODES.R) public class FallbackSwipeHandler extends BaseSwipeUpHandlerV2 { + /** + * Message used for receiving gesture nav contract information. We use a static messenger to + * avoid leaking too make binders in case the receiving launcher does not handle the contract + * properly. + */ + private static StaticMessageReceiver sMessageReceiver = null; + private FallbackHomeAnimationFactory mActiveAnimationFactory; private final boolean mRunningOverHome; @@ -89,7 +124,9 @@ public class FallbackSwipeHandler extends protected HomeAnimationFactory createHomeAnimationFactory(long duration) { mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); - mContext.startActivity(new Intent(mGestureState.getHomeIntent()), options.toBundle()); + Intent intent = new Intent(mGestureState.getHomeIntent()); + mActiveAnimationFactory.addGestureContract(intent); + mContext.startActivity(intent, options.toBundle()); return mActiveAnimationFactory; } @@ -130,15 +167,19 @@ public class FallbackSwipeHandler extends } private class FallbackHomeAnimationFactory extends HomeAnimationFactory { - + private final Rect mTempRect = new Rect(); private final TransformParams mHomeAlphaParams = new TransformParams(); private final AnimatedFloat mHomeAlpha; private final AnimatedFloat mVerticalShiftForScale = new AnimatedFloat(); - private final AnimatedFloat mRecentsAlpha = new AnimatedFloat(); + private final RectF mTargetRect = new RectF(); + private SurfaceControl mSurfaceControl; + private final long mDuration; + + private RectFSpringAnim mSpringAnim; FallbackHomeAnimationFactory(long duration) { mDuration = duration; @@ -161,6 +202,15 @@ public class FallbackSwipeHandler extends this::updateRecentsActivityTransformDuringHomeAnim); } + @NonNull + @Override + public RectF getWindowTargetRect() { + if (mTargetRect.isEmpty()) { + mTargetRect.set(super.getWindowTargetRect()); + } + return mTargetRect; + } + private void updateRecentsActivityTransformDuringHomeAnim(SurfaceParams.Builder builder, RemoteAnimationTargetCompat app, TransformParams params) { builder.withAlpha(mRecentsAlpha.value); @@ -217,5 +267,87 @@ public class FallbackSwipeHandler extends .start(); } } + + @Override + public void setAnimation(RectFSpringAnim anim) { + mSpringAnim = anim; + } + + private void onMessageReceived(Message msg) { + try { + Bundle data = msg.getData(); + RectF position = data.getParcelable(EXTRA_ICON_POSITION); + if (!position.isEmpty()) { + mSurfaceControl = data.getParcelable(EXTRA_ICON_SURFACE); + mTargetRect.set(position); + if (mSpringAnim != null) { + mSpringAnim.onTargetPositionChanged(); + } + } + } catch (Exception e) { + // Ignore + } + } + + @Override + public void update(RectF currentRect, float progress, float radius) { + if (mSurfaceControl != null) { + currentRect.roundOut(mTempRect); + Transaction t = new Transaction(); + t.setGeometry(mSurfaceControl, null, mTempRect, Surface.ROTATION_0); + t.apply(); + } + } + + private void addGestureContract(Intent intent) { + if (mRunningOverHome || mGestureState.getRunningTask() == null) { + return; + } + + TaskKey key = new TaskKey(mGestureState.getRunningTask()); + if (key.getComponent() != null) { + if (sMessageReceiver == null) { + sMessageReceiver = new StaticMessageReceiver(); + } + + Bundle gestureNavContract = new Bundle(); + gestureNavContract.putParcelable(EXTRA_COMPONENT_NAME, key.getComponent()); + gestureNavContract.putParcelable(EXTRA_USER, UserHandle.of(key.userId)); + gestureNavContract.putParcelable(EXTRA_REMOTE_CALLBACK, + sMessageReceiver.newCallback(this::onMessageReceived)); + intent.putExtra(EXTRA_GESTURE_CONTRACT, gestureNavContract); + } + } + } + + private static class StaticMessageReceiver implements Handler.Callback { + + private final Messenger mMessenger = + new Messenger(new Handler(Looper.getMainLooper(), this)); + + private ParcelUuid mCurrentUID = new ParcelUuid(UUID.randomUUID()); + private WeakReference> mCurrentCallback = new WeakReference<>(null); + + public Message newCallback(Consumer callback) { + mCurrentUID = new ParcelUuid(UUID.randomUUID()); + mCurrentCallback = new WeakReference<>(callback); + + Message msg = Message.obtain(); + msg.replyTo = mMessenger; + msg.obj = mCurrentUID; + return msg; + } + + @Override + public boolean handleMessage(@NonNull Message message) { + if (mCurrentUID.equals(message.obj)) { + Consumer consumer = mCurrentCallback.get(); + if (consumer != null) { + consumer.accept(message); + return true; + } + } + return false; + } } } diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 6b941be471..235df425b4 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -110,6 +110,13 @@ public abstract class BaseQuickstepLauncher extends Launcher .getHighResLoadingState().setVisible(true); } + @Override + protected void handleGestureContract(Intent intent) { + if (FeatureFlags.SEPARATE_RECENTS_ACTIVITY.get()) { + super.handleGestureContract(intent); + } + } + @Override public void onTrimMemory(int level) { super.onTrimMemory(level); diff --git a/res/layout/floating_surface_view.xml b/res/layout/floating_surface_view.xml new file mode 100644 index 0000000000..434e84f269 --- /dev/null +++ b/res/layout/floating_surface_view.xml @@ -0,0 +1,19 @@ + + + diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index cd27a2ddca..ce37a30160 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -62,7 +62,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch TYPE_ALL_APPS_EDU, TYPE_TASK_MENU, - TYPE_OPTIONS_POPUP + TYPE_OPTIONS_POPUP, + TYPE_ICON_SURFACE }) @Retention(RetentionPolicy.SOURCE) public @interface FloatingViewType {} @@ -80,16 +81,18 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch // Popups related to quickstep UI public static final int TYPE_TASK_MENU = 1 << 10; public static final int TYPE_OPTIONS_POPUP = 1 << 11; + public static final int TYPE_ICON_SURFACE = 1 << 12; public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE | TYPE_TASK_MENU - | TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU; + | TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU + | TYPE_ICON_SURFACE; // Type of popups which should be kept open during launcher rebind public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE - | TYPE_ALL_APPS_EDU; + | TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE; // Usually we show the back button when a floating view is open. Instead, hide for these types. public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 48819cbfa0..198f13d02a 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -614,6 +614,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, @Override public void setIconVisible(boolean visible) { mIsIconVisible = visible; + if (!mIsIconVisible) { + resetIconScale(); + } Drawable icon = visible ? mIcon : new ColorDrawable(Color.TRANSPARENT); applyCompoundDrawables(icon); } @@ -753,11 +756,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, @Override public SafeCloseable prepareDrawDragView() { - if (getIcon() instanceof FastBitmapDrawable) { - FastBitmapDrawable icon = (FastBitmapDrawable) getIcon(); - icon.setScale(1f); - } + resetIconScale(); setForceHideDot(true); return () -> { }; } + + private void resetIconScale() { + if (mIcon instanceof FastBitmapDrawable) { + ((FastBitmapDrawable) mIcon).setScale(1f); + } + } } diff --git a/src/com/android/launcher3/GestureNavContract.java b/src/com/android/launcher3/GestureNavContract.java new file mode 100644 index 0000000000..2a7e629247 --- /dev/null +++ b/src/com/android/launcher3/GestureNavContract.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3; + +import static android.content.Intent.EXTRA_COMPONENT_NAME; +import static android.content.Intent.EXTRA_USER; + +import android.annotation.TargetApi; +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.RectF; +import android.os.Build; +import android.os.Bundle; +import android.os.Message; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; +import android.view.SurfaceControl; + +import androidx.annotation.Nullable; + +/** + * Class to encapsulate the handshake protocol between Launcher and gestureNav. + */ +public class GestureNavContract { + + private static final String TAG = "GestureNavContract"; + + public static final String EXTRA_GESTURE_CONTRACT = "gesture_nav_contract_v1"; + public static final String EXTRA_ICON_POSITION = "gesture_nav_contract_icon_position"; + public static final String EXTRA_ICON_SURFACE = "gesture_nav_contract_surface_control"; + public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK"; + + public final ComponentName componentName; + public final UserHandle user; + + private final Message mCallback; + + public GestureNavContract(ComponentName componentName, UserHandle user, Message callback) { + this.componentName = componentName; + this.user = user; + this.mCallback = callback; + } + + /** + * Sends the position information to the receiver + */ + @TargetApi(Build.VERSION_CODES.R) + public void sendEndPosition(RectF position, @Nullable SurfaceControl surfaceControl) { + Bundle result = new Bundle(); + result.putParcelable(EXTRA_ICON_POSITION, position); + result.putParcelable(EXTRA_ICON_SURFACE, surfaceControl); + + Message callback = Message.obtain(); + callback.copyFrom(mCallback); + callback.setData(result); + + try { + callback.replyTo.send(callback); + } catch (RemoteException e) { + Log.e(TAG, "Error sending icon position", e); + } + } + + /** + * Clears and returns the GestureNavContract if it was present in the intent. + */ + public static GestureNavContract fromIntent(Intent intent) { + if (!Utilities.ATLEAST_R) { + return null; + } + Bundle extras = intent.getBundleExtra(EXTRA_GESTURE_CONTRACT); + if (extras == null) { + return null; + } + intent.removeExtra(EXTRA_GESTURE_CONTRACT); + + ComponentName componentName = extras.getParcelable(EXTRA_COMPONENT_NAME); + UserHandle userHandle = extras.getParcelable(EXTRA_USER); + Message callback = extras.getParcelable(EXTRA_REMOTE_CALLBACK); + + if (componentName != null && userHandle != null && callback != null + && callback.replyTo != null) { + return new GestureNavContract(componentName, userHandle, callback); + } + return null; + } +} diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index d06ae7a9c5..4675362f64 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; +import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE; import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR; import static com.android.launcher3.InstallShortcutReceiver.FLAG_DRAG_AND_DROP; @@ -168,6 +169,7 @@ import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.UiThreadHelper; import com.android.launcher3.util.ViewOnDrawExecutor; import com.android.launcher3.views.ActivityContext; +import com.android.launcher3.views.FloatingSurfaceView; import com.android.launcher3.views.OptionsPopupView; import com.android.launcher3.views.ScrimView; import com.android.launcher3.widget.LauncherAppWidgetHostView; @@ -509,6 +511,7 @@ public class Launcher extends StatefulActivity implements Launche public void onEnterAnimationComplete() { super.onEnterAnimationComplete(); mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE); + AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE); } @Override @@ -1450,6 +1453,7 @@ public class Launcher extends StatefulActivity implements Launche mLauncherCallbacks.onHomeIntent(internalStateHandled); } mOverlayManager.hideOverlay(isStarted() && !isForceInvisible()); + handleGestureContract(intent); } else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) { getStateManager().goToState(ALL_APPS, alreadyOnHome); } @@ -1457,6 +1461,17 @@ public class Launcher extends StatefulActivity implements Launche TraceHelper.INSTANCE.endSection(traceToken); } + /** + * Handles gesture nav contract + */ + protected void handleGestureContract(Intent intent) { + GestureNavContract gnc = GestureNavContract.fromIntent(intent); + if (gnc != null) { + AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE); + FloatingSurfaceView.show(this, gnc); + } + } + /** * Hides the keyboard if visible */ diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index 7cdde2e84b..8186dfa3dc 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -196,13 +196,18 @@ public class FloatingIconView extends FrameLayout implements layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height); } + private static void getLocationBoundsForView(Launcher launcher, View v, boolean isOpening, + RectF outRect) { + getLocationBoundsForView(launcher, v, isOpening, outRect, new Rect()); + } + /** * Gets the location bounds of a view and returns the overall rotation. * - For DeepShortcutView, we return the bounds of the icon view. * - For BubbleTextView, we return the icon bounds. */ - private static void getLocationBoundsForView(Launcher launcher, View v, boolean isOpening, - RectF outRect) { + public static void getLocationBoundsForView(Launcher launcher, View v, boolean isOpening, + RectF outRect, Rect outViewBounds) { boolean ignoreTransform = !isOpening; if (v instanceof DeepShortcutView) { v = ((DeepShortcutView) v).getBubbleText(); @@ -215,17 +220,16 @@ public class FloatingIconView extends FrameLayout implements return; } - Rect iconBounds = new Rect(); if (v instanceof BubbleTextView) { - ((BubbleTextView) v).getIconBounds(iconBounds); + ((BubbleTextView) v).getIconBounds(outViewBounds); } else if (v instanceof FolderIcon) { - ((FolderIcon) v).getPreviewBounds(iconBounds); + ((FolderIcon) v).getPreviewBounds(outViewBounds); } else { - iconBounds.set(0, 0, v.getWidth(), v.getHeight()); + outViewBounds.set(0, 0, v.getWidth(), v.getHeight()); } - float[] points = new float[] {iconBounds.left, iconBounds.top, iconBounds.right, - iconBounds.bottom}; + float[] points = new float[] {outViewBounds.left, outViewBounds.top, outViewBounds.right, + outViewBounds.bottom}; Utilities.getDescendantCoordRelativeToAncestor(v, launcher.getDragLayer(), points, false, ignoreTransform); outRect.set( diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java new file mode 100644 index 0000000000..040619e9c7 --- /dev/null +++ b/src/com/android/launcher3/views/FloatingSurfaceView.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2020 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.views; + +import static com.android.launcher3.views.FloatingIconView.getLocationBoundsForView; +import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Picture; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; + +import androidx.annotation.NonNull; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.GestureNavContract; +import com.android.launcher3.Insettable; +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.util.DefaultDisplay; +import com.android.launcher3.util.Executors; + +/** + * Similar to {@link FloatingIconView} but displays a surface with the targetIcon. It then passes + * the surfaceHandle to the {@link GestureNavContract}. + */ +@TargetApi(Build.VERSION_CODES.R) +public class FloatingSurfaceView extends AbstractFloatingView implements + OnGlobalLayoutListener, Insettable, SurfaceHolder.Callback2 { + + private final RectF mTmpPosition = new RectF(); + + private final Launcher mLauncher; + private final RectF mIconPosition = new RectF(); + + private final Rect mIconBounds = new Rect(); + private final Picture mPicture = new Picture(); + private final Runnable mRemoveViewRunnable = this::removeViewFromParent; + + private final SurfaceView mSurfaceView; + + + private View mIcon; + private GestureNavContract mContract; + + public FloatingSurfaceView(Context context) { + this(context, null); + } + + public FloatingSurfaceView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public FloatingSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mLauncher = Launcher.getLauncher(context); + + mSurfaceView = new SurfaceView(context); + mSurfaceView.setZOrderOnTop(true); + + mSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); + mSurfaceView.getHolder().addCallback(this); + mIsOpen = true; + addView(mSurfaceView); + } + + @Override + protected void handleClose(boolean animate) { + setCurrentIconVisible(true); + mLauncher.getViewCache().recycleView(R.layout.floating_surface_view, this); + mContract = null; + mIcon = null; + mIsOpen = false; + + // Remove after some time, to avoid flickering + Executors.MAIN_EXECUTOR.getHandler().postDelayed(mRemoveViewRunnable, + DefaultDisplay.INSTANCE.get(mLauncher).getInfo().singleFrameMs); + } + + private void removeViewFromParent() { + mPicture.beginRecording(1, 1); + mPicture.endRecording(); + mLauncher.getDragLayer().removeView(this); + } + + /** + * Shows the surfaceView for the provided contract + */ + public static void show(Launcher launcher, GestureNavContract contract) { + FloatingSurfaceView view = launcher.getViewCache().getView(R.layout.floating_surface_view, + launcher, launcher.getDragLayer()); + view.mContract = contract; + view.mIsOpen = true; + + // Cancel any pending remove + Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(view.mRemoveViewRunnable); + view.removeViewFromParent(); + launcher.getDragLayer().addView(view); + } + + @Override + public void logActionCommand(int command) { } + + @Override + protected boolean isOfType(int type) { + return (type & TYPE_ICON_SURFACE) != 0; + } + + @Override + public boolean onControllerInterceptTouchEvent(MotionEvent ev) { + close(false); + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + getViewTreeObserver().addOnGlobalLayoutListener(this); + updateIconLocation(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getViewTreeObserver().removeOnGlobalLayoutListener(this); + setCurrentIconVisible(true); + } + + @Override + public void onGlobalLayout() { + updateIconLocation(); + } + + @Override + public void setInsets(Rect insets) { } + + private void updateIconLocation() { + if (mContract == null) { + return; + } + View icon = mLauncher.getWorkspace().getFirstMatchForAppClose( + mContract.componentName.getPackageName(), mContract.user); + + boolean iconChanged = mIcon != icon; + if (iconChanged) { + setCurrentIconVisible(true); + mIcon = icon; + setCurrentIconVisible(false); + } + + if (icon != null && icon.isAttachedToWindow()) { + getLocationBoundsForView(mLauncher, icon, false, mTmpPosition, mIconBounds); + + if (!mTmpPosition.equals(mIconPosition)) { + mIconPosition.set(mTmpPosition); + sendIconInfo(); + + LayoutParams lp = (LayoutParams) mSurfaceView.getLayoutParams(); + lp.width = Math.round(mIconPosition.width()); + lp.height = Math.round(mIconPosition.height()); + lp.leftMargin = Math.round(mIconPosition.left); + lp.topMargin = Math.round(mIconPosition.top); + } + } + if (iconChanged && !mIconBounds.isEmpty()) { + // Record the icon display + setCurrentIconVisible(true); + Canvas c = mPicture.beginRecording(mIconBounds.width(), mIconBounds.height()); + c.translate(-mIconBounds.left, -mIconBounds.top); + mIcon.draw(c); + mPicture.endRecording(); + setCurrentIconVisible(false); + drawOnSurface(); + } + } + + private void sendIconInfo() { + if (mContract != null && !mIconPosition.isEmpty()) { + mContract.sendEndPosition(mIconPosition, mSurfaceView.getSurfaceControl()); + } + } + + @Override + public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) { + drawOnSurface(); + sendIconInfo(); + } + + @Override + public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, + int format, int width, int height) { + drawOnSurface(); + } + + @Override + public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {} + + @Override + public void surfaceRedrawNeeded(@NonNull SurfaceHolder surfaceHolder) { + drawOnSurface(); + } + + private void drawOnSurface() { + SurfaceHolder surfaceHolder = mSurfaceView.getHolder(); + + Canvas c = surfaceHolder.lockHardwareCanvas(); + if (c != null) { + mPicture.draw(c); + surfaceHolder.unlockCanvasAndPost(c); + } + } + + private void setCurrentIconVisible(boolean isVisible) { + if (mIcon != null) { + setIconAndDotVisible(mIcon, isVisible); + } + } +} From 422015cb9f5f5505c9450c1716fa95d5c16f21d8 Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Thu, 16 Jul 2020 11:58:00 -0700 Subject: [PATCH 16/51] Minimal Phone Mode (part-1) Include feature flag for minimal phone mode Bug: 161462256 Test: manual Change-Id: I4ddbe7fd2fd73b4cfaa27ab18c210f38133dd3c2 --- src/com/android/launcher3/config/FeatureFlags.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 5c4a4922fd..45116b6b27 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -177,6 +177,10 @@ public final class FeatureFlags { public static final BooleanFlag USER_EVENT_DISPATCHER = new DeviceFlag( "USER_EVENT_DISPATCHER", true, "User event dispatcher collects logs."); + public static final BooleanFlag ENABLE_MINIMAL_DEVICE = new DeviceFlag( + "ENABLE_MINIMAL_DEVICE", false, + "Allow user to toggle minimal device mode in launcher."); + public static void initialize(Context context) { synchronized (sDebugFlags) { for (DebugFlag flag : sDebugFlags) { From 3344b8ce3da451ff624ce6b991b049c4ed331e1b Mon Sep 17 00:00:00 2001 From: thiruram Date: Wed, 15 Jul 2020 10:28:12 -0700 Subject: [PATCH 17/51] Fixes missing field mappings from launcher_atom.ItemInfo to Statslog. Bug: 161284668 Change-Id: I70b247e896bfcad5f6dbb6ce3ec5ed7aa57b8a61 --- .../logging/StatsLogCompatManager.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index eac45e9907..ba60185c79 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -33,6 +33,7 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.Utilities; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logger.LauncherAtom.ContainerInfo; +import com.android.launcher3.logger.LauncherAtom.FolderContainer.ParentContainerCase; import com.android.launcher3.logger.LauncherAtom.FolderIcon; import com.android.launcher3.logger.LauncherAtom.FromState; import com.android.launcher3.logger.LauncherAtom.ToState; @@ -59,9 +60,11 @@ import java.util.OptionalInt; * This class calls StatsLog compile time generated methods. * * To see if the logs are properly sent to statsd, execute following command. + *
    * $ wwdebug (to turn on the logcat printout) * $ wwlogcat (see logcat with grep filter on) * $ statsd_testdrive (see how ww is writing the proto to statsd buffer) + *
*/ public class StatsLogCompatManager extends StatsLogManager { @@ -109,7 +112,9 @@ public class StatsLogCompatManager extends StatsLogManager { } private class SnapshotWorker extends BaseModelUpdateTask { + private final InstanceId mInstanceId; + SnapshotWorker() { mInstanceId = new InstanceIdSequence( 1 << 20 /*InstanceId.INSTANCE_ID_MAX*/).newInstanceId(); @@ -132,7 +137,8 @@ public class StatsLogCompatManager extends StatsLogManager { LauncherAtom.ItemInfo atomInfo = info.buildProto(fInfo); writeSnapshot(atomInfo, mInstanceId); } - } catch (Exception e) { } + } catch (Exception e) { + } } for (ItemInfo info : appWidgets) { LauncherAtom.ItemInfo atomInfo = info.buildProto(null); @@ -337,7 +343,7 @@ public class StatsLogCompatManager extends StatsLogManager { } private static int getCardinality(LauncherAtom.ItemInfo info) { - switch (info.getContainerInfo().getContainerCase()){ + switch (info.getContainerInfo().getContainerCase()) { case PREDICTED_HOTSEAT_CONTAINER: return info.getContainerInfo().getPredictedHotseatContainer().getCardinality(); case SEARCH_RESULT_CONTAINER: @@ -402,9 +408,16 @@ public class StatsLogCompatManager extends StatsLogManager { } private static int getPageId(LauncherAtom.ItemInfo info) { + if (info.hasTask()) { + return info.getTask().getIndex(); + } switch (info.getContainerInfo().getContainerCase()) { case FOLDER: return info.getContainerInfo().getFolder().getPageIndex(); + case HOTSEAT: + return info.getContainerInfo().getHotseat().getIndex(); + case PREDICTED_HOTSEAT_CONTAINER: + return info.getContainerInfo().getPredictedHotseatContainer().getIndex(); default: return info.getContainerInfo().getWorkspace().getPageIndex(); } @@ -413,6 +426,10 @@ public class StatsLogCompatManager extends StatsLogManager { private static int getParentPageId(LauncherAtom.ItemInfo info) { switch (info.getContainerInfo().getContainerCase()) { case FOLDER: + if (info.getContainerInfo().getFolder().getParentContainerCase() + == ParentContainerCase.HOTSEAT) { + return info.getContainerInfo().getFolder().getHotseat().getIndex(); + } return info.getContainerInfo().getFolder().getWorkspace().getPageIndex(); case SEARCH_RESULT_CONTAINER: return info.getContainerInfo().getSearchResultContainer().getWorkspace() From a4661192ff978ad2dbcb4923fcc86c5e245f5eef Mon Sep 17 00:00:00 2001 From: thiruram Date: Tue, 21 Jul 2020 23:17:32 -0700 Subject: [PATCH 18/51] Limit launcher snapshot logging once per day. This change will make sure launcher snapshot is logged only once in 24hrs interval using sharedpreference. Bug: 161375303 Change-Id: Iab6b25d931b2e91ae5647e266bd68ead86c99bc6 Merged-In: Iab6b25d931b2e91ae5647e266bd68ead86c99bc6 (cherry picked from commit efa41c1c522c039eefd85b1f3ae1c411010a8cf5) --- .../logging/StatsLogCompatManager.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index ba60185c79..a89319eacf 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -16,6 +16,10 @@ package com.android.quickstep.logging; +import static android.text.format.DateUtils.DAY_IN_MILLIS; +import static android.text.format.DateUtils.formatElapsedTime; + +import static com.android.launcher3.Utilities.getDevicePrefs; import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.FOLDER; import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.SEARCH_RESULT_CONTAINER; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WORKSPACE_SNAPSHOT; @@ -24,6 +28,8 @@ import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGE import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__HOME; import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGED__DST_STATE__OVERVIEW; +import static java.lang.System.currentTimeMillis; + import android.content.Context; import android.util.Log; @@ -71,8 +77,7 @@ public class StatsLogCompatManager extends StatsLogManager { private static final String TAG = "StatsLog"; private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG); - private static Context sContext; - + private static final String LAST_SNAPSHOT_TIME_MILLIS = "LAST_SNAPSHOT_TIME_MILLIS"; private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0); // LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates // from nano to lite, bake constant to prevent robo test failure. @@ -80,8 +85,10 @@ public class StatsLogCompatManager extends StatsLogManager { private static final int FOLDER_HIERARCHY_OFFSET = 100; private static final int SEARCH_RESULT_HIERARCHY_OFFSET = 200; + private final Context mContext; + public StatsLogCompatManager(Context context) { - sContext = context; + mContext = context; } @Override @@ -107,7 +114,7 @@ public class StatsLogCompatManager extends StatsLogManager { */ @Override public void logSnapshot() { - LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask( + LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask( new SnapshotWorker()); } @@ -122,6 +129,20 @@ public class StatsLogCompatManager extends StatsLogManager { @Override public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { + long lastSnapshotTimeMillis = getDevicePrefs(mContext) + .getLong(LAST_SNAPSHOT_TIME_MILLIS, 0); + // Log snapshot only if previous snapshot was older than a day + if (currentTimeMillis() - lastSnapshotTimeMillis < DAY_IN_MILLIS) { + if (IS_VERBOSE) { + String elapsedTime = formatElapsedTime( + (currentTimeMillis() - lastSnapshotTimeMillis) / 1000); + Log.d(TAG, String.format( + "Skipped snapshot logging since previous snapshot was %s old.", + elapsedTime)); + } + return; + } + IntSparseArrayMap folders = dataModel.folders.clone(); ArrayList workspaceItems = (ArrayList) dataModel.workspaceItems.clone(); ArrayList appWidgets = (ArrayList) dataModel.appWidgets.clone(); @@ -144,10 +165,12 @@ public class StatsLogCompatManager extends StatsLogManager { LauncherAtom.ItemInfo atomInfo = info.buildProto(null); writeSnapshot(atomInfo, mInstanceId); } + getDevicePrefs(mContext).edit() + .putLong(LAST_SNAPSHOT_TIME_MILLIS, currentTimeMillis()).apply(); } } - private static void writeSnapshot(LauncherAtom.ItemInfo info, InstanceId instanceId) { + private void writeSnapshot(LauncherAtom.ItemInfo info, InstanceId instanceId) { if (IS_VERBOSE) { Log.d(TAG, String.format("\nwriteSnapshot(%d):\n%s", instanceId.getId(), info)); } @@ -266,7 +289,7 @@ public class StatsLogCompatManager extends StatsLogManager { } else { // Item is inside the folder, fetch folder info in a BG thread // and then write to StatsLog. - LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask( + LauncherAppState.getInstanceNoCreate().getModel().enqueueModelUpdateTask( new BaseModelUpdateTask() { @Override public void execute(LauncherAppState app, BgDataModel dataModel, From 3c3116826b087e6258e62f3dabbc7c5dc9eadaed Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 20 Jul 2020 13:23:08 -0700 Subject: [PATCH 19/51] Pass through touches in FolderIcon padding area Pass touch events happening in padding of folder icon to workspace. BubbleTextView already does this. Bug: 161014416 Test: Manual Change-Id: Ibfa24adb2d84efbfab36f02a2240837f03858e43 --- src/com/android/launcher3/folder/FolderIcon.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 75275b20e5..32d061cb42 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -129,6 +129,8 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel private float mDotScale; private Animator mDotScaleAnim; + private Rect mTouchArea = new Rect(); + private final PointF mTranslationForReorderBounce = new PointF(0, 0); private final PointF mTranslationForReorderPreview = new PointF(0, 0); private float mScaleForReorderBounce = 1f; @@ -711,6 +713,11 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel @Override public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN + && shouldIgnoreTouchDown(event.getX(), event.getY())) { + return false; + } + // Call the superclass onTouchEvent first, because sometimes it changes the state to // isPressed() on an ACTION_UP super.onTouchEvent(event); @@ -719,6 +726,15 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel return true; } + /** + * Returns true if the touch down at the provided position be ignored + */ + protected boolean shouldIgnoreTouchDown(float x, float y) { + mTouchArea.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), + getHeight() - getPaddingBottom()); + return !mTouchArea.contains((int) x, (int) y); + } + @Override public void cancelLongPress() { super.cancelLongPress(); From ccf92c65871ac50c883df93791956486181a778c Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 16 Jul 2020 16:08:12 -0700 Subject: [PATCH 20/51] Use TouchDelegate to listen for icon view taps on RecentsView Using a negative margin to move the icon view to stick out above the task prevents that part sticking out from receiving touches. They go directly through to RecentsView, which interprets it as a touch to home. Now we use a touch delegate that recents view passes touches to before processing it directly. Note we can't override should steal touches from children in LauncherRecentsView because the icon view isn't actually seen as a child of RecentsView if it's outside of the task view area. Fixes: 159820339 Test: Touching anywhere on the icon works. Scrolled to previous/next tasks and in different rotations and verified tap registers correctly. Change-Id: I4559c34b20079e06aac401e2c93ac36a74b653ea --- .../android/quickstep/views/RecentsView.java | 11 +++++ .../com/android/quickstep/views/TaskView.java | 44 ++++++++++++++++--- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 027a737cef..ac9049f869 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -78,6 +78,7 @@ import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.TouchDelegate; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; @@ -648,6 +649,16 @@ public abstract class RecentsView extends PagedView @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); + + TaskView taskView = getCurrentPageTaskView(); + if (taskView != null) { + TouchDelegate mChildTouchDelegate = taskView.getIconTouchDelegate(ev); + if (mChildTouchDelegate != null && mChildTouchDelegate.onTouchEvent(ev)) { + // Keep consuming events to pass to delegate + return true; + } + } + final int x = (int) ev.getX(); final int y = (int) ev.getY(); switch (ev.getAction()) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 222f6e6728..2058a7f375 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -22,16 +22,19 @@ import static android.view.Gravity.CENTER_VERTICAL; import static android.view.Gravity.END; import static android.view.Gravity.START; import static android.view.Gravity.TOP; +import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; +import static android.view.Surface.ROTATION_90; import static android.widget.Toast.LENGTH_SHORT; import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.Utilities.comp; +import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent - .LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import android.animation.Animator; @@ -53,7 +56,9 @@ import android.os.Handler; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; +import android.view.MotionEvent; import android.view.Surface; +import android.view.TouchDelegate; import android.view.View; import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityNodeInfo; @@ -78,6 +83,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.TransformingTouchDelegate; import com.android.launcher3.util.ViewPool.Reusable; import com.android.quickstep.RecentsModel; import com.android.quickstep.TaskIconCache; @@ -122,6 +128,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { public static final long SCALE_ICON_DURATION = 120; private static final long DIM_ANIM_DURATION = 700; + /** + * This technically can be a vanilla {@link TouchDelegate} class, however that class requires + * setting the touch bounds at construction, so we'd repeatedly be created many instances + * unnecessarily as scrolling occurs, whereas {@link TransformingTouchDelegate} allows touch + * delegated bounds only to be updated. + */ + private TransformingTouchDelegate mIconTouchDelegate; private static final List SYSTEM_GESTURE_EXCLUSION_RECT = Collections.singletonList(new Rect()); @@ -186,6 +199,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private int mStackHeight; private View mContextualChipWrapper; private View mContextualChip; + private final float[] mIconCenterCoords = new float[2]; public TaskView(Context context) { this(context, null); @@ -246,6 +260,26 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { super.onFinishInflate(); mSnapshotView = findViewById(R.id.snapshot); mIconView = findViewById(R.id.icon); + mIconTouchDelegate = new TransformingTouchDelegate(mIconView); + } + + public TouchDelegate getIconTouchDelegate(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + computeAndSetIconTouchDelegate(); + } + return mIconTouchDelegate; + } + + private void computeAndSetIconTouchDelegate() { + float iconHalfSize = mIconView.getWidth() / 2f; + mIconCenterCoords[0] = mIconCenterCoords[1] = iconHalfSize; + getDescendantCoordRelativeToAncestor(mIconView, mActivity.getDragLayer(), mIconCenterCoords, + false); + mIconTouchDelegate.setBounds( + (int) (mIconCenterCoords[0] - iconHalfSize), + (int) (mIconCenterCoords[1] - iconHalfSize), + (int) (mIconCenterCoords[0] + iconHalfSize), + (int) (mIconCenterCoords[1] + iconHalfSize)); } /** @@ -468,18 +502,18 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin); LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams(); switch (orientationHandler.getRotation()) { - case Surface.ROTATION_90: + case ROTATION_90: iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL; iconParams.rightMargin = -thumbnailPadding; iconParams.leftMargin = 0; iconParams.topMargin = snapshotParams.topMargin / 2; break; - case Surface.ROTATION_180: + case ROTATION_180: iconParams.gravity = BOTTOM | CENTER_HORIZONTAL; iconParams.bottomMargin = -thumbnailPadding; iconParams.leftMargin = iconParams.topMargin = iconParams.rightMargin = 0; break; - case Surface.ROTATION_270: + case ROTATION_270: iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL; iconParams.leftMargin = -thumbnailPadding; iconParams.rightMargin = 0; From 0ad7b172e67294d76e4fc8785336badb9d0a8344 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 20 Jul 2020 16:46:47 -0700 Subject: [PATCH 21/51] Handle uiMode changes - Launcher already dedupes if there are no theme changes Bug: 148988542 Test: adb shell cmd uimode car yes/no, adb shell cmd uimode night yes/no Change-Id: Ia83f02d18a0433c8be59d1f488e58b38476ba5ff Merged-In: Ia83f02d18a0433c8be59d1f488e58b38476ba5ff --- AndroidManifest.xml | 2 +- quickstep/AndroidManifest-launcher.xml | 2 +- quickstep/AndroidManifest.xml | 2 +- tests/AndroidManifest-common.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index b031ffbee4..bc0cd97685 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -49,7 +49,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml index 60afddb0a8..d680507e3b 100644 --- a/quickstep/AndroidManifest-launcher.xml +++ b/quickstep/AndroidManifest-launcher.xml @@ -49,7 +49,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index e49f2ecdc0..bb83b761e7 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -60,7 +60,7 @@ android:stateNotNeeded="true" android:theme="@style/LauncherTheme" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" /> diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml index 1c8f095810..33c8fbd96e 100644 --- a/tests/AndroidManifest-common.xml +++ b/tests/AndroidManifest-common.xml @@ -92,7 +92,7 @@ Date: Fri, 24 Jul 2020 16:44:03 -0700 Subject: [PATCH 22/51] Fixing touches getting ignored just after swipe-up Moving the input proxy logic outside the recents controller, so that it is not lied to the controller lifecycle. > Fixing input consumer not getting registered if recentsController was not received until ACTION_UP > Fixing input events being ignored after finishing recentsAnimation, but before handler is invalidated Bug: 161750900 Change-Id: Ib06617caef77f18a71c5a231e781291c3a4ee57e --- .../android/quickstep/BaseSwipeUpHandler.java | 6 +- .../quickstep/BaseSwipeUpHandlerV2.java | 7 +- .../quickstep/util/InputConsumerProxy.java | 118 ++++++++++++++++++ .../quickstep/RecentsAnimationController.java | 103 +-------------- 4 files changed, 127 insertions(+), 107 deletions(-) create mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index b49299d2fe..cbef67b84b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -43,6 +43,7 @@ import com.android.launcher3.util.WindowBounds; import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActivityInitListener; +import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.TransformParams; @@ -65,7 +66,7 @@ public abstract class BaseSwipeUpHandler, Q extend private static final String TAG = "BaseSwipeUpHandler"; protected final BaseActivityInterface mActivityInterface; - protected final InputConsumerController mInputConsumer; + protected final InputConsumerProxy mInputConsumerProxy; protected final ActivityInitListener mActivityInitListener; @@ -91,7 +92,8 @@ public abstract class BaseSwipeUpHandler, Q extend super(context, deviceState, gestureState, new TransformParams()); mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); - mInputConsumer = inputConsumer; + mInputConsumerProxy = + new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler); } /** diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 80c145a959..a8a49b0378 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -851,11 +851,9 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } } - if (endTarget.isLauncher && mRecentsAnimationController != null) { - mRecentsAnimationController.enableInputProxy(mInputConsumer, - this::createNewInputProxyHandler); + if (endTarget.isLauncher) { + mInputConsumerProxy.enable(); } - if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); @@ -1183,6 +1181,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } private void invalidateHandler() { + mInputConsumerProxy.destroy(); endRunningWindowAnim(false /* cancel */); if (mGestureEndCallback != null) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java new file mode 100644 index 0000000000..3e87f48f02 --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import static android.view.MotionEvent.ACTION_CANCEL; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_UP; + +import android.util.Log; +import android.view.InputEvent; +import android.view.KeyEvent; +import android.view.MotionEvent; + +import com.android.quickstep.InputConsumer; +import com.android.systemui.shared.system.InputConsumerController; + +import java.util.function.Supplier; + +/** + * Utility class which manages proxying input events from {@link InputConsumerController} + * to an {@link InputConsumer} + */ +public class InputConsumerProxy { + + private static final String TAG = "InputConsumerProxy"; + + private final InputConsumerController mInputConsumerController; + private final Supplier mConsumerSupplier; + + // The consumer is created lazily on demand. + private InputConsumer mInputConsumer; + + private boolean mDestroyed = false; + private boolean mTouchInProgress = false; + private boolean mDestroyPending = false; + + public InputConsumerProxy(InputConsumerController inputConsumerController, + Supplier consumerSupplier) { + mInputConsumerController = inputConsumerController; + mConsumerSupplier = consumerSupplier; + } + + public void enable() { + if (mDestroyed) { + return; + } + mInputConsumerController.setInputListener(this::onInputConsumerEvent); + } + + private boolean onInputConsumerEvent(InputEvent ev) { + if (ev instanceof MotionEvent) { + onInputConsumerMotionEvent((MotionEvent) ev); + } else if (ev instanceof KeyEvent) { + if (mInputConsumer == null) { + mInputConsumer = mConsumerSupplier.get(); + } + mInputConsumer.onKeyEvent((KeyEvent) ev); + return true; + } + return false; + } + + private boolean onInputConsumerMotionEvent(MotionEvent ev) { + int action = ev.getAction(); + + // Just to be safe, verify that ACTION_DOWN comes before any other action, + // and ignore any ACTION_DOWN after the first one (though that should not happen). + if (!mTouchInProgress && action != ACTION_DOWN) { + Log.w(TAG, "Received non-down motion before down motion: " + action); + return false; + } + if (mTouchInProgress && action == ACTION_DOWN) { + Log.w(TAG, "Received down motion while touch was already in progress"); + return false; + } + + if (action == ACTION_DOWN) { + mTouchInProgress = true; + if (mInputConsumer == null) { + mInputConsumer = mConsumerSupplier.get(); + } + } else if (action == ACTION_CANCEL || action == ACTION_UP) { + // Finish any pending actions + mTouchInProgress = false; + if (mDestroyPending) { + destroy(); + } + } + if (mInputConsumer != null) { + mInputConsumer.onMotionEvent(ev); + } + + return true; + } + + public void destroy() { + if (mTouchInProgress) { + mDestroyPending = true; + return; + } + mDestroyPending = false; + mDestroyed = true; + mInputConsumerController.setInputListener(null); + } +} diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index 4e9aa6135e..51f5e5d785 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -15,49 +15,30 @@ */ package com.android.quickstep; -import static android.view.MotionEvent.ACTION_CANCEL; -import static android.view.MotionEvent.ACTION_DOWN; -import static android.view.MotionEvent.ACTION_UP; - import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; -import android.os.SystemClock; -import android.util.Log; -import android.view.InputEvent; -import android.view.KeyEvent; -import android.view.MotionEvent; - import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.android.launcher3.util.Preconditions; import com.android.systemui.shared.recents.model.ThumbnailData; -import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.util.function.Consumer; -import java.util.function.Supplier; /** * Wrapper around RecentsAnimationControllerCompat to help with some synchronization */ public class RecentsAnimationController { - private static final String TAG = "RecentsAnimationController"; - private final RecentsAnimationControllerCompat mController; private final Consumer mOnFinishedListener; private final boolean mAllowMinimizeSplitScreen; - private InputConsumerController mInputConsumerController; - private Supplier mInputProxySupplier; - private InputConsumer mInputConsumer; private boolean mUseLauncherSysBarFlags = false; private boolean mSplitScreenMinimized = false; - private boolean mTouchInProgress; - private boolean mDisableInputProxyPending; public RecentsAnimationController(RecentsAnimationControllerCompat controller, boolean allowMinimizeSplitScreen, @@ -136,12 +117,12 @@ public class RecentsAnimationController { @UiThread public void finishAnimationToHome() { - finishAndDisableInputProxy(true /* toRecents */, null, false /* sendUserLeaveHint */); + finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); } @UiThread public void finishAnimationToApp() { - finishAndDisableInputProxy(false /* toRecents */, null, false /* sendUserLeaveHint */); + finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); } /** See {@link #finish(boolean, Runnable, boolean)} */ @@ -160,18 +141,6 @@ public class RecentsAnimationController { @UiThread public void finish(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { Preconditions.assertUIThread(); - if (toRecents && mTouchInProgress) { - // Finish the controller as requested, but don't disable input proxy yet. - mDisableInputProxyPending = true; - finishController(toRecents, onFinishComplete, sendUserLeaveHint); - } else { - finishAndDisableInputProxy(toRecents, onFinishComplete, sendUserLeaveHint); - } - } - - private void finishAndDisableInputProxy(boolean toRecents, Runnable onFinishComplete, - boolean sendUserLeaveHint) { - disableInputProxy(); finishController(toRecents, onFinishComplete, sendUserLeaveHint); } @@ -179,7 +148,6 @@ public class RecentsAnimationController { public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { mOnFinishedListener.accept(this); UI_HELPER_EXECUTOR.execute(() -> { - mController.setInputConsumerEnabled(false); mController.finish(toRecents, sendUserLeaveHint); if (callback != null) { MAIN_EXECUTOR.execute(callback); @@ -197,75 +165,8 @@ public class RecentsAnimationController { }); } - public void enableInputProxy(InputConsumerController inputConsumerController, - Supplier inputProxySupplier) { - mInputProxySupplier = inputProxySupplier; - mInputConsumerController = inputConsumerController; - mInputConsumerController.setInputListener(this::onInputConsumerEvent); - } - /** @return wrapper controller. */ public RecentsAnimationControllerCompat getController() { return mController; } - - private void disableInputProxy() { - if (mInputConsumer != null && mTouchInProgress) { - long now = SystemClock.uptimeMillis(); - MotionEvent dummyCancel = MotionEvent.obtain(now, now, ACTION_CANCEL, 0, 0, 0); - mInputConsumer.onMotionEvent(dummyCancel); - dummyCancel.recycle(); - } - if (mInputConsumerController != null) { - mInputConsumerController.setInputListener(null); - } - mInputProxySupplier = null; - } - - private boolean onInputConsumerEvent(InputEvent ev) { - if (ev instanceof MotionEvent) { - onInputConsumerMotionEvent((MotionEvent) ev); - } else if (ev instanceof KeyEvent) { - if (mInputConsumer == null) { - mInputConsumer = mInputProxySupplier.get(); - } - mInputConsumer.onKeyEvent((KeyEvent) ev); - return true; - } - return false; - } - - private boolean onInputConsumerMotionEvent(MotionEvent ev) { - int action = ev.getAction(); - - // Just to be safe, verify that ACTION_DOWN comes before any other action, - // and ignore any ACTION_DOWN after the first one (though that should not happen). - if (!mTouchInProgress && action != ACTION_DOWN) { - Log.w(TAG, "Received non-down motion before down motion: " + action); - return false; - } - if (mTouchInProgress && action == ACTION_DOWN) { - Log.w(TAG, "Received down motion while touch was already in progress"); - return false; - } - - if (action == ACTION_DOWN) { - mTouchInProgress = true; - if (mInputConsumer == null) { - mInputConsumer = mInputProxySupplier.get(); - } - } else if (action == ACTION_CANCEL || action == ACTION_UP) { - // Finish any pending actions - mTouchInProgress = false; - if (mDisableInputProxyPending) { - mDisableInputProxyPending = false; - disableInputProxy(); - } - } - if (mInputConsumer != null) { - mInputConsumer.onMotionEvent(ev); - } - - return true; - } } From 17f379bf4b9a9e080288c9601f099185cf2899fb Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Fri, 24 Jul 2020 16:48:54 -0700 Subject: [PATCH 23/51] Adds haptics to Overview gesture in Sandbox. Change-Id: I4b8ec88bfc051de287b1b8ac27c4b5ab9ac90bbf --- .../interaction/NavBarGestureHandler.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java index 0e2312bddf..81c4d0c7c8 100644 --- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java +++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java @@ -16,6 +16,7 @@ package com.android.quickstep.interaction; import static com.android.launcher3.Utilities.squaredHypot; +import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC; import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_COMPLETED; import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_BAD_ANGLE; import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT; @@ -48,6 +49,7 @@ import com.android.launcher3.ResourceUtils; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.util.VibratorWrapper; import com.android.quickstep.SysUINavigationMode.Mode; +import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.NavBarPosition; import com.android.quickstep.util.TriggerSwipeUpTouchTracker; import com.android.systemui.shared.system.QuickStepContract; @@ -74,6 +76,7 @@ public class NavBarGestureHandler implements OnTouchListener, private final PointF mAssistantStartDragPos = new PointF(); private final PointF mDownPos = new PointF(); private final PointF mLastPos = new PointF(); + private final MotionPauseDetector mMotionPauseDetector; private boolean mTouchCameFromAssistantCorner; private boolean mTouchCameFromNavBar; private boolean mPassedAssistantSlop; @@ -100,6 +103,7 @@ public class NavBarGestureHandler implements OnTouchListener, new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/, new NavBarPosition(Mode.NO_BUTTON, displayRotation), null /*onInterceptTouch*/, this); + mMotionPauseDetector = new MotionPauseDetector(context); final Resources resources = context.getResources(); mBottomGestureHeight = @@ -177,12 +181,14 @@ public class NavBarGestureHandler implements OnTouchListener, } mLaunchedAssistant = false; mSwipeUpTouchTracker.init(); + mMotionPauseDetector.clear(); + mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged); break; case MotionEvent.ACTION_MOVE: + mLastPos.set(event.getX(), event.getY()); if (!mAssistantGestureActive) { break; } - mLastPos.set(event.getX(), event.getY()); if (!mPassedAssistantSlop) { // Normal gesture, ensure we pass the slop before we start tracking the gesture @@ -213,6 +219,8 @@ public class NavBarGestureHandler implements OnTouchListener, break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + mMotionPauseDetector.clear(); + mMotionPauseDetector.setOnMotionPauseListener(null); if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) { mGestureCallback.onNavBarGestureAttempted( HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, new PointF()); @@ -239,9 +247,17 @@ public class NavBarGestureHandler implements OnTouchListener, } mSwipeUpTouchTracker.onMotionEvent(event); mAssistantGestureDetector.onTouchEvent(event); + mMotionPauseDetector.addPosition(event); + mMotionPauseDetector.setDisallowPause(mLastPos.y >= mDisplaySize.y - mBottomGestureHeight); return intercepted; } + protected void onMotionPauseChanged(boolean isPaused) { + if (isPaused) { + VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC); + } + } + /** * Determine if angle is larger than threshold for assistant detection */ From 1a286a189ed24ae81d6985f57b395076cc5efa0c Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 24 Jul 2020 16:44:03 -0700 Subject: [PATCH 24/51] Fixing touches getting ignored just after swipe-up Moving the input proxy logic outside the recents controller, so that it is not lied to the controller lifecycle. > Fixing input consumer not getting registered if recentsController was not received until ACTION_UP > Fixing input events being ignored after finishing recentsAnimation, but before handler is invalidated Bug: 161750900 Change-Id: Ib06617caef77f18a71c5a231e781291c3a4ee57e (cherry picked from commit ff4b142789e8fa66d1b64a78e99c924d9c484867) --- .../android/quickstep/BaseSwipeUpHandler.java | 6 +- .../quickstep/BaseSwipeUpHandlerV2.java | 7 +- .../quickstep/util/InputConsumerProxy.java | 118 ++++++++++++++++++ .../quickstep/RecentsAnimationController.java | 103 +-------------- 4 files changed, 127 insertions(+), 107 deletions(-) create mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index a63f3a802f..aba5ab63e1 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -39,6 +39,7 @@ import com.android.launcher3.util.WindowBounds; import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActivityInitListener; +import com.android.quickstep.util.InputConsumerProxy; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.SurfaceTransactionApplier; import com.android.quickstep.util.TransformParams; @@ -61,7 +62,7 @@ public abstract class BaseSwipeUpHandler, Q extend private static final String TAG = "BaseSwipeUpHandler"; protected final BaseActivityInterface mActivityInterface; - protected final InputConsumerController mInputConsumer; + protected final InputConsumerProxy mInputConsumerProxy; protected final ActivityInitListener mActivityInitListener; @@ -87,7 +88,8 @@ public abstract class BaseSwipeUpHandler, Q extend super(context, deviceState, gestureState, new TransformParams()); mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); - mInputConsumer = inputConsumer; + mInputConsumerProxy = + new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler); } /** diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 6c4c5d3f4d..f0f3d0f1e3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -850,11 +850,9 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } } - if (endTarget.isLauncher && mRecentsAnimationController != null) { - mRecentsAnimationController.enableInputProxy(mInputConsumer, - this::createNewInputProxyHandler); + if (endTarget.isLauncher) { + mInputConsumerProxy.enable(); } - if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); @@ -1181,6 +1179,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } private void invalidateHandler() { + mInputConsumerProxy.destroy(); endRunningWindowAnim(false /* cancel */); if (mGestureEndCallback != null) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java new file mode 100644 index 0000000000..3e87f48f02 --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import static android.view.MotionEvent.ACTION_CANCEL; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_UP; + +import android.util.Log; +import android.view.InputEvent; +import android.view.KeyEvent; +import android.view.MotionEvent; + +import com.android.quickstep.InputConsumer; +import com.android.systemui.shared.system.InputConsumerController; + +import java.util.function.Supplier; + +/** + * Utility class which manages proxying input events from {@link InputConsumerController} + * to an {@link InputConsumer} + */ +public class InputConsumerProxy { + + private static final String TAG = "InputConsumerProxy"; + + private final InputConsumerController mInputConsumerController; + private final Supplier mConsumerSupplier; + + // The consumer is created lazily on demand. + private InputConsumer mInputConsumer; + + private boolean mDestroyed = false; + private boolean mTouchInProgress = false; + private boolean mDestroyPending = false; + + public InputConsumerProxy(InputConsumerController inputConsumerController, + Supplier consumerSupplier) { + mInputConsumerController = inputConsumerController; + mConsumerSupplier = consumerSupplier; + } + + public void enable() { + if (mDestroyed) { + return; + } + mInputConsumerController.setInputListener(this::onInputConsumerEvent); + } + + private boolean onInputConsumerEvent(InputEvent ev) { + if (ev instanceof MotionEvent) { + onInputConsumerMotionEvent((MotionEvent) ev); + } else if (ev instanceof KeyEvent) { + if (mInputConsumer == null) { + mInputConsumer = mConsumerSupplier.get(); + } + mInputConsumer.onKeyEvent((KeyEvent) ev); + return true; + } + return false; + } + + private boolean onInputConsumerMotionEvent(MotionEvent ev) { + int action = ev.getAction(); + + // Just to be safe, verify that ACTION_DOWN comes before any other action, + // and ignore any ACTION_DOWN after the first one (though that should not happen). + if (!mTouchInProgress && action != ACTION_DOWN) { + Log.w(TAG, "Received non-down motion before down motion: " + action); + return false; + } + if (mTouchInProgress && action == ACTION_DOWN) { + Log.w(TAG, "Received down motion while touch was already in progress"); + return false; + } + + if (action == ACTION_DOWN) { + mTouchInProgress = true; + if (mInputConsumer == null) { + mInputConsumer = mConsumerSupplier.get(); + } + } else if (action == ACTION_CANCEL || action == ACTION_UP) { + // Finish any pending actions + mTouchInProgress = false; + if (mDestroyPending) { + destroy(); + } + } + if (mInputConsumer != null) { + mInputConsumer.onMotionEvent(ev); + } + + return true; + } + + public void destroy() { + if (mTouchInProgress) { + mDestroyPending = true; + return; + } + mDestroyPending = false; + mDestroyed = true; + mInputConsumerController.setInputListener(null); + } +} diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index 4e9aa6135e..51f5e5d785 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -15,49 +15,30 @@ */ package com.android.quickstep; -import static android.view.MotionEvent.ACTION_CANCEL; -import static android.view.MotionEvent.ACTION_DOWN; -import static android.view.MotionEvent.ACTION_UP; - import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; -import android.os.SystemClock; -import android.util.Log; -import android.view.InputEvent; -import android.view.KeyEvent; -import android.view.MotionEvent; - import androidx.annotation.NonNull; import androidx.annotation.UiThread; import com.android.launcher3.util.Preconditions; import com.android.systemui.shared.recents.model.ThumbnailData; -import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.util.function.Consumer; -import java.util.function.Supplier; /** * Wrapper around RecentsAnimationControllerCompat to help with some synchronization */ public class RecentsAnimationController { - private static final String TAG = "RecentsAnimationController"; - private final RecentsAnimationControllerCompat mController; private final Consumer mOnFinishedListener; private final boolean mAllowMinimizeSplitScreen; - private InputConsumerController mInputConsumerController; - private Supplier mInputProxySupplier; - private InputConsumer mInputConsumer; private boolean mUseLauncherSysBarFlags = false; private boolean mSplitScreenMinimized = false; - private boolean mTouchInProgress; - private boolean mDisableInputProxyPending; public RecentsAnimationController(RecentsAnimationControllerCompat controller, boolean allowMinimizeSplitScreen, @@ -136,12 +117,12 @@ public class RecentsAnimationController { @UiThread public void finishAnimationToHome() { - finishAndDisableInputProxy(true /* toRecents */, null, false /* sendUserLeaveHint */); + finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); } @UiThread public void finishAnimationToApp() { - finishAndDisableInputProxy(false /* toRecents */, null, false /* sendUserLeaveHint */); + finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); } /** See {@link #finish(boolean, Runnable, boolean)} */ @@ -160,18 +141,6 @@ public class RecentsAnimationController { @UiThread public void finish(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { Preconditions.assertUIThread(); - if (toRecents && mTouchInProgress) { - // Finish the controller as requested, but don't disable input proxy yet. - mDisableInputProxyPending = true; - finishController(toRecents, onFinishComplete, sendUserLeaveHint); - } else { - finishAndDisableInputProxy(toRecents, onFinishComplete, sendUserLeaveHint); - } - } - - private void finishAndDisableInputProxy(boolean toRecents, Runnable onFinishComplete, - boolean sendUserLeaveHint) { - disableInputProxy(); finishController(toRecents, onFinishComplete, sendUserLeaveHint); } @@ -179,7 +148,6 @@ public class RecentsAnimationController { public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { mOnFinishedListener.accept(this); UI_HELPER_EXECUTOR.execute(() -> { - mController.setInputConsumerEnabled(false); mController.finish(toRecents, sendUserLeaveHint); if (callback != null) { MAIN_EXECUTOR.execute(callback); @@ -197,75 +165,8 @@ public class RecentsAnimationController { }); } - public void enableInputProxy(InputConsumerController inputConsumerController, - Supplier inputProxySupplier) { - mInputProxySupplier = inputProxySupplier; - mInputConsumerController = inputConsumerController; - mInputConsumerController.setInputListener(this::onInputConsumerEvent); - } - /** @return wrapper controller. */ public RecentsAnimationControllerCompat getController() { return mController; } - - private void disableInputProxy() { - if (mInputConsumer != null && mTouchInProgress) { - long now = SystemClock.uptimeMillis(); - MotionEvent dummyCancel = MotionEvent.obtain(now, now, ACTION_CANCEL, 0, 0, 0); - mInputConsumer.onMotionEvent(dummyCancel); - dummyCancel.recycle(); - } - if (mInputConsumerController != null) { - mInputConsumerController.setInputListener(null); - } - mInputProxySupplier = null; - } - - private boolean onInputConsumerEvent(InputEvent ev) { - if (ev instanceof MotionEvent) { - onInputConsumerMotionEvent((MotionEvent) ev); - } else if (ev instanceof KeyEvent) { - if (mInputConsumer == null) { - mInputConsumer = mInputProxySupplier.get(); - } - mInputConsumer.onKeyEvent((KeyEvent) ev); - return true; - } - return false; - } - - private boolean onInputConsumerMotionEvent(MotionEvent ev) { - int action = ev.getAction(); - - // Just to be safe, verify that ACTION_DOWN comes before any other action, - // and ignore any ACTION_DOWN after the first one (though that should not happen). - if (!mTouchInProgress && action != ACTION_DOWN) { - Log.w(TAG, "Received non-down motion before down motion: " + action); - return false; - } - if (mTouchInProgress && action == ACTION_DOWN) { - Log.w(TAG, "Received down motion while touch was already in progress"); - return false; - } - - if (action == ACTION_DOWN) { - mTouchInProgress = true; - if (mInputConsumer == null) { - mInputConsumer = mInputProxySupplier.get(); - } - } else if (action == ACTION_CANCEL || action == ACTION_UP) { - // Finish any pending actions - mTouchInProgress = false; - if (mDisableInputProxyPending) { - mDisableInputProxyPending = false; - disableInputProxy(); - } - } - if (mInputConsumer != null) { - mInputConsumer.onMotionEvent(ev); - } - - return true; - } } From 00ad8ee720e6abb21eaee45294f8c0e2b4db6712 Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 17 Jul 2020 18:23:59 -0700 Subject: [PATCH 25/51] Introducing a new gesture scope Gesture may occur outside of Launcher and not trigger system gesture recognition by TIS. Change-Id: Ibbb0180d6ef3856ab652164e6f3c1c86488a4caa (cherry picked from commit a37ecee10454b3c74c87394bf58342bda541009d) --- .../android/launcher3/tapl/Background.java | 6 ++--- .../tapl/LauncherInstrumentation.java | 23 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index ce94a3e723..0c4e5a9461 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -85,7 +85,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer { final LauncherInstrumentation.GestureScope gestureScope = zeroButtonToOverviewGestureStartsInLauncher() ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE - : LauncherInstrumentation.GestureScope.OUTSIDE; + : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER; // b/156044202 mLauncher.log("Hierarchy before swiping up to overview:"); @@ -130,7 +130,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer { } mLauncher.swipeToState(startX, startY, endX, endY, 10, OVERVIEW_STATE_ORDINAL, - LauncherInstrumentation.GestureScope.OUTSIDE); + LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER); break; } @@ -194,7 +194,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer { mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState, launcherWasVisible && isZeroButton ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE - : LauncherInstrumentation.GestureScope.OUTSIDE); + : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER); break; } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 5cf5d0fa88..94c75b0bea 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -112,9 +112,10 @@ public final class LauncherInstrumentation { public enum NavigationModel {ZERO_BUTTON, TWO_BUTTON, THREE_BUTTON} - // Where the gesture happens: outside of Launcher, inside or from inside to outside. + // Where the gesture happens: outside of Launcher, inside or from inside to outside and + // whether the gesture recognition triggers pilfer. public enum GestureScope { - OUTSIDE, INSIDE, INSIDE_TO_OUTSIDE + OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE } ; @@ -693,7 +694,7 @@ public final class LauncherInstrumentation { ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL, launcherWasVisible ? GestureScope.INSIDE_TO_OUTSIDE - : GestureScope.OUTSIDE); + : GestureScope.OUTSIDE_WITH_PILFER); } } } else { @@ -1159,7 +1160,8 @@ public final class LauncherInstrumentation { final boolean notLauncher3 = !isLauncher3(); switch (action) { case MotionEvent.ACTION_DOWN: - if (gestureScope != GestureScope.OUTSIDE) { + if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER + && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER) { expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN); } if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) { @@ -1167,12 +1169,17 @@ public final class LauncherInstrumentation { } break; case MotionEvent.ACTION_UP: - if (notLauncher3 && gestureScope != GestureScope.INSIDE) { + if (notLauncher3 && gestureScope != GestureScope.INSIDE + && (gestureScope == GestureScope.OUTSIDE_WITH_PILFER + || gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) { expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS); } - if (gestureScope != GestureScope.OUTSIDE) { - expectEvent(TestProtocol.SEQUENCE_MAIN, gestureScope == GestureScope.INSIDE - ? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL); + if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER + && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER) { + expectEvent(TestProtocol.SEQUENCE_MAIN, + gestureScope == GestureScope.INSIDE + || gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER + ? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL); } if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) { expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS); From b6d0607d8b4530132870e63e0685389f4ec02f49 Mon Sep 17 00:00:00 2001 From: thiruram Date: Thu, 23 Jul 2020 16:13:54 -0700 Subject: [PATCH 26/51] Logs system navigation details part of launcher snapshot logging. Bug: 157997545 Change-Id: I18e908dc62bb790c3a77e1aacd0236a7d84e8ce5 Merged-In: I18e908dc62bb790c3a77e1aacd0236a7d84e8ce5 --- .../quickstep/SysUINavigationMode.java | 15 +++-- .../logging/StatsLogCompatManager.java | 19 +++--- .../launcher3/logging/StatsLogManager.java | 59 ++++++++++++++++--- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java index 05ce2a2b9b..f2675f2b41 100644 --- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java +++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java @@ -16,6 +16,9 @@ package com.android.quickstep; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_2_BUTTON; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_3_BUTTON; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON; import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter; import android.content.BroadcastReceiver; @@ -24,6 +27,7 @@ import android.content.Intent; import android.content.res.Resources; import android.util.Log; +import com.android.launcher3.logging.StatsLogManager.LauncherEvent; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.MainThreadInitializedObject; @@ -37,16 +41,18 @@ import java.util.List; public class SysUINavigationMode { public enum Mode { - THREE_BUTTONS(false, 0), - TWO_BUTTONS(true, 1), - NO_BUTTON(true, 2); + THREE_BUTTONS(false, 0, LAUNCHER_NAVIGATION_MODE_3_BUTTON), + TWO_BUTTONS(true, 1, LAUNCHER_NAVIGATION_MODE_2_BUTTON), + NO_BUTTON(true, 2, LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON); public final boolean hasGestures; public final int resValue; + public final LauncherEvent launcherEvent; - Mode(boolean hasGestures, int resValue) { + Mode(boolean hasGestures, int resValue, LauncherEvent launcherEvent) { this.hasGestures = hasGestures; this.resValue = resValue; + this.launcherEvent = launcherEvent; } } @@ -147,7 +153,6 @@ public class SysUINavigationMode { } public interface NavigationModeChangeListener { - void onNavigationModeChanged(Mode newMode); } } \ No newline at end of file diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index a89319eacf..256ad82baa 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -59,6 +59,7 @@ import com.android.launcher3.util.LogConfig; import com.android.systemui.shared.system.SysUiStatsLog; import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.OptionalInt; @@ -110,21 +111,22 @@ public class StatsLogCompatManager extends StatsLogManager { } /** - * Logs the workspace layout information on the model thread. + * Logs impression of the current workspace with additional launcher events. */ @Override - public void logSnapshot() { + public void logSnapshot(List extraEvents) { LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask( - new SnapshotWorker()); + new SnapshotWorker(extraEvents)); } private class SnapshotWorker extends BaseModelUpdateTask { - private final InstanceId mInstanceId; + private final List mExtraEvents; - SnapshotWorker() { - mInstanceId = new InstanceIdSequence( - 1 << 20 /*InstanceId.INSTANCE_ID_MAX*/).newInstanceId(); + SnapshotWorker(List extraEvents) { + mInstanceId = new InstanceIdSequence(1 << 20 /*InstanceId.INSTANCE_ID_MAX*/) + .newInstanceId(); + this.mExtraEvents = extraEvents; } @Override @@ -165,6 +167,9 @@ public class StatsLogCompatManager extends StatsLogManager { LauncherAtom.ItemInfo atomInfo = info.buildProto(null); writeSnapshot(atomInfo, mInstanceId); } + mExtraEvents + .forEach(eventName -> logger().withInstanceId(mInstanceId).log(eventName)); + getDevicePrefs(mContext).edit() .putLong(LAST_SNAPSHOT_TIME_MILLIS, currentTimeMillis()).apply(); } diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index 8e23b65d5f..2abde02a73 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -33,11 +33,16 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.userevent.LauncherLogProto; import com.android.launcher3.util.ResourceBasedOverride; +import java.util.List; + /** * Handles the user event logging in R+. + * + *
  * All of the event ids are defined here.
  * Most of the methods are dummy methods for Launcher3
  * Actual call happens only for Launcher variant that implements QuickStep.
+ * 
*/ public class StatsLogManager implements ResourceBasedOverride { @@ -49,8 +54,8 @@ public class StatsLogManager implements ResourceBasedOverride { public static final int LAUNCHER_STATE_UNCHANGED = 5; /** - * Returns proper launcher state enum for {@link StatsLogManager} - * (to be removed during UserEventDispatcher cleanup) + * Returns proper launcher state enum for {@link StatsLogManager}(to be removed during + * UserEventDispatcher cleanup) */ public static int containerTypeToAtomState(int containerType) { switch (containerType) { @@ -67,9 +72,8 @@ public class StatsLogManager implements ResourceBasedOverride { } /** - * Returns event enum based on the two {@link ContainerType} transition information when - * swipe gesture happens. - * (to be removed during UserEventDispatcher cleanup) + * Returns event enum based on the two {@link ContainerType} transition information when swipe + * gesture happens(to be removed during UserEventDispatcher cleanup). */ public static EventEnum getLauncherAtomEvent(int startContainerType, int targetContainerType, EventEnum fallbackEvent) { @@ -273,7 +277,46 @@ public class StatsLogManager implements ResourceBasedOverride { LAUNCHER_SELECT_MODE_CLOSE(583), @UiEvent(doc = "User tapped on the highlight items in select mode") - LAUNCHER_SELECT_MODE_ITEM(584); + LAUNCHER_SELECT_MODE_ITEM(584), + + @UiEvent(doc = "Notification dot on app icon enabled.") + LAUNCHER_NOTIFICATION_DOT_ENABLED(611), + + @UiEvent(doc = "Notification dot on app icon disabled.") + LAUNCHER_NOTIFICATION_DOT_DISABLED(612), + + @UiEvent(doc = "For new apps, add app icons to home screen enabled.") + LAUNCHER_ADD_NEW_APPS_TO_HOME_SCREEN_ENABLED(613), + + @UiEvent(doc = "For new apps, add app icons to home screen disabled.") + LAUNCHER_ADD_NEW_APPS_TO_HOME_SCREEN_DISABLED(614), + + @UiEvent(doc = "Home screen rotation is enabled when phone is rotated.") + LAUNCHER_HOME_SCREEN_ROTATION_ENABLED(615), + + @UiEvent(doc = "Home screen rotation is disabled when phone is rotated.") + LAUNCHER_HOME_SCREEN_ROTATION_DISABLED(616), + + @UiEvent(doc = "Suggestions in all apps list enabled.") + LAUNCHER_ALL_APPS_SUGGESTIONS_ENABLED(619), + + @UiEvent(doc = "Suggestions in all apps list disabled.") + LAUNCHER_ALL_APPS_SUGGESTIONS_DISABLED(620), + + @UiEvent(doc = "Suggestions on home screen is enabled.") + LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED(621), + + @UiEvent(doc = "Suggestions on home screen is disabled.") + LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED(622), + + @UiEvent(doc = "System navigation is 3 button mode.") + LAUNCHER_NAVIGATION_MODE_3_BUTTON(623), + + @UiEvent(doc = "System navigation mode is 2 button mode.") + LAUNCHER_NAVIGATION_MODE_2_BUTTON(624), + + @UiEvent(doc = "System navigation mode is 0 button mode/gesture navigation mode .") + LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON(625); // ADD MORE @@ -417,8 +460,8 @@ public class StatsLogManager implements ResourceBasedOverride { } /** - * Logs snapshot, or impression of the current workspace. + * Logs impression of the current workspace with additional launcher events. */ - public void logSnapshot() { + public void logSnapshot(List additionalEvents) { } } From cfec6b5151adf116ca54ff7eadec3989584a6311 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 27 Jul 2020 12:15:53 -0700 Subject: [PATCH 27/51] Adding tracing for work profile removal Bug: 159671700 Change-Id: I6e1bcdfbf1bbaab989106ce2979575652a3fb404 --- src/com/android/launcher3/pm/UserCache.java | 5 +++++ src/com/android/launcher3/testing/TestProtocol.java | 1 + tests/src/com/android/launcher3/ui/WorkTabTest.java | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java index 5aab41a8a2..2d7d6b092a 100644 --- a/src/com/android/launcher3/pm/UserCache.java +++ b/src/com/android/launcher3/pm/UserCache.java @@ -21,8 +21,10 @@ import android.content.Intent; import android.os.UserHandle; import android.os.UserManager; import android.util.ArrayMap; +import android.util.Log; import android.util.LongSparseArray; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SafeCloseable; import com.android.launcher3.util.SimpleBroadcastReceiver; @@ -102,6 +104,9 @@ public class UserCache { mUsers = null; mUserToSerialMap = null; } + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work profile removed", new Exception()); + } } } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 3ca08fd8ec..626d9dd966 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -106,4 +106,5 @@ public final class TestProtocol { public static final String PAUSE_NOT_DETECTED = "b/139891609"; public static final String OVERIEW_NOT_ALLAPPS = "b/156095088"; public static final String NO_SWIPE_TO_HOME = "b/158017601"; + public static final String WORK_PROFILE_REMOVED = "b/159671700"; } diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java index 8d571ff18c..f5f93c429f 100644 --- a/tests/src/com/android/launcher3/ui/WorkTabTest.java +++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; +import android.util.Log; import android.widget.TextView; import androidx.test.filters.LargeTest; @@ -34,6 +35,7 @@ import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsPagedView; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.views.WorkEduView; import org.junit.After; @@ -132,6 +134,10 @@ public class WorkTabTest extends AbstractLauncherUiTest { l.getResources().getString(R.string.work_profile_edu_personal_apps)); workEduView.findViewById(R.id.proceed).callOnClick(); }); + + executeOnLauncher(launcher -> Log.d(TestProtocol.WORK_PROFILE_REMOVED, + "Work profile status: " + launcher.getAppsView().isPersonalTabVisible())); + // verify work edu is seen next waitForLauncherCondition("Launcher did not show the next edu screen", l -> ((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage() == WORK_PAGE From f496ea46342bd7420c3cf453bcbd5c12f7ecfc5d Mon Sep 17 00:00:00 2001 From: Jonathan Miranda Date: Wed, 29 Jul 2020 19:03:29 +0000 Subject: [PATCH 28/51] Revert "Fix bug where double swipe gets us stuck in Hint state while in Overview." This reverts commit a8c08584a7bb295a2f14eafd2923a2688d3e3626. Reason for revert: "caused a regression with quick switch from home: if you start the gesture then swipe back to the left, it ends up launching the task anyway" Change-Id: I8e12e2de46b6fc6a3faeb0336762da08080c61d6 --- .../src/com/android/quickstep/BaseSwipeUpHandlerV2.java | 1 - .../src/com/android/quickstep/SwipeUpAnimationLogic.java | 1 - .../src/com/android/quickstep/views/TaskMenuView.java | 1 - src/com/android/launcher3/anim/AlphaUpdateListener.java | 3 +-- .../android/launcher3/anim/AnimationSuccessListener.java | 8 -------- .../launcher3/anim/AnimatorPlaybackController.java | 1 - src/com/android/launcher3/statemanager/StateManager.java | 1 - 7 files changed, 1 insertion(+), 15 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index e084de1acb..a3f1dd4c5f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -1090,7 +1090,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte anim.addAnimatorListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); if (mActivity != null) { removeLiveTileOverlay(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java index 07faab7aeb..e54a21c073 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -287,7 +287,6 @@ public abstract class SwipeUpAnimationLogic { @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); mHomeAnim.dispatchOnStart(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java index 9b2048e4ac..8b49f2c212 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java @@ -282,7 +282,6 @@ public class TaskMenuView extends AbstractFloatingView { mOpenCloseAnimator.addListener(new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); setVisibility(VISIBLE); } diff --git a/src/com/android/launcher3/anim/AlphaUpdateListener.java b/src/com/android/launcher3/anim/AlphaUpdateListener.java index 69716eabf1..eabd283699 100644 --- a/src/com/android/launcher3/anim/AlphaUpdateListener.java +++ b/src/com/android/launcher3/anim/AlphaUpdateListener.java @@ -46,8 +46,7 @@ public class AlphaUpdateListener extends AnimationSuccessListener } @Override - public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); + public void onAnimationStart(Animator arg0) { // We want the views to be visible for animation, so fade-in/out is visible mView.setVisibility(View.VISIBLE); } diff --git a/src/com/android/launcher3/anim/AnimationSuccessListener.java b/src/com/android/launcher3/anim/AnimationSuccessListener.java index b83417c2eb..9905e81638 100644 --- a/src/com/android/launcher3/anim/AnimationSuccessListener.java +++ b/src/com/android/launcher3/anim/AnimationSuccessListener.java @@ -19,8 +19,6 @@ package com.android.launcher3.anim; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import androidx.annotation.CallSuper; - /** * Extension of {@link AnimatorListenerAdapter} for listening for non-cancelled animations */ @@ -28,12 +26,6 @@ public abstract class AnimationSuccessListener extends AnimatorListenerAdapter { protected boolean mCancelled = false; - @Override - @CallSuper - public void onAnimationStart(Animator animation) { - mCancelled = false; - } - @Override public void onAnimationCancel(Animator animation) { mCancelled = true; diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java index 31e0418571..ea0ff8b687 100644 --- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java +++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java @@ -335,7 +335,6 @@ public class AnimatorPlaybackController implements ValueAnimator.AnimatorUpdateL @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); mCancelled = false; mDispatched = false; } diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java index f1e7f166e5..60b87d984b 100644 --- a/src/com/android/launcher3/statemanager/StateManager.java +++ b/src/com/android/launcher3/statemanager/StateManager.java @@ -315,7 +315,6 @@ public class StateManager> { @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); // Change the internal state only when the transition actually starts onStateTransitionStart(state); } From 16eb9226c5c21e6cb6913c50b7b13057b851152c Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 7 Jul 2020 19:25:25 -0700 Subject: [PATCH 29/51] Fix adjacent task offset distance Instead of calculating an overall distance for tasks to translate based on RecentsView width, calculate the distance for the tasks to the left and right of the midpoint based on how far the first adjacent tasks in those directions are from being offscreen. Changes made to make "distance to offscreen" calculations possible: - Update TaskView curve scale to reach final scale as soon as it is completely offscreen. Before, it would reach its final scale just shy of that point (calculations were off). - As we update RecentsView scale, calculate how much the new scale will push out tasks that are just offscreen. - With both above, we can calculate the scale and position of a TaskView such that it is just offscreen, and interpolate between its current position and that position. Tests: - Task comes in immediately when quick switching from home, and doesn't shift as you swipe directly upwards. - When swiping far up from an app, tasks come in from all the way offscreen, and cover distance appropriately (e.g. if you're scrolled a bit to the right when you pause, the left adjacent app will move faster to cover the farther distance). - Task modalness: entering Select mode now animates adjacent tasks at the same rate as the scaling up, because they move only the distance needed to get offscreen (before they moved way too far and thus seemed to be much faster than the rest of the animation). Bug: 149934536 Change-Id: Ie3fffe0e5c304cb16e7637f058f5ce72cee40aeb Merged-In: Ie3fffe0e5c304cb16e7637f058f5ce72cee40aeb --- .../QuickstepAtomicAnimationFactory.java | 4 +- .../NoButtonQuickSwitchTouchController.java | 7 +- .../FallbackRecentsStateController.java | 4 +- .../quickstep/util/TaskViewSimulator.java | 6 +- .../android/quickstep/views/RecentsView.java | 126 ++++++++++++++++-- .../BaseRecentsViewStateController.java | 6 +- .../quickstep/BaseActivityInterface.java | 4 +- src/com/android/launcher3/PagedView.java | 21 ++- .../touch/LandscapePagedViewHandler.java | 1 + .../touch/PagedOrientationHandler.java | 1 + .../touch/PortraitPagedViewHandler.java | 1 + 11 files changed, 146 insertions(+), 35 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index a0af79743b..131fcbfbf1 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -17,7 +17,6 @@ package com.android.launcher3.uioverrides.states; import static android.view.View.VISIBLE; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.HINT_STATE; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; @@ -52,6 +51,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_S import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import android.animation.Animator; import android.animation.AnimatorSet; @@ -212,7 +212,7 @@ public class QuickstepAtomicAnimationFactory extends // Scale up the recents, if it is not coming from the side RecentsView overview = mActivity.getOverviewPanel(); if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) { - SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE); + RECENTS_SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE); } } config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index 1b439d1d31..821ada400e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.uioverrides.touchcontrollers; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; @@ -47,6 +46,7 @@ import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE; import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import android.animation.Animator; @@ -244,7 +244,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, final LauncherState toState = OVERVIEW; // Set RecentView's initial properties. - SCALE_PROPERTY.set(mRecentsView, fromState.getOverviewScaleAndOffset(mLauncher)[0]); + RECENTS_SCALE_PROPERTY.set(mRecentsView, fromState.getOverviewScaleAndOffset(mLauncher)[0]); ADJACENT_PAGE_OFFSET.set(mRecentsView, 1f); mRecentsView.setContentAlpha(1); mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress()); @@ -266,7 +266,8 @@ public class NoButtonQuickSwitchTouchController implements TouchController, // - RecentsView scale // - RecentsView fullscreenProgress PendingAnimation yAnim = new PendingAnimation((long) (mYRange * 2)); - yAnim.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndOffset[0], SCALE_DOWN_INTERPOLATOR); + yAnim.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0], + SCALE_DOWN_INTERPOLATOR); yAnim.setFloat(mRecentsView, FULLSCREEN_PROGRESS, toState.getOverviewFullscreenProgress(), SCALE_DOWN_INTERPOLATOR); mYOverviewAnim = yAnim.createPlaybackController(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 3f1e7bad9b..163c23268b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -15,7 +15,6 @@ */ package com.android.quickstep.fallback; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; @@ -25,6 +24,7 @@ import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVER import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; import com.android.launcher3.anim.PendingAnimation; @@ -82,7 +82,7 @@ public class FallbackRecentsStateController implements StateHandler { }); mCurrentFullscreenParams = new FullscreenDrawParams(context); - mPageSpacing = context.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing); } /** @@ -251,7 +248,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { int start = mOrientationState.getOrientationHandler() .getPrimaryValue(mTaskRect.left, mTaskRect.top); mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize; - mScrollState.updateInterpolation(start, mPageSpacing); + mScrollState.pageParentScale = recentsViewScale.value; + mScrollState.updateInterpolation(start); mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 26e6d87a67..9c93fed833 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -22,7 +22,6 @@ import static android.view.View.MeasureSpec.makeMeasureSpec; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; @@ -62,6 +61,7 @@ import android.graphics.Canvas; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; @@ -209,6 +209,23 @@ public abstract class RecentsView extends PagedView } }; + /** Same as normal SCALE_PROPERTY, but also updates page offsets that depend on this scale. */ + public static final FloatProperty RECENTS_SCALE_PROPERTY = + new FloatProperty("recentsScale") { + @Override + public void setValue(RecentsView view, float scale) { + view.setScaleX(scale); + view.setScaleY(scale); + view.mLastComputedTaskPushOutDistance = null; + view.updatePageOffsets(); + } + + @Override + public Float get(RecentsView view) { + return view.getScaleX(); + } + }; + protected RecentsOrientedState mOrientationState; protected final BaseActivityInterface mSizeStrategy; protected RecentsAnimationController mRecentsAnimationController; @@ -216,8 +233,12 @@ public abstract class RecentsView extends PagedView protected SurfaceTransactionApplier mSyncTransactionApplier; protected int mTaskWidth; protected int mTaskHeight; + protected final Rect mLastComputedTaskSize = new Rect(); + // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot. + protected Float mLastComputedTaskPushOutDistance = null; protected boolean mEnableDrawingLiveTile = false; protected final Rect mTempRect = new Rect(); + protected final RectF mTempRectF = new RectF(); private final PointF mTempPointF = new PointF(); private static final int DISMISS_TASK_DURATION = 300; @@ -864,6 +885,7 @@ public abstract class RecentsView extends PagedView public void getTaskSize(Rect outRect) { mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect, mOrientationHandler); + mLastComputedTaskSize.set(outRect); } /** Gets the task size for modal state. */ @@ -905,8 +927,8 @@ public abstract class RecentsView extends PagedView final int pageCount = getPageCount(); for (int i = 0; i < pageCount; i++) { View page = getPageAt(i); - mScrollState.updateInterpolation(mOrientationHandler.getChildStartWithTranslation(page), - mPageSpacing); + mScrollState.updateInterpolation( + mOrientationHandler.getChildStartWithTranslation(page)); ((PageCallbacks) page).onPageScroll(mScrollState); } } @@ -1321,10 +1343,14 @@ public abstract class RecentsView extends PagedView /** * Updates linearInterpolation for the provided child position */ - public void updateInterpolation(float childStart, int pageSpacing) { - float pageCenter = childStart + halfPageSize; + public void updateInterpolation(float childStart) { + float scaledHalfPageSize = halfPageSize / pageParentScale; + float pageCenter = childStart + scaledHalfPageSize; float distanceFromScreenCenter = screenCenter - pageCenter; - float distanceToReachEdge = halfScreenSize + halfPageSize + pageSpacing; + // How far the page has to move from the center to be offscreen, taking into account + // the EDGE_SCALE_DOWN_FACTOR that will be applied at that position. + float distanceToReachEdge = halfScreenSize + + scaledHalfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR); linearInterpolation = Math.min(1, Math.abs(distanceFromScreenCenter) / distanceToReachEdge); } @@ -1761,14 +1787,15 @@ public abstract class RecentsView extends PagedView setPivotX(mTempPointF.x); setPivotY(mTempPointF.y); setTaskModalness(mTaskModalness); + mLastComputedTaskPushOutDistance = null; updatePageOffsets(); setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO : IMPORTANT_FOR_ACCESSIBILITY_AUTO); } private void updatePageOffsets() { - float offset = mAdjacentPageOffset * getWidth(); - float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness) * getWidth(); + float offset = mAdjacentPageOffset; + float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness); if (mIsRtl) { offset = -offset; modalOffset = -modalOffset; @@ -1777,18 +1804,89 @@ public abstract class RecentsView extends PagedView TaskView runningTask = mRunningTaskId == -1 || !mRunningTaskTileHidden ? null : getTaskView(mRunningTaskId); - int midPoint = runningTask == null ? -1 : indexOfChild(runningTask); - int currentPage = getCurrentPage(); + int midpoint = runningTask == null ? -1 : indexOfChild(runningTask); + int modalMidpoint = getCurrentPage(); + + float midpointOffsetSize = 0; + float leftOffsetSize = midpoint - 1 >= 0 + ? -getOffsetSize(midpoint - 1, midpoint, offset) + : 0; + float rightOffsetSize = midpoint + 1 < count + ? getOffsetSize(midpoint + 1, midpoint, offset) + : 0; + + float modalMidpointOffsetSize = 0; + float modalLeftOffsetSize = modalMidpoint - 1 >= 0 + ? -getOffsetSize(modalMidpoint - 1, modalMidpoint, modalOffset) + : 0; + float modalRightOffsetSize = modalMidpoint + 1 < count + ? getOffsetSize(modalMidpoint + 1, modalMidpoint, modalOffset) + : 0; for (int i = 0; i < count; i++) { - float translation = i == midPoint ? 0 : (i < midPoint ? -offset : offset); - float modalTranslation = - i == currentPage ? 0 : (i < currentPage ? -modalOffset : modalOffset); + float translation = i == midpoint + ? midpointOffsetSize + : i < midpoint + ? leftOffsetSize + : rightOffsetSize; + float modalTranslation = i == modalMidpoint + ? modalMidpointOffsetSize + : i < modalMidpoint + ? modalLeftOffsetSize + : modalRightOffsetSize; getChildAt(i).setTranslationX(translation + modalTranslation); } updateCurveProperties(); } + /** + * Computes the distance to offset the given child such that it is completely offscreen when + * translating away from the given midpoint. + * @param offsetProgress From 0 to 1 where 0 means no offset and 1 means offset offscreen. + */ + private float getOffsetSize(int childIndex, int midpointIndex, float offsetProgress) { + if (offsetProgress == 0) { + // Don't bother calculating everything below if we won't offset anyway. + return 0; + } + // First, get the position of the task relative to the midpoint. If there is no midpoint + // then we just use the normal (centered) task position. + mTempRectF.set(mLastComputedTaskSize); + RectF taskPosition = mTempRectF; + float desiredLeft = getWidth(); + float distanceToOffscreen = desiredLeft - taskPosition.left; + // Used to calculate the scale of the task view based on its new offset. + float centerToOffscreenProgress = Math.abs(offsetProgress); + if (midpointIndex > -1) { + // When there is a midpoint reference task, adjacent tasks have less distance to travel + // to reach offscreen. Offset the task position to the task's starting point. + View child = getChildAt(childIndex); + View midpointChild = getChildAt(midpointIndex); + int distanceFromMidpoint = Math.abs(mOrientationHandler.getChildStart(child) + - mOrientationHandler.getChildStart(midpointChild) + + getDisplacementFromScreenCenter(midpointIndex)); + taskPosition.offset(distanceFromMidpoint, 0); + centerToOffscreenProgress = Utilities.mapRange(centerToOffscreenProgress, + distanceFromMidpoint / distanceToOffscreen, 1); + } + // Find the task's scale based on its offscreen progress, then see how far it still needs to + // move to be completely offscreen. + Utilities.scaleRectFAboutCenter(taskPosition, + TaskView.getCurveScaleForInterpolation(centerToOffscreenProgress)); + distanceToOffscreen = desiredLeft - taskPosition.left; + // Finally, we need to account for RecentsView scale, because it moves tasks based on its + // pivot. To do this, we move the task position to where it would be offscreen at scale = 1 + // (computed above), then we apply the scale via getMatrix() to determine how much that + // moves the task from its desired position, and adjust the computed distance accordingly. + if (mLastComputedTaskPushOutDistance == null) { + taskPosition.offsetTo(desiredLeft, 0); + getMatrix().mapRect(taskPosition); + mLastComputedTaskPushOutDistance = (taskPosition.left - desiredLeft) / getScaleX(); + } + distanceToOffscreen -= mLastComputedTaskPushOutDistance; + return distanceToOffscreen * offsetProgress; + } + /** * TODO: Do not assume motion across X axis for adjacent page */ @@ -1887,7 +1985,7 @@ public abstract class RecentsView extends PagedView float toScale = getMaxScaleForFullScreen(); if (launchingCenterTask) { RecentsView recentsView = tv.getRecentsView(); - anim.play(ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY, toScale)); + anim.play(ObjectAnimator.ofFloat(recentsView, RECENTS_SCALE_PROPERTY, toScale)); anim.play(ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS, 1)); } else { // We are launching an adjacent task, so parallax the center and other adjacent task. diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index ec3a4905f5..6e120e8bd8 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -16,7 +16,6 @@ package com.android.launcher3.uioverrides; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS; @@ -29,6 +28,7 @@ import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVER import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import android.util.FloatProperty; @@ -61,7 +61,7 @@ public abstract class BaseRecentsViewStateController @Override public void setState(@NonNull LauncherState state) { float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher); - SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]); + RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]); ADJACENT_PAGE_OFFSET.set(mRecentsView, scaleAndOffset[1]); getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0); @@ -93,7 +93,7 @@ public abstract class BaseRecentsViewStateController void setStateWithAnimationInternal(@NonNull final LauncherState toState, @NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) { float[] scaleAndOffset = toState.getOverviewScaleAndOffset(mLauncher); - setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndOffset[0], + setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0], config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR)); setter.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1], config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR)); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 56005893cd..df8f31d2c0 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -15,7 +15,6 @@ */ package com.android.quickstep; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.INSTANT; import static com.android.launcher3.anim.Interpolators.LINEAR; @@ -28,6 +27,7 @@ import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_REC import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import android.animation.Animator; import android.annotation.TargetApi; @@ -400,7 +400,7 @@ public abstract class BaseActivityInterface extends ViewGrou int minDistanceFromScreenCenterIndex = -1; final int childCount = getChildCount(); for (int i = 0; i < childCount; ++i) { - View layout = getPageAt(i); - int childSize = mOrientationHandler.getMeasuredSize(layout); - int halfChildSize = (childSize / 2); - int childCenter = getChildOffset(i) + halfChildSize; - int distanceFromScreenCenter = Math.abs(childCenter - screenCenter); + int distanceFromScreenCenter = Math.abs( + getDisplacementFromScreenCenter(i, screenCenter)); if (distanceFromScreenCenter < minDistanceFromScreenCenter) { minDistanceFromScreenCenter = distanceFromScreenCenter; minDistanceFromScreenCenterIndex = i; @@ -1461,6 +1458,20 @@ public abstract class PagedView extends ViewGrou return minDistanceFromScreenCenterIndex; } + private int getDisplacementFromScreenCenter(int childIndex, int screenCenter) { + View layout = getPageAt(childIndex); + int childSize = mOrientationHandler.getMeasuredSize(layout); + int halfChildSize = (childSize / 2); + int childCenter = getChildOffset(childIndex) + halfChildSize; + return childCenter - screenCenter; + } + + protected int getDisplacementFromScreenCenter(int childIndex) { + int pageOrientationSize = mOrientationHandler.getMeasuredSize(this); + int screenCenter = mOrientationHandler.getPrimaryScroll(this) + (pageOrientationSize / 2); + return getDisplacementFromScreenCenter(childIndex, screenCenter); + } + protected void snapToDestination() { snapToPage(getPageNearestToCenterOfScreen(), getPageSnapDuration()); } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index c2bfb167a2..ab495eadc7 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -72,6 +72,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { out.halfPageSize = view.getNormalChildHeight() / 2; out.halfScreenSize = view.getMeasuredHeight() / 2; out.screenCenter = insets.top + view.getPaddingTop() + out.scroll + out.halfPageSize; + out.pageParentScale = view.getScaleY(); } @Override diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index b650526fe1..8abb0475dc 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -109,6 +109,7 @@ public interface PagedOrientationHandler { public int halfPageSize; public int screenCenter; public int halfScreenSize; + public float pageParentScale; } class ChildBounds { diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index e87c887d33..3acb3aef90 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -70,6 +70,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { out.halfPageSize = view.getNormalChildWidth() / 2; out.halfScreenSize = view.getMeasuredWidth() / 2; out.screenCenter = insets.left + view.getPaddingLeft() + out.scroll + out.halfPageSize; + out.pageParentScale = view.getScaleX(); } @Override From 553d4dfe7d30376baabebe9c09408e68b64224ef Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Mon, 20 Jul 2020 11:03:39 -0700 Subject: [PATCH 30/51] Minimal Phone Mode (part-2) Integrate with ContentProvider from Digital Wellbeing Change-Id: Ie1fbb706e767ac5d760d686af88a9a0adf162418 --- .../launcher3/model/WellbeingModel.java | 57 +++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java index f42b124fd6..cc7b712842 100644 --- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java +++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java @@ -43,9 +43,11 @@ import android.util.ArrayMap; import android.util.Log; import androidx.annotation.MainThread; +import androidx.annotation.WorkerThread; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.popup.RemoteActionShortcut; import com.android.launcher3.popup.SystemShortcut; @@ -57,6 +59,7 @@ import com.android.launcher3.util.SimpleBroadcastReceiver; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.function.Consumer; /** * Data model for digital wellbeing status of apps. @@ -72,6 +75,9 @@ public final class WellbeingModel { private static final int MSG_FULL_REFRESH = 3; // Welbeing contract + private static final String PATH_ACTIONS = "actions"; + private static final String PATH_MINIMAL_DEVICE = "minimal_device"; + private static final String METHOD_GET_MINIMAL_DEVICE_CONFIG = "get_minimal_device_config"; private static final String METHOD_GET_ACTIONS = "get_actions"; private static final String EXTRA_ACTIONS = "actions"; private static final String EXTRA_ACTION = "action"; @@ -104,15 +110,22 @@ public final class WellbeingModel { mContentObserver = new ContentObserver(MAIN_EXECUTOR.getHandler()) { @Override public void onChange(boolean selfChange, Uri uri) { - // Wellbeing reports that app actions have changed. if (DEBUG || mIsInTest) { - Log.d(TAG, "ContentObserver.onChange() called with: selfChange = [" + selfChange - + "], uri = [" + uri + "]"); + Log.d(TAG, "ContentObserver.onChange() called with: selfChange = [" + + selfChange + "], uri = [" + uri + "]"); } Preconditions.assertUIThread(); - updateWellbeingData(); + + if (uri.getPath().contains(PATH_ACTIONS)) { + // Wellbeing reports that app actions have changed. + updateWellbeingData(); + } else if (uri.getPath().contains(PATH_MINIMAL_DEVICE)) { + // Wellbeing reports that minimal device state or config is changed. + updateLauncherModel(); + } } }; + FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, this::updateLauncherModel); if (!TextUtils.isEmpty(mWellbeingProviderPkg)) { context.registerReceiver( @@ -146,14 +159,18 @@ public final class WellbeingModel { private void restartObserver() { final ContentResolver resolver = mContext.getContentResolver(); resolver.unregisterContentObserver(mContentObserver); - Uri actionsUri = apiBuilder().path("actions").build(); + Uri actionsUri = apiBuilder().path(PATH_ACTIONS).build(); + Uri minimalDeviceUri = apiBuilder().path(PATH_MINIMAL_DEVICE).build(); try { resolver.registerContentObserver( actionsUri, true /* notifyForDescendants */, mContentObserver); + resolver.registerContentObserver( + minimalDeviceUri, true /* notifyForDescendants */, mContentObserver); } catch (Exception e) { Log.e(TAG, "Failed to register content observer for " + actionsUri + ": " + e); if (mIsInTest) throw new RuntimeException(e); } + updateWellbeingData(); } @@ -191,12 +208,42 @@ public final class WellbeingModel { mWorkerHandler.sendEmptyMessage(MSG_FULL_REFRESH); } + private void updateLauncherModel() { + if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) return; + + // TODO: init Launcher in minimal device / normal mode + } + private Uri.Builder apiBuilder() { return new Uri.Builder() .scheme(SCHEME_CONTENT) .authority(mWellbeingProviderPkg + ".api"); } + /** + * Fetch most up-to-date minimal device config. + */ + @WorkerThread + private void runWithMinimalDeviceConfigs(Consumer consumer) { + if (DEBUG || mIsInTest) { + Log.d(TAG, "runWithMinimalDeviceConfigs() called"); + } + Preconditions.assertNonUiThread(); + + final Uri contentUri = apiBuilder().build(); + final Bundle remoteBundle; + try (ContentProviderClient client = mContext.getContentResolver() + .acquireUnstableContentProviderClient(contentUri)) { + remoteBundle = client.call( + METHOD_GET_MINIMAL_DEVICE_CONFIG, null /* args */, null /* extras */); + consumer.accept(remoteBundle); + } catch (Exception e) { + Log.e(TAG, "Failed to retrieve data from " + contentUri + ": " + e); + if (mIsInTest) throw new RuntimeException(e); + } + if (DEBUG || mIsInTest) Log.i(TAG, "runWithMinimalDeviceConfigs(): finished"); + } + private boolean updateActions(String... packageNames) { if (packageNames.length == 0) { return true; From 48afb6b3b9f5a4d67e36a7c6cc994efeb8b9be38 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 30 Jul 2020 14:40:29 -0700 Subject: [PATCH 31/51] Fixing wrong velocity state when there are too few samples Bug: 160568387 Change-Id: I32b3b7ee1bff5595941fc0c0b37c9f5a28d1a1fa --- .../quickstep/util/MotionPauseDetector.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java index a5d456878a..969fa5067d 100644 --- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java +++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java @@ -358,18 +358,23 @@ public class MotionPauseDetector { if (count < 3) { // Too few samples - if (count == 2) { - int endPos = pointPos - 1; - if (endPos < 0) { - endPos += HISTORY_SIZE; - } - float denominator = eventTime - mHistoricTimes[endPos]; - if (denominator != 0) { - return (eventTime - mHistoricPos[endPos]) / denominator; - + switch (count) { + case 2: { + int endPos = pointPos - 1; + if (endPos < 0) { + endPos += HISTORY_SIZE; + } + float denominator = eventTime - mHistoricTimes[endPos]; + if (denominator != 0) { + return (mHistoricPos[pointPos] - mHistoricPos[endPos]) / denominator; + } } + // fall through + case 1: + return 0f; + default: + return null; } - return null; } float Sxx = sxi2 - sxi * sxi / count; From bf103f16b18642dcaa631fb0892c55084164a468 Mon Sep 17 00:00:00 2001 From: Sreyas Date: Tue, 5 May 2020 12:29:37 -0700 Subject: [PATCH 32/51] Creating UI tests for overview action buttons. Change-Id: Ie6298064a068dc978ca33fb64e1856c3ba2a8cb1 --- .../QuickstepTestInformationHandler.java | 6 + .../android/quickstep/TaplTestsQuickstep.java | 24 +++- .../launcher3/testing/TestProtocol.java | 1 + .../android/launcher3/tapl/BaseOverview.java | 17 ++- .../tapl/LauncherInstrumentation.java | 14 ++ .../launcher3/tapl/OverviewActions.java | 130 ++++++++++++++++++ .../launcher3/tapl/SelectModeButtons.java | 68 +++++++++ 7 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 tests/tapl/com/android/launcher3/tapl/OverviewActions.java create mode 100644 tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java index 6f4d34c8c7..5026f36e08 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -58,6 +58,12 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()); return response; } + + case TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED: { + response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, + FeatureFlags.ENABLE_OVERVIEW_SHARE.get()); + return response; + } } return super.call(method); diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index bf093fdabf..ecd4e2bd67 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -36,6 +36,7 @@ import com.android.launcher3.tapl.AllAppsFromOverview; import com.android.launcher3.tapl.Background; import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel; import com.android.launcher3.tapl.Overview; +import com.android.launcher3.tapl.OverviewActions; import com.android.launcher3.tapl.OverviewTask; import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.ui.TaplTestsLauncher3; @@ -68,11 +69,14 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { }); } - private void startTestApps() throws Exception { + public static void startTestApps() throws Exception { startAppFast(getAppPackageName()); startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); startTestActivity(2); + } + private void startTestAppsWithCheck() throws Exception { + startTestApps(); executeOnLauncher(launcher -> assertTrue( "Launcher activity is the top activity; expecting another activity to be the top " + "one", @@ -105,7 +109,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { @Test @PortraitLandscape public void testOverview() throws Exception { - startTestApps(); + startTestAppsWithCheck(); // mLauncher.pressHome() also tests an important case of pressing home while in background. Overview overview = mLauncher.pressHome().switchToOverview(); assertTrue("Launcher internal state didn't switch to Overview", @@ -189,6 +193,22 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { 0, getTaskCount(launcher))); } + /** + * Smoke test for action buttons: Presses all the buttons and makes sure no crashes occur. + */ + @Test + @NavigationModeSwitch + @PortraitLandscape + public void testOverviewActions() throws Exception { + if (mLauncher.getNavigationModel() != NavigationModel.TWO_BUTTON) { + startTestAppsWithCheck(); + OverviewActions actionsView = + mLauncher.pressHome().switchToOverview().getOverviewActions(); + actionsView.clickAndDismissScreenshot(); + actionsView.clickAndDismissShare(); + } + } + private int getCurrentOverviewPage(Launcher launcher) { return launcher.getOverviewPanel().getCurrentPage(); } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 626d9dd966..58bff090e8 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -98,6 +98,7 @@ public final class TestProtocol { public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing"; public static final String REQUEST_OVERVIEW_ACTIONS_ENABLED = "overview-actions-enabled"; + public static final String REQUEST_OVERVIEW_SHARE_ENABLED = "overview-share-enabled"; public static boolean sDisableSensorRotation; public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation"; diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java index 223ae298b9..588b6b8f07 100644 --- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java +++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java @@ -27,7 +27,7 @@ import java.util.Collections; import java.util.List; /** - * Common overview pane for both Launcher and fallback recents + * Common overview panel for both Launcher and fallback recents */ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { private static final int FLINGS_FOR_DISMISS_LIMIT = 40; @@ -135,4 +135,19 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer { public boolean hasTasks() { return getTasks().size() > 0; } + + /** + * Gets Overview Actions. + * + * @return The Overview Actions + */ + @NonNull + public OverviewActions getOverviewActions() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get overview actions")) { + verifyActiveContainer(); + UiObject2 overviewActions = mLauncher.waitForLauncherObject("action_buttons"); + return new OverviewActions(overviewActions, mLauncher); + } + } } \ No newline at end of file diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 94c75b0bea..85f3234bf1 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -154,6 +154,7 @@ public final class LauncherInstrumentation { private static final String CONTEXT_MENU_RES_ID = "deep_shortcuts_container"; public static final int WAIT_TIME_MS = 10000; private static final String SYSTEMUI_PACKAGE = "com.android.systemui"; + private static final String ANDROID_PACKAGE = "android"; private static WeakReference sActiveContainer = new WeakReference<>(null); @@ -926,6 +927,14 @@ public final class LauncherInstrumentation { return waitForObjectBySelector(getOverviewObjectSelector(resName)); } + @NonNull + UiObject2 waitForAndroidObject(String resId) { + final UiObject2 object = mDevice.wait( + Until.findObject(By.res(ANDROID_PACKAGE, resId)), WAIT_TIME_MS); + assertNotNull("Can't find a android object with id: " + resId, object); + return object; + } + private UiObject2 waitForObjectBySelector(BySelector selector) { final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS); assertNotNull("Can't find a view in Launcher, selector: " + selector, object); @@ -1302,6 +1311,11 @@ public final class LauncherInstrumentation { TestProtocol.TEST_INFO_RESPONSE_FIELD); } + boolean overviewShareEnabled() { + return getTestInfo(TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED).getBoolean( + TestProtocol.TEST_INFO_RESPONSE_FIELD); + } + private void disableSensorRotation() { getTestInfo(TestProtocol.REQUEST_MOCK_SENSOR_ROTATION); } diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java new file mode 100644 index 0000000000..a30a404764 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.tapl; + +import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiObject2; + +import com.android.launcher3.testing.TestProtocol; + +/** + * View containing overview actions + */ +public class OverviewActions { + private final UiObject2 mOverviewActions; + private final LauncherInstrumentation mLauncher; + + OverviewActions(UiObject2 overviewActions, LauncherInstrumentation launcherInstrumentation) { + this.mOverviewActions = overviewActions; + this.mLauncher = launcherInstrumentation; + } + + /** + * Clicks screenshot button and closes screenshot ui. + */ + @NonNull + public Overview clickAndDismissScreenshot() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to click screenshot button and exit screenshot ui")) { + UiObject2 screenshot = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_screenshot"); + mLauncher.clickLauncherObject(screenshot); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked screenshot button")) { + UiObject2 closeScreenshot = mLauncher.waitForSystemUiObject( + "global_screenshot_dismiss_image"); + if (mLauncher.getNavigationModel() + != LauncherInstrumentation.NavigationModel.THREE_BUTTON) { + mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, + LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS); + mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, + LauncherInstrumentation.EVENT_TOUCH_UP_TIS); + } + closeScreenshot.click(); + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer( + "dismissed screenshot")) { + return new Overview(mLauncher); + } + } + } + } + + /** + * Click share button, then drags sharesheet down to remove it. + * + * Share is currently hidden behind flag, test is kept in case share becomes a default feature. + * If share is completely removed then remove this test as well. + */ + @NonNull + public Overview clickAndDismissShare() { + if (mLauncher.overviewShareEnabled()) { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to click share button and dismiss sharesheet")) { + UiObject2 share = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_share"); + mLauncher.clickLauncherObject(share); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked share button")) { + mLauncher.waitForAndroidObject("contentPanel"); + mLauncher.getDevice().pressBack(); + try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer( + "dismissed sharesheet")) { + return new Overview(mLauncher); + } + } + } + } + return new Overview(mLauncher); + } + + /** + * Click select button + * + * @return The select mode buttons that are now shown instead of action buttons. + */ + @NonNull + public SelectModeButtons clickSelect() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to click select button")) { + UiObject2 select = mLauncher.waitForObjectInContainer(mOverviewActions, + "action_select"); + mLauncher.clickLauncherObject(select); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked select button")) { + return getSelectModeButtons(); + } + + } + } + + /** + * Gets the Select Mode Buttons. + * + * @return The Select Mode Buttons. + */ + @NonNull + private SelectModeButtons getSelectModeButtons() { + try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer( + "want to get select mode buttons")) { + UiObject2 selectModeButtons = mLauncher.waitForLauncherObject("select_mode_buttons"); + return new SelectModeButtons(selectModeButtons, mLauncher); + } + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java new file mode 100644 index 0000000000..35074184d6 --- /dev/null +++ b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.tapl; + +import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiObject2; + +/** + * View containing select mode buttons + */ +public class SelectModeButtons { + private final UiObject2 mSelectModeButtons; + private final LauncherInstrumentation mLauncher; + + SelectModeButtons(UiObject2 selectModeButtons, + LauncherInstrumentation launcherInstrumentation) { + mSelectModeButtons = selectModeButtons; + mLauncher = launcherInstrumentation; + } + + /** + * Click close button. + */ + @NonNull + public Overview clickClose() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to click close button")) { + UiObject2 close = mLauncher.waitForObjectInContainer(mSelectModeButtons, "close"); + mLauncher.clickLauncherObject(close); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked close button")) { + return new Overview(mLauncher); + } + } + } + + /** + * Click feedback button. + */ + @NonNull + public Background clickFeedback() { + try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck(); + LauncherInstrumentation.Closable c = + mLauncher.addContextLayer("want to click feedback button")) { + UiObject2 feedback = mLauncher.waitForObjectInContainer(mSelectModeButtons, "feedback"); + mLauncher.clickLauncherObject(feedback); + try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer( + "clicked feedback button")) { + return new Background(mLauncher); + } + } + } +} From 354a436f4e96d2ae12740cb1af16b97c37166321 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 25 Jun 2020 15:51:33 -0700 Subject: [PATCH 33/51] Rewrite long swipe resistance ("pullback") logic - Rename "pullback" to "resistance" to reduce confusion. - Remove mDragLengthFactorStartPullback & mDragLengthFactorMaxPullback - Add AnimatorControllerWithResistance, which has 2 controllers, one for the normal shift to overview, then one to apply the resistance when swiping beyond that. - Don't hack animator interpolators/progress; insteaad, allow progress to go > 1 (which will run the separate resistance animator). - Don't start launcher controller separately from window controller; instead, both are controlled by mCurrentShift in updateFinalShift(). - The resistance animation logic is shared by both the active window and launcher (RecentsView). Bug: 149934536 Change-Id: Ib0f9da18e10cc9ddf1a2f82ed767f237c89d3a41 Merged-In: Ib0f9da18e10cc9ddf1a2f82ed767f237c89d3a41 --- .../AppToOverviewAnimationProvider.java | 4 +- .../android/quickstep/BaseSwipeUpHandler.java | 3 +- .../quickstep/BaseSwipeUpHandlerV2.java | 55 ++---- .../quickstep/FallbackActivityInterface.java | 4 +- .../quickstep/LauncherActivityInterface.java | 4 +- .../quickstep/SwipeUpAnimationLogic.java | 35 ++-- .../quickstep/BaseActivityInterface.java | 15 +- .../SwipeUpGestureTutorialController.java | 3 +- .../AnimatorControllerWithResistance.java | 157 ++++++++++++++++++ .../android/launcher3/anim/Interpolators.java | 1 + 10 files changed, 198 insertions(+), 83 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java index 9310685e30..55f542461c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -79,8 +79,8 @@ final class AppToOverviewAnimationProvider> extend BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI( mDeviceState, wasVisible, (controller) -> { - controller.dispatchOnStart(); - controller.getAnimationPlayer().end(); + controller.getNormalController().dispatchOnStart(); + controller.getNormalController().getAnimationPlayer().end(); }); factory.createActivityInterface(RECENTS_LAUNCH_DURATION); factory.setRecentsAttachedToAppWindow(true, false); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index cbef67b84b..c90f70125a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -365,8 +365,7 @@ public abstract class BaseSwipeUpHandler, Q extend */ protected void applyWindowTransform() { if (mWindowTransitionController != null) { - float progress = mCurrentShift.value / mDragLengthFactor; - mWindowTransitionController.setPlayFraction(progress); + mWindowTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor); } if (mRecentsAnimationTargets != null) { if (mRecentsViewScrollLinked) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 758066f8c7..929b11ad66 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -21,7 +21,6 @@ import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; -import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE; @@ -45,7 +44,6 @@ import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHO import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; import android.animation.Animator; -import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.ActivityManager; @@ -67,7 +65,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; -import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.UserEventDispatcher; @@ -80,6 +77,7 @@ import com.android.quickstep.BaseActivityInterface.AnimationFactory; import com.android.quickstep.GestureState.GestureEndTarget; import com.android.quickstep.inputconsumers.OverviewInputConsumer; import com.android.quickstep.util.ActiveGestureLog; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.ShelfPeekAnim; import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState; @@ -181,8 +179,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte private ThumbnailData mTaskSnapshot; // Used to control launcher components throughout the swipe gesture. - private AnimatorPlaybackController mLauncherTransitionController; - private boolean mHasLauncherTransitionControllerStarted; + private AnimatorControllerWithResistance mLauncherTransitionController; private AnimationFactory mAnimationFactory = (t) -> { }; @@ -528,11 +525,11 @@ public abstract class BaseSwipeUpHandlerV2, Q exte /** * We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME - * (it has its own animation) or if we're already animating the current controller. + * (it has its own animation). * @return Whether we can create the launcher controller or update its progress. */ private boolean canCreateNewOrUpdateExistingLauncherTransitionController() { - return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted; + return mGestureState.getEndTarget() != HOME; } @Override @@ -542,10 +539,9 @@ public abstract class BaseSwipeUpHandlerV2, Q exte return result; } - private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) { + private void onAnimatorPlaybackControllerCreated(AnimatorControllerWithResistance anim) { mLauncherTransitionController = anim; - mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor); - mLauncherTransitionController.dispatchOnStart(); + mLauncherTransitionController.getNormalController().dispatchOnStart(); updateLauncherTransitionProgress(); } @@ -582,10 +578,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte || !canCreateNewOrUpdateExistingLauncherTransitionController()) { return; } - // Normalize the progress to 0 to 1, as the animation controller will clamp it to that - // anyway. The controller mimics the drag length factor by applying it to its interpolators. - float progress = mCurrentShift.value / mDragLengthFactor; - mLauncherTransitionController.setPlayFraction(progress); + mLauncherTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor); } /** @@ -1028,31 +1021,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte windowAnim.start(); mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); } - // Always play the entire launcher animation when going home, since it is separate from - // the animation that has been controlled thus far. - if (mGestureState.getEndTarget() == HOME) { - start = 0; - } - - // We want to use the same interpolator as the window, but need to adjust it to - // interpolate over the remaining progress (end - start). - TimeInterpolator adjustedInterpolator = Interpolators.mapToProgress( - interpolator, start, end); - if (mLauncherTransitionController == null) { - return; - } - if (start == end || duration <= 0) { - mLauncherTransitionController.dispatchSetInterpolator(t -> end); - } else { - mLauncherTransitionController.dispatchSetInterpolator(adjustedInterpolator); - } - mLauncherTransitionController.getAnimationPlayer().setDuration(Math.max(0, duration)); - - if (UNSTABLE_SPRINGS.get()) { - mLauncherTransitionController.dispatchOnStart(); - } - mLauncherTransitionController.getAnimationPlayer().start(); - mHasLauncherTransitionControllerStarted = true; } private void computeRecentsScrollIfInvisible() { @@ -1173,10 +1141,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte private void cancelCurrentAnimation() { mCanceled = true; mCurrentShift.cancelAnimation(); - if (mLauncherTransitionController != null && mLauncherTransitionController - .getAnimationPlayer().isStarted()) { - mLauncherTransitionController.getAnimationPlayer().cancel(); - } } private void invalidateHandler() { @@ -1202,7 +1166,10 @@ public abstract class BaseSwipeUpHandlerV2, Q exte private void endLauncherTransitionController() { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); if (mLauncherTransitionController != null) { - mLauncherTransitionController.getAnimationPlayer().end(); + // End the animation, but stay at the same visual progress. + mLauncherTransitionController.getNormalController().dispatchSetInterpolator( + t -> Utilities.boundToRange(mCurrentShift.value, 0, 1)); + mLauncherTransitionController.getNormalController().getAnimationPlayer().end(); mLauncherTransitionController = null; } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java index d1da0c1c10..3898f0b0ca 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java @@ -27,11 +27,11 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; -import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.fallback.RecentsState; import com.android.quickstep.util.ActivityInitListener; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; @@ -84,7 +84,7 @@ public final class FallbackActivityInterface extends /** 6 */ @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, - boolean activityVisible, Consumer callback) { + boolean activityVisible, Consumer callback) { DefaultAnimationFactory factory = new DefaultAnimationFactory(callback); factory.initUI(); return factory; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java index 7cd49fe18d..cd4be1895b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java @@ -39,7 +39,6 @@ import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.allapps.DiscoveryBounce; -import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.appprediction.PredictionUiStateManager; import com.android.launcher3.statehandlers.DepthController; @@ -50,6 +49,7 @@ import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.util.ActivityInitListener; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState; import com.android.quickstep.views.RecentsView; @@ -119,7 +119,7 @@ public final class LauncherActivityInterface extends @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, - boolean activityVisible, Consumer callback) { + boolean activityVisible, Consumer callback) { notifyRecentsOfOrientation(deviceState.getRotationTouchHelper()); DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) { @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java index e54a21c073..137f8091ad 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -16,7 +16,7 @@ package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; -import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.LINEAR; import android.animation.Animator; import android.content.Context; @@ -24,7 +24,6 @@ import android.graphics.Matrix; import android.graphics.Matrix.ScaleToFit; import android.graphics.Rect; import android.graphics.RectF; -import android.view.animation.Interpolator; import androidx.annotation.NonNull; import androidx.annotation.UiThread; @@ -35,6 +34,7 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.touch.PagedOrientationHandler; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; @@ -45,7 +45,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. public abstract class SwipeUpAnimationLogic { protected static final Rect TEMP_RECT = new Rect(); - private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL; protected DeviceProfile mDp; @@ -66,12 +65,8 @@ public abstract class SwipeUpAnimationLogic { protected int mTransitionDragLength; // How much further we can drag past recents, as a factor of mTransitionDragLength. protected float mDragLengthFactor = 1; - // Start resisting when swiping past this factor of mTransitionDragLength. - private float mDragLengthFactorStartPullback = 1f; - // This is how far down we can scale down, where 0f is full screen and 1f is recents. - private float mDragLengthFactorMaxPullback = 1f; - protected AnimatorPlaybackController mWindowTransitionController; + protected AnimatorControllerWithResistance mWindowTransitionController; public SwipeUpAnimationLogic(Context context, RecentsAnimationDeviceState deviceState, GestureState gestureState, TransformParams transformParams) { @@ -97,19 +92,16 @@ public abstract class SwipeUpAnimationLogic { if (mDeviceState.isFullyGesturalNavMode()) { // We can drag all the way to the top of the screen. mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength; - - float startScale = mTaskViewSimulator.getFullScreenScale(); - // Start pulling back when RecentsView scale is 0.75f, and let it go down to 0.5f. - mDragLengthFactorStartPullback = (0.75f - startScale) / (1 - startScale); - mDragLengthFactorMaxPullback = (0.5f - startScale) / (1 - startScale); } else { - mDragLengthFactor = 1; - mDragLengthFactorStartPullback = mDragLengthFactorMaxPullback = 1; + mDragLengthFactor = 1 + AnimatorControllerWithResistance.TWO_BUTTON_EXTRA_DRAG_FACTOR; } PendingAnimation pa = new PendingAnimation(mTransitionDragLength * 2); - mTaskViewSimulator.addAppToOverviewAnim(pa, t -> t * mDragLengthFactor); - mWindowTransitionController = pa.createPlaybackController(); + mTaskViewSimulator.addAppToOverviewAnim(pa, LINEAR); + AnimatorPlaybackController normalController = pa.createPlaybackController(); + mWindowTransitionController = AnimatorControllerWithResistance.createForRecents( + normalController, mContext, mTaskViewSimulator.getOrientationState(), + mDp, mTaskViewSimulator.recentsViewScale, AnimatedFloat.VALUE); } @UiThread @@ -122,13 +114,6 @@ public abstract class SwipeUpAnimationLogic { } else { float translation = Math.max(displacement, 0); shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength; - if (shift > mDragLengthFactorStartPullback) { - float pullbackProgress = Utilities.getProgress(shift, - mDragLengthFactorStartPullback, mDragLengthFactor); - pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress); - shift = mDragLengthFactorStartPullback + pullbackProgress - * (mDragLengthFactorMaxPullback - mDragLengthFactorStartPullback); - } } mCurrentShift.updateValue(shift); @@ -183,7 +168,7 @@ public abstract class SwipeUpAnimationLogic { HomeAnimationFactory homeAnimationFactory) { final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); - mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor); + mCurrentShift.updateValue(startProgress); mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress)); RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect()); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index df8f31d2c0..31630ff1bc 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -52,6 +52,7 @@ import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.WindowBounds; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.util.ActivityInitListener; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.ShelfPeekAnim; import com.android.quickstep.util.SplitScreenBounds; import com.android.quickstep.views.RecentsView; @@ -106,7 +107,7 @@ public abstract class BaseActivityInterface callback); + boolean activityVisible, Consumer callback); public abstract ActivityInitListener createActivityInitListener( Predicate onInitListener); @@ -319,11 +320,11 @@ public abstract class BaseActivityInterface mCallback; + private final Consumer mCallback; private boolean mIsAttachedToWindow; - DefaultAnimationFactory(Consumer callback) { + DefaultAnimationFactory(Consumer callback) { mCallback = callback; mActivity = getCreatedActivity(); @@ -351,7 +352,13 @@ public abstract class BaseActivityInterface mActivity.getStateManager().goToState( controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState, false)); - mCallback.accept(controller); + + RecentsView recentsView = mActivity.getOverviewPanel(); + AnimatorControllerWithResistance controllerWithResistance = + AnimatorControllerWithResistance.createForRecents(controller, mActivity, + recentsView.getPagedViewOrientedState(), mActivity.getDeviceProfile(), + recentsView, RECENTS_SCALE_PROPERTY); + mCallback.accept(controllerWithResistance); // Creating the activity controller animation sometimes reapplies the launcher state // (because we set the animation as the current state animation), so we reapply the diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java index 4110b33d24..a15731400e 100644 --- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java @@ -184,8 +184,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController { @Override public void updateFinalShift() { - float progress = mCurrentShift.value / mDragLengthFactor; - mWindowTransitionController.setPlayFraction(progress); + mWindowTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor); mTaskViewSimulator.apply(mTransformParams); } diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java new file mode 100644 index 0000000000..d58329ab0b --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS; + +import android.animation.TimeInterpolator; +import android.content.Context; +import android.graphics.PointF; +import android.graphics.Rect; +import android.util.FloatProperty; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Utilities; +import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.anim.PendingAnimation; +import com.android.quickstep.LauncherActivityInterface; +import com.android.quickstep.SysUINavigationMode; + +/** + * Controls an animation that can go beyond progress = 1, at which point resistance should be + * applied. Internally, this is a wrapper around 2 {@link AnimatorPlaybackController}s, one that + * runs from progress 0 to 1 like normal, then one that seamlessly continues that animation but + * starts applying resistance as well. + */ +public class AnimatorControllerWithResistance { + + /** + * How much farther we can drag past overview in 2-button mode, as a factor of the distance + * it takes to drag from an app to overview. + */ + public static final float TWO_BUTTON_EXTRA_DRAG_FACTOR = 0.25f; + + /** + * Start slowing down the rate of scaling down when recents view is smaller than this scale. + */ + private static final float RECENTS_SCALE_START_RESIST = 0.75f; + + /** + * Recents view will reach this scale at the very end of the drag. + */ + private static final float RECENTS_SCALE_MAX_RESIST = 0.5f; + + private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL; + + private final AnimatorPlaybackController mNormalController; + private final AnimatorPlaybackController mResistanceController; + + // Initialize to -1 so the first 0 gets applied. + private float mLastNormalProgress = -1; + private float mLastResistProgress; + + public AnimatorControllerWithResistance(AnimatorPlaybackController normalController, + AnimatorPlaybackController resistanceController) { + mNormalController = normalController; + mResistanceController = resistanceController; + } + + public AnimatorPlaybackController getNormalController() { + return mNormalController; + } + + /** + * Applies the current progress of the animation. + * @param progress From 0 to maxProgress, where 1 is the target we are animating towards. + * @param maxProgress > 1, this is where the resistance will be applied. + */ + public void setProgress(float progress, float maxProgress) { + float normalProgress = Utilities.boundToRange(progress, 0, 1); + if (normalProgress != mLastNormalProgress) { + mLastNormalProgress = normalProgress; + mNormalController.setPlayFraction(normalProgress); + } + if (maxProgress <= 1) { + return; + } + float resistProgress = progress <= 1 ? 0 : Utilities.getProgress(progress, 1, maxProgress); + if (resistProgress != mLastResistProgress) { + mLastResistProgress = resistProgress; + mResistanceController.setPlayFraction(resistProgress); + } + } + + /** + * Applies resistance to recents when swiping up past its target position. + * @param normalController The controller to run from 0 to 1 before this resistance applies. + * @param context Used to compute start and end values. + * @param recentsOrientedState Used to compute start and end values. + * @param dp Used to compute start and end values. + * @param scaleTarget The target for the scaleProperty. + * @param scaleProperty Animate the value to change the scale of the window/recents view. + */ + public static AnimatorControllerWithResistance createForRecents( + AnimatorPlaybackController normalController, Context context, + RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget, + FloatProperty scaleProperty) { + Rect startRect = new Rect(); + LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect, + recentsOrientedState.getOrientationHandler()); + long distanceToCover = startRect.bottom; + boolean isTwoButtonMode = SysUINavigationMode.getMode(context) == TWO_BUTTONS; + if (isTwoButtonMode) { + // We can only drag a small distance past overview, not to the top of the screen. + distanceToCover = (long) + ((dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR); + } + PendingAnimation resistAnim = new PendingAnimation(distanceToCover * 2); + + PointF pivot = new PointF(); + float fullscreenScale = recentsOrientedState.getFullScreenScaleAndPivot( + startRect, dp, pivot); + float startScale = 1; + float prevScaleRate = (fullscreenScale - startScale) / (dp.heightPx - startRect.bottom); + // This is what the scale would be at the end of the drag if we didn't apply resistance. + float endScale = startScale - prevScaleRate * distanceToCover; + final TimeInterpolator scaleInterpolator; + if (isTwoButtonMode) { + // We are bounded by the distance of the drag, so we don't need to apply resistance. + scaleInterpolator = LINEAR; + } else { + // Create an interpolator that resists the scale so the scale doesn't get smaller than + // RECENTS_SCALE_MAX_RESIST. + float startResist = Utilities.getProgress(RECENTS_SCALE_START_RESIST, startScale, + endScale); + float maxResist = Utilities.getProgress(RECENTS_SCALE_MAX_RESIST, startScale, endScale); + scaleInterpolator = t -> { + if (t < startResist) { + return t; + } + float resistProgress = Utilities.getProgress(t, startResist, 1); + resistProgress = RECENTS_SCALE_RESIST_INTERPOLATOR.getInterpolation(resistProgress); + return startResist + resistProgress * (maxResist - startResist); + }; + } + resistAnim.addFloat(scaleTarget, scaleProperty, startScale, endScale, + scaleInterpolator); + + AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController(); + return new AnimatorControllerWithResistance(normalController, resistanceController); + } + +} diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java index 860ccebef4..6ad43ea1e4 100644 --- a/src/com/android/launcher3/anim/Interpolators.java +++ b/src/com/android/launcher3/anim/Interpolators.java @@ -198,6 +198,7 @@ public class Interpolators { public OvershootParams(float startProgress, float overshootPastProgress, float endProgress, float velocityPxPerMs, int totalDistancePx, Context context) { velocityPxPerMs = Math.abs(velocityPxPerMs); + overshootPastProgress = Math.max(overshootPastProgress, startProgress); start = startProgress; int startPx = (int) (start * totalDistancePx); // Overshoot by about half a frame. From 3f8d868110b426e40e09ece8b305fd84c1dde60c Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 4 Aug 2020 14:01:27 -0700 Subject: [PATCH 34/51] Defer recreation until resumed - Temporarily work around issue with activity recreation while started but not resumed by deferring recreating the activity on theme change until after launcher has resumed. Bug: 162812884 Test: Switch dark mode via QuickSettings, Settings Test: Change system theme Change-Id: Ifbc0d538907a30d6b23176cd67353a81b6f8c617 --- src/com/android/launcher3/BaseDraggingActivity.java | 13 ++++++++++++- src/com/android/launcher3/Launcher.java | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index f2a5c656ff..833ce1501d 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -42,6 +42,7 @@ import android.widget.Toast; import androidx.annotation.Nullable; +import com.android.launcher3.Launcher.OnResumeCallback; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.InstanceIdSequence; @@ -108,10 +109,20 @@ public abstract class BaseDraggingActivity extends BaseActivity private void updateTheme() { if (mThemeRes != Themes.getActivityThemeRes(this)) { - recreate(); + // Workaround (b/162812884): The system currently doesn't allow recreating an activity + // when it is not resumed, in such a case defer recreation until it is possible + if (hasBeenResumed()) { + recreate(); + } else { + addOnResumeCallback(this::recreate); + } } } + protected void addOnResumeCallback(OnResumeCallback callback) { + // To be overridden + } + @Override public void onActionModeStarted(ActionMode mode) { super.onActionModeStarted(mode); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4675362f64..03e4b06f8f 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1943,6 +1943,7 @@ public class Launcher extends StatefulActivity implements Launche return result; } + @Override public void addOnResumeCallback(OnResumeCallback callback) { mOnResumeCallbacks.add(callback); } From 3af714f052d183aa31f22eee3afeecb94ec552db Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 5 Aug 2020 13:32:37 -0700 Subject: [PATCH 35/51] Remove overscroll on running task when it's not attached to RecentsView This allows the running task to follow the finger freely until motion pause is detected (or when trying to quick switch in a direciton that has no tasks, as RecentsView is still attached until you swipe up). Bug: 149934536 Change-Id: If68166e962af9f28c56017838f720e15ddb96560 --- .../com/android/quickstep/BaseSwipeUpHandlerV2.java | 10 ++++++++++ .../src/com/android/quickstep/views/RecentsView.java | 9 ++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 929b11ad66..ed33532e6d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -488,6 +488,16 @@ public abstract class BaseSwipeUpHandlerV2, Q exte recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask; } mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate); + + // Reapply window transform throughout the attach animation, as the animation affects how + // much the window is bound by overscroll (vs moving freely). + if (animate) { + ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1); + reapplyWindowTransformAnim.addUpdateListener(anim -> applyWindowTransform()); + reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start(); + } else { + applyWindowTransform(); + } } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 857a020698..26e6055174 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -2290,7 +2290,14 @@ public abstract class RecentsView extends PagedView if (pageIndex == -1) { return 0; } - return getScrollForPage(pageIndex) - mOrientationHandler.getPrimaryScroll(this); + // Unbound the scroll (due to overscroll) if the adjacent tasks are offset away from it. + // This allows the page to move freely, given there's no visual indication why it shouldn't. + int boundedScroll = mOrientationHandler.getPrimaryScroll(this); + int unboundedScroll = getUnboundedScroll(); + float unboundedProgress = mAdjacentPageOffset; + int scroll = Math.round(unboundedScroll * unboundedProgress + + boundedScroll * (1 - unboundedProgress)); + return getScrollForPage(pageIndex) - scroll; } public Consumer getEventDispatcher(float navbarRotation) { From b8b3e957a6049ba0cd3ed48623a1666bae80b25e Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 5 Aug 2020 18:43:53 -0700 Subject: [PATCH 36/51] Fix TaskViewTouchController success progress to match haptic We use the interpolated progress of the animation contoller target to determine success, but only the child animation had the interpolator set. Updating the parent to use the same interpolator ensures getInterpolatedProgress() returns the same one used to play the haptic. Fixes: 161536946 Change-Id: Ibc2aef67f53efa01f2b185cf03140bad4bb5c421 --- .../touchcontrollers/TaskViewTouchController.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index 0ee5d047c6..7bae2e5d86 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -25,6 +25,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.view.MotionEvent; import android.view.View; +import android.view.animation.Interpolator; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; @@ -206,14 +207,19 @@ public abstract class TaskViewTouchController long maxDuration = 2 * secondaryLayerDimension; int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl); int secondaryTaskDimension = orientationHandler.getSecondaryDimension(mTaskBeingDragged); + // The interpolator controlling the most prominent visual movement. We use this to determine + // whether we passed SUCCESS_TRANSITION_PROGRESS. + final Interpolator currentInterpolator; if (goingUp) { + currentInterpolator = Interpolators.LINEAR; mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged, true /* animateTaskView */, true /* removeTask */, maxDuration); mEndDisplacement = -secondaryTaskDimension; } else { + currentInterpolator = Interpolators.ZOOM_IN; mPendingAnimation = mRecentsView.createTaskLaunchAnimation( - mTaskBeingDragged, maxDuration, Interpolators.ZOOM_IN); + mTaskBeingDragged, maxDuration, currentInterpolator); // Since the thumbnail is what is filling the screen, based the end displacement on it. View thumbnailView = mTaskBeingDragged.getThumbnail(); @@ -228,6 +234,9 @@ public abstract class TaskViewTouchController } mCurrentAnimation = mPendingAnimation.createPlaybackController() .setOnCancelRunnable(this::clearState); + // Setting this interpolator doesn't affect the visual motion, but is used to determine + // whether we successfully reached the target state in onDragEnd(). + mCurrentAnimation.getTarget().setInterpolator(currentInterpolator); onUserControlledAnimationCreated(mCurrentAnimation); mCurrentAnimation.getTarget().addListener(this); mCurrentAnimation.dispatchOnStart(); From d00340f7a24d11db58954298eb979e6c8ac0438f Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 6 Aug 2020 14:28:13 -0700 Subject: [PATCH 37/51] Fixing cutouts insets not clipped properly during swipeup for rotated activities Bug: 161939759 Change-Id: Ia55f938fdc51e2813c205d7d13d5f1bf852c9bb2 --- .../android/quickstep/views/TaskThumbnailView.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index a8d6442135..fad64271f3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -479,17 +479,18 @@ public class TaskThumbnailView extends View implements PluginListener Date: Thu, 6 Aug 2020 15:04:51 -0700 Subject: [PATCH 38/51] Fix adjacent page offset in landscape orientation Before, the adjacent tasks were coming in from the top and bottom of the screen rather than the sides. Bug: 149934536 Change-Id: Id6e57dcbc1967d70869df06068d25717de116934 --- .../src/com/android/quickstep/views/RecentsView.java | 4 +++- .../android/launcher3/touch/LandscapePagedViewHandler.java | 5 +++++ src/com/android/launcher3/touch/PagedOrientationHandler.java | 1 + .../android/launcher3/touch/PortraitPagedViewHandler.java | 5 +++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 857a020698..5ce6f6ba60 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -1853,7 +1853,9 @@ public abstract class RecentsView extends PagedView : i < modalMidpoint ? modalLeftOffsetSize : modalRightOffsetSize; - getChildAt(i).setTranslationX(translation + modalTranslation); + float totalTranslation = translation + modalTranslation; + mOrientationHandler.getPrimaryViewTranslate().set(getChildAt(i), + totalTranslation * mOrientationHandler.getPrimaryTranslationDirectionFactor()); } updateCurveProperties(); } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index 1aaa608657..b2740fab3e 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -214,6 +214,11 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { return HORIZONTAL; } + @Override + public int getPrimaryTranslationDirectionFactor() { + return -1; + } + @Override public int getTaskDismissDirectionFactor() { return 1; diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index f88cdb3b0d..4b17c79a33 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -74,6 +74,7 @@ public interface PagedOrientationHandler { int getScrollOffsetStart(View view, Rect insets); int getScrollOffsetEnd(View view, Rect insets); SingleAxisSwipeDetector.Direction getOppositeSwipeDirection(); + int getPrimaryTranslationDirectionFactor(); int getTaskDismissDirectionFactor(); int getTaskDragDisplacementFactor(boolean isRtl); ChildBounds getChildBounds(View child, int childStart, int pageCenter, boolean layoutChild); diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index f18b109515..8f1c487f8a 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -211,6 +211,11 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { return VERTICAL; } + @Override + public int getPrimaryTranslationDirectionFactor() { + return 1; + } + @Override public int getTaskDismissDirectionFactor() { return -1; From ce8b2b51800e42fc61c14f516ec563c3561b7adb Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 1 Jul 2020 17:25:28 -0700 Subject: [PATCH 39/51] Add translation component to swipe up resistance Now recents view follows your finger all the way to the top of the screen. Specifically, your finger tracks the bottom of the window until resistance starts (when RecentsView is at 75% scale), then we add translation to compensate for the slower rate of scaling down, such that your finger slips to the top of the window by the time it reaches the top of the screen. Also reset this translation back to 0 in the state handlers. Bug: 149934536 Fixes: 158701272 Change-Id: Iaee58da758d422f0173c29d002f5c451ce0c1809 --- .../quickstep/SwipeUpAnimationLogic.java | 3 ++- .../FallbackRecentsStateController.java | 4 +++ .../quickstep/fallback/RecentsState.java | 1 - .../quickstep/util/TaskViewSimulator.java | 5 +++- .../android/quickstep/views/RecentsView.java | 25 ++++++++++++++++++- .../BaseRecentsViewStateController.java | 5 ++++ .../quickstep/BaseActivityInterface.java | 4 ++- .../AnimatorControllerWithResistance.java | 23 +++++++++++++++-- .../touch/LandscapePagedViewHandler.java | 8 ++++-- .../touch/PagedOrientationHandler.java | 3 ++- .../touch/PortraitPagedViewHandler.java | 8 ++++-- .../touch/SeascapePagedViewHandler.java | 2 +- 12 files changed, 78 insertions(+), 13 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java index 137f8091ad..2963b6ce18 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -101,7 +101,8 @@ public abstract class SwipeUpAnimationLogic { AnimatorPlaybackController normalController = pa.createPlaybackController(); mWindowTransitionController = AnimatorControllerWithResistance.createForRecents( normalController, mContext, mTaskViewSimulator.getOrientationState(), - mDp, mTaskViewSimulator.recentsViewScale, AnimatedFloat.VALUE); + mDp, mTaskViewSimulator.recentsViewScale, AnimatedFloat.VALUE, + mTaskViewSimulator.recentsViewSecondaryTranslation, AnimatedFloat.VALUE); } @UiThread diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 163c23268b..24a761066a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -19,6 +19,7 @@ import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK; import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; @@ -26,6 +27,7 @@ import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; +import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.PropertySetter; @@ -86,6 +88,8 @@ public class FallbackRecentsStateController implements StateHandler { return new float[] { NO_SCALE, NO_OFFSET }; } - private static class ModalState extends RecentsState { public ModalState(int id, int flags) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java index c5918fed84..db64464a61 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java @@ -90,6 +90,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { // RecentsView properties public final AnimatedFloat recentsViewScale = new AnimatedFloat(); public final AnimatedFloat fullScreenProgress = new AnimatedFloat(); + public final AnimatedFloat recentsViewSecondaryTranslation = new AnimatedFloat(); private final ScrollState mScrollState = new ScrollState(); // Cached calculations @@ -274,8 +275,10 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { mOrientationState.getOrientationHandler().set( mMatrix, MATRIX_POST_TRANSLATE, mScrollState.scroll); - // Apply recensView matrix + // Apply RecentsView matrix mMatrix.postScale(recentsViewScale.value, recentsViewScale.value, mPivot.x, mPivot.y); + mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE, + recentsViewSecondaryTranslation.value); applyWindowToHomeRotation(mMatrix); // Crop rect is the inverse of thumbnail matrix diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 5ce6f6ba60..6ebf8ad46a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -210,6 +210,19 @@ public abstract class RecentsView extends PagedView } }; + public static final FloatProperty TASK_SECONDARY_TRANSLATION = + new FloatProperty("taskSecondaryTranslation") { + @Override + public void setValue(RecentsView recentsView, float v) { + recentsView.setTaskViewsSecondaryTranslation(v); + } + + @Override + public Float get(RecentsView recentsView) { + return recentsView.mTaskViewsSecondaryTranslation; + } + }; + /** Same as normal SCALE_PROPERTY, but also updates page offsets that depend on this scale. */ public static final FloatProperty RECENTS_SCALE_PROPERTY = new FloatProperty("recentsScale") { @@ -219,6 +232,7 @@ public abstract class RecentsView extends PagedView view.setScaleY(scale); view.mLastComputedTaskPushOutDistance = null; view.updatePageOffsets(); + view.setTaskViewsSecondaryTranslation(view.mTaskViewsSecondaryTranslation); } @Override @@ -269,6 +283,7 @@ public abstract class RecentsView extends PagedView protected boolean mFreezeViewVisibility; private float mAdjacentPageOffset = 0; + private float mTaskViewsSecondaryTranslation = 0; /** * TODO: Call reloadIdNeeded in onTaskStackChanged. @@ -1391,7 +1406,7 @@ public abstract class RecentsView extends PagedView FloatProperty secondaryViewTranslate = mOrientationHandler.getSecondaryViewTranslate(); int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView); - int verticalFactor = mOrientationHandler.getTaskDismissDirectionFactor(); + int verticalFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor(); ResourceProvider rp = DynamicResource.provider(mActivity); SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_START) @@ -1908,6 +1923,14 @@ public abstract class RecentsView extends PagedView return distanceToOffscreen * offsetProgress; } + private void setTaskViewsSecondaryTranslation(float translation) { + mTaskViewsSecondaryTranslation = translation; + for (int i = 0; i < getTaskViewCount(); i++) { + TaskView task = getTaskViewAt(i); + mOrientationHandler.getSecondaryViewTranslate().set(task, translation / getScaleY()); + } + } + /** * TODO: Do not assume motion across X axis for adjacent page */ diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index 6e120e8bd8..1b8e244ac1 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -24,11 +24,13 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MO import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK; import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; +import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import android.util.FloatProperty; @@ -63,6 +65,7 @@ public abstract class BaseRecentsViewStateController float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher); RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]); ADJACENT_PAGE_OFFSET.set(mRecentsView, scaleAndOffset[1]); + TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f); getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0); OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim(); @@ -97,6 +100,8 @@ public abstract class BaseRecentsViewStateController config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR)); setter.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1], config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR)); + setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f, + config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR)); setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0, config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 31630ff1bc..bdf525dcd0 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -28,6 +28,7 @@ import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_REC import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; +import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import android.animation.Animator; import android.annotation.TargetApi; @@ -357,7 +358,8 @@ public abstract class BaseActivityInterface AnimatorControllerWithResistance createForRecents( + public static AnimatorControllerWithResistance createForRecents( AnimatorPlaybackController normalController, Context context, RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget, - FloatProperty scaleProperty) { + FloatProperty scaleProperty, TRANSLATION translationTarget, + FloatProperty translationProperty) { Rect startRect = new Rect(); LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect, recentsOrientedState.getOrientationHandler()); @@ -150,6 +156,19 @@ public class AnimatorControllerWithResistance { resistAnim.addFloat(scaleTarget, scaleProperty, startScale, endScale, scaleInterpolator); + if (!isTwoButtonMode) { + // Compute where the task view would be based on the end scale, if we didn't translate. + RectF endRectF = new RectF(startRect); + Matrix temp = new Matrix(); + temp.setScale(RECENTS_SCALE_MAX_RESIST, RECENTS_SCALE_MAX_RESIST, pivot.x, pivot.y); + temp.mapRect(endRectF); + // Translate such that the task view touches the top of the screen when drag does. + float endTranslation = endRectF.top * recentsOrientedState.getOrientationHandler() + .getSecondaryTranslationDirectionFactor(); + resistAnim.addFloat(translationTarget, translationProperty, 0, endTranslation, + RECENTS_TRANSLATE_RESIST_INTERPOLATOR); + } + AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController(); return new AnimatorControllerWithResistance(normalController, resistanceController); } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index b2740fab3e..4fd163360b 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -107,6 +107,11 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { action.call(target, 0, param); } + @Override + public void setSecondary(T target, Float2DAction action, float param) { + action.call(target, param, 0); + } + @Override public float getPrimaryDirection(MotionEvent event, int pointerIndex) { return event.getY(pointerIndex); @@ -219,8 +224,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { return -1; } - @Override - public int getTaskDismissDirectionFactor() { + public int getSecondaryTranslationDirectionFactor() { return 1; } diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index 4b17c79a33..c0d488bb45 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -57,6 +57,7 @@ public interface PagedOrientationHandler { void set(T target, Int2DAction action, int param); void set(T target, Float2DAction action, float param); + void setSecondary(T target, Float2DAction action, float param); float getPrimaryDirection(MotionEvent event, int pointerIndex); float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId); int getMeasuredSize(View view); @@ -75,7 +76,7 @@ public interface PagedOrientationHandler { int getScrollOffsetEnd(View view, Rect insets); SingleAxisSwipeDetector.Direction getOppositeSwipeDirection(); int getPrimaryTranslationDirectionFactor(); - int getTaskDismissDirectionFactor(); + int getSecondaryTranslationDirectionFactor(); int getTaskDragDisplacementFactor(boolean isRtl); ChildBounds getChildBounds(View child, int childStart, int pageCenter, boolean layoutChild); void setMaxScroll(AccessibilityEvent event, int maxScroll); diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 8f1c487f8a..9e53e5f8ec 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -104,6 +104,11 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { action.call(target, param, 0); } + @Override + public void setSecondary(T target, Float2DAction action, float param) { + action.call(target, 0, param); + } + @Override public float getPrimaryDirection(MotionEvent event, int pointerIndex) { return event.getX(pointerIndex); @@ -216,8 +221,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { return 1; } - @Override - public int getTaskDismissDirectionFactor() { + public int getSecondaryTranslationDirectionFactor() { return -1; } diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java index e91f16d71a..7153452f23 100644 --- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java @@ -28,7 +28,7 @@ import com.android.launcher3.Utilities; public class SeascapePagedViewHandler extends LandscapePagedViewHandler { @Override - public int getTaskDismissDirectionFactor() { + public int getSecondaryTranslationDirectionFactor() { return -1; } From d6a1063f258452b5f34dcad22dc416cc03c16dd4 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 6 Jul 2020 17:26:39 -0700 Subject: [PATCH 40/51] Add swipe up resistance to quick switch from home Bug: 149934536 Change-Id: I1b355a16d972f94d541231449ef323a41861a3e6 --- .../NoButtonQuickSwitchTouchController.java | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java index 821ada400e..5c9fd4705b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java @@ -22,7 +22,6 @@ import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS; import static com.android.launcher3.LauncherState.QUICK_SWITCH; import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD; import static com.android.launcher3.anim.Interpolators.ACCEL_0_75; -import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL_5; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; @@ -47,6 +46,7 @@ import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; +import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; import android.animation.Animator; @@ -74,7 +74,9 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; import com.android.launcher3.util.VibratorWrapper; +import com.android.quickstep.AnimatedFloat; import com.android.quickstep.SystemUiProxy; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.ShelfPeekAnim; @@ -90,16 +92,17 @@ public class NoButtonQuickSwitchTouchController implements TouchController, BothAxesSwipeDetector.Listener, MotionPauseDetector.OnMotionPauseListener { /** The minimum progress of the scale/translationY animation until drag end. */ - private static final float Y_ANIM_MIN_PROGRESS = 0.15f; + private static final float Y_ANIM_MIN_PROGRESS = 0.25f; private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_5; private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75; - private static final Interpolator SCALE_DOWN_INTERPOLATOR = DEACCEL; + private static final Interpolator SCALE_DOWN_INTERPOLATOR = LINEAR; private final BaseQuickstepLauncher mLauncher; private final BothAxesSwipeDetector mSwipeDetector; private final ShelfPeekAnim mShelfPeekAnim; private final float mXRange; private final float mYRange; + private final float mMaxYProgress; private final MotionPauseDetector mMotionPauseDetector; private final float mMotionPauseMinDisplacement; private final LauncherRecentsView mRecentsView; @@ -113,7 +116,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, // and the other two to set overview properties based on x and y progress. private AnimatorPlaybackController mNonOverviewAnim; private AnimatorPlaybackController mXOverviewAnim; - private AnimatorPlaybackController mYOverviewAnim; + private AnimatedFloat mYOverviewAnim; public NoButtonQuickSwitchTouchController(BaseQuickstepLauncher launcher) { mLauncher = launcher; @@ -123,6 +126,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, mXRange = mLauncher.getDeviceProfile().widthPx / 2f; mYRange = LayoutUtils.getShelfTrackingDistance( mLauncher, mLauncher.getDeviceProfile(), mRecentsView.getPagedOrientationHandler()); + mMaxYProgress = mLauncher.getDeviceProfile().heightPx / mYRange; mMotionPauseDetector = new MotionPauseDetector(mLauncher); mMotionPauseMinDisplacement = mLauncher.getResources().getDimension( R.dimen.motion_pause_detector_min_displacement_from_app); @@ -270,8 +274,18 @@ public class NoButtonQuickSwitchTouchController implements TouchController, SCALE_DOWN_INTERPOLATOR); yAnim.setFloat(mRecentsView, FULLSCREEN_PROGRESS, toState.getOverviewFullscreenProgress(), SCALE_DOWN_INTERPOLATOR); - mYOverviewAnim = yAnim.createPlaybackController(); - mYOverviewAnim.dispatchOnStart(); + AnimatorPlaybackController yNormalController = yAnim.createPlaybackController(); + AnimatorControllerWithResistance yAnimWithResistance = AnimatorControllerWithResistance + .createForRecents(yNormalController, mLauncher, + mRecentsView.getPagedViewOrientedState(), mLauncher.getDeviceProfile(), + mRecentsView, RECENTS_SCALE_PROPERTY, mRecentsView, + TASK_SECONDARY_TRANSLATION); + mYOverviewAnim = new AnimatedFloat(() -> { + if (mYOverviewAnim != null) { + yAnimWithResistance.setProgress(mYOverviewAnim.value, mMaxYProgress); + } + }); + yNormalController.dispatchOnStart(); } @Override @@ -307,7 +321,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, mXOverviewAnim.setPlayFraction(xProgress); } if (mYOverviewAnim != null) { - mYOverviewAnim.setPlayFraction(yProgress); + mYOverviewAnim.updateValue(yProgress); } return true; } @@ -354,9 +368,11 @@ public class NoButtonQuickSwitchTouchController implements TouchController, } else if (verticalFling) { targetState = velocity.y > 0 ? QUICK_SWITCH : NORMAL; } else { - // If user isn't flinging, just snap to the closest state based on x progress. + // If user isn't flinging, just snap to the closest state. boolean passedHorizontalThreshold = mXOverviewAnim.getInterpolatedProgress() > 0.5f; - targetState = passedHorizontalThreshold ? QUICK_SWITCH : NORMAL; + boolean passedVerticalThreshold = mYOverviewAnim.value > 1f; + targetState = passedHorizontalThreshold && !passedVerticalThreshold + ? QUICK_SWITCH : NORMAL; } // Animate the various components to the target state. @@ -375,9 +391,9 @@ public class NoButtonQuickSwitchTouchController implements TouchController, boolean flingUpToNormal = verticalFling && velocity.y < 0 && targetState == NORMAL; - float yProgress = mYOverviewAnim.getProgressFraction(); + float yProgress = mYOverviewAnim.value; float startYProgress = Utilities.boundToRange(yProgress - - velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, 1f); + - velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, mMaxYProgress); final float endYProgress; if (flingUpToNormal) { endYProgress = 1; @@ -387,12 +403,11 @@ public class NoButtonQuickSwitchTouchController implements TouchController, } else { endYProgress = 0; } - long yDuration = BaseSwipeDetector.calculateDuration(velocity.y, - Math.abs(endYProgress - startYProgress)); - ValueAnimator yOverviewAnim = mYOverviewAnim.getAnimationPlayer(); - yOverviewAnim.setFloatValues(startYProgress, endYProgress); + float yDistanceToCover = Math.abs(endYProgress - startYProgress) * mYRange; + long yDuration = (long) (yDistanceToCover / Math.max(1f, Math.abs(velocity.y))); + ValueAnimator yOverviewAnim = mYOverviewAnim.animateToValue(startYProgress, endYProgress); yOverviewAnim.setDuration(yDuration); - mYOverviewAnim.dispatchOnStart(); + mYOverviewAnim.updateValue(startYProgress); ValueAnimator nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer(); if (flingUpToNormal && !mIsHomeScreenVisible) { @@ -457,7 +472,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController, mXOverviewAnim.getAnimationPlayer().cancel(); } if (mYOverviewAnim != null) { - mYOverviewAnim.getAnimationPlayer().cancel(); + mYOverviewAnim.cancelAnimation(); } mShelfPeekAnim.setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); mMotionPauseDetector.clear(); From 14e03d1c4d6c68e84f3f4d9867e0757562a78e4a Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Fri, 7 Aug 2020 15:06:38 -0700 Subject: [PATCH 41/51] [Overview Actions] Add a logging event for tapping images in select mode. Event IDs were generated by command line on my workstation by uieventscli. Manually added to StatsLogManager. Test: local Bug: 161273376 Change-Id: Iee36c450ddb207f87653a8da2355c720369caa34 --- src/com/android/launcher3/logging/StatsLogManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index 2abde02a73..e754618a10 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -316,7 +316,10 @@ public class StatsLogManager implements ResourceBasedOverride { LAUNCHER_NAVIGATION_MODE_2_BUTTON(624), @UiEvent(doc = "System navigation mode is 0 button mode/gesture navigation mode .") - LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON(625); + LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON(625), + + @UiEvent(doc = "User tapped on image content in Overview Select mode.") + LAUNCHER_SELECT_MODE_IMAGE(627); // ADD MORE From 03a4a0cd530c6d13f01882e81568ab1544030c12 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 17 Jul 2020 13:06:57 -0700 Subject: [PATCH 42/51] Update overview from home transitions For both NoButtonNavbarToOverviewTouchController and NavBarToHomeTouchController: - Have consistent resistance applied such that RecentsView scales down and translates up slightly (but not as much as from an app) - Have consistent animation to home if you fling to that state rather than stay in overview. This is handled by a new class, OverviewToHomeAnim, which consolidates logic from NBTHTC and overrides some interpolators such that RecentsView doesn't fade out or translate downwards during the animation (it just slides off the screen while the home animation plays). Also make overview actions not clickable when alpha == 0, so that you can tap the hotseat/qsb during the transition from home to overview. Bug: 144170434 Change-Id: Ic291f285ff2f63c477633c48d4fadb23cf70c28a --- .../RecentsViewStateController.java | 11 +- .../QuickstepAtomicAnimationFactory.java | 15 +- .../NavBarToHomeTouchController.java | 25 ++- ...ButtonNavbarToOverviewTouchController.java | 71 ++++----- .../quickstep/util/OverviewToHomeAnim.java | 143 ++++++++++++++++++ .../quickstep/views/OverviewActionsView.java | 2 +- .../AnimatorControllerWithResistance.java | 84 ++++++++-- .../states/StateAnimationConfig.java | 6 +- .../launcher3/util/MultiValueAlpha.java | 12 ++ 9 files changed, 293 insertions(+), 76 deletions(-) create mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 085b9b3af9..5ccc1e8681 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides; import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE; import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; @@ -57,7 +58,7 @@ public final class RecentsViewStateController extends mRecentsView.updateEmptyMessage(); mRecentsView.resetTaskVisuals(); } - setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state); + setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig(), state); mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress()); } @@ -75,17 +76,19 @@ public final class RecentsViewStateController extends AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals)); } - setAlphas(builder, toState); + setAlphas(builder, config, toState); builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS, toState.getOverviewFullscreenProgress(), LINEAR); } - private void setAlphas(PropertySetter propertySetter, LauncherState state) { + private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config, + LauncherState state) { float buttonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1 : 0; propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA, buttonAlpha, LINEAR); propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(), - MultiValueAlpha.VALUE, buttonAlpha, LINEAR); + MultiValueAlpha.VALUE, buttonAlpha, config.getInterpolator( + ANIM_OVERVIEW_ACTIONS_FADE, LINEAR)); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index 131fcbfbf1..daa1aadbae 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -25,6 +25,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_PEEK; import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator; import static com.android.launcher3.anim.Interpolators.ACCEL; +import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7; import static com.android.launcher3.anim.Interpolators.DEACCEL_3; @@ -163,10 +164,15 @@ public class QuickstepAtomicAnimationFactory extends config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL); config.setInterpolator(ANIM_ALL_APPS_FADE, ACCEL); config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f)); - config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL); - config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7); - Workspace workspace = mActivity.getWorkspace(); + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL); + if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) { + config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME); + } else { + config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7); + } + + Workspace workspace = mActivity.getWorkspace(); // Start from a higher workspace scale, but only if we're invisible so we don't jump. boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE; if (isWorkspaceVisible) { @@ -206,8 +212,10 @@ public class QuickstepAtomicAnimationFactory extends config.setInterpolator(ANIM_WORKSPACE_SCALE, fromState == NORMAL ? ACCEL : OVERSHOOT_1_2); config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL); + config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT); } else { config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2); + config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2); // Scale up the recents, if it is not coming from the side RecentsView overview = mActivity.getOverviewPanel(); @@ -225,7 +233,6 @@ public class QuickstepAtomicAnimationFactory extends : OVERSHOOT_1_7; config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator); config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator); - config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2); } else if (fromState == HINT_STATE && toState == NORMAL) { config.setInterpolator(ANIM_DEPTH, DEACCEL_3); if (mHintToNormalDuration == -1) { diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index c1a585ea9d..61f6702dcc 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -19,13 +19,13 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_APPS_EDU; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.anim.Interpolators.DEACCEL_3; import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE; import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS; -import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import android.animation.ValueAnimator; @@ -45,6 +45,7 @@ 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.graphics.OverviewScrim; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.testing.TestProtocol; @@ -52,7 +53,9 @@ import com.android.launcher3.touch.SingleAxisSwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.TouchController; +import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.AssistantUtilities; +import com.android.quickstep.util.OverviewToHomeAnim; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -63,6 +66,8 @@ public class NavBarToHomeTouchController implements TouchController, SingleAxisSwipeDetector.Listener { private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3; + // How much of the overview scrim we can remove during the transition. + private static final float OVERVIEW_TO_HOME_SCRIM_PROGRESS = 0.5f; private final Launcher mLauncher; private final SingleAxisSwipeDetector mSwipeDetector; @@ -156,8 +161,13 @@ public class NavBarToHomeTouchController implements TouchController, final PendingAnimation builder = new PendingAnimation(accuracy); if (mStartState.overviewUi) { RecentsView recentsView = mLauncher.getOverviewPanel(); - builder.setFloat(recentsView, ADJACENT_PAGE_OFFSET, - -mPullbackDistance / recentsView.getPageOffsetScale(), PULLBACK_INTERPOLATOR); + AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher, + builder); + float endScrimAlpha = Utilities.mapRange(OVERVIEW_TO_HOME_SCRIM_PROGRESS, + mStartState.getOverviewScrimAlpha(mLauncher), + mEndState.getOverviewScrimAlpha(mLauncher)); + builder.setFloat(mLauncher.getDragLayer().getOverviewScrim(), + OverviewScrim.SCRIM_PROGRESS, endScrimAlpha, PULLBACK_INTERPOLATOR); if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { builder.addOnFrameCallback( () -> recentsView.redrawLiveTile(false /* mightNeedToRefill */)); @@ -212,8 +222,13 @@ public class NavBarToHomeTouchController implements TouchController, recentsView.switchToScreenshot(null, () -> recentsView.finishRecentsAnimation(true /* toRecents */, null)); } - mLauncher.getStateManager().goToState(mEndState, true, - () -> onSwipeInteractionCompleted(mEndState)); + if (mStartState == OVERVIEW) { + new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState)) + .animateWithVelocity(velocity); + } else { + mLauncher.getStateManager().goToState(mEndState, true, + () -> onSwipeInteractionCompleted(mEndState)); + } if (mStartState != mEndState) { logStateChange(mStartState.containerType, logAction); } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index 9316938c45..dbff20ae6c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -21,11 +21,8 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; -import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK; import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC; -import android.animation.Animator; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.graphics.PointF; @@ -35,14 +32,15 @@ import android.view.MotionEvent; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; -import com.android.launcher3.anim.AnimationSuccessListener; +import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.graphics.OverviewScrim; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.VibratorWrapper; -import com.android.quickstep.util.StaggeredWorkspaceAnim; +import com.android.quickstep.util.AnimatorControllerWithResistance; +import com.android.quickstep.util.OverviewToHomeAnim; import com.android.quickstep.views.RecentsView; /** @@ -62,10 +60,10 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo private boolean mDidTouchStartInNavBar; private boolean mReachedOverview; - private boolean mIsOverviewRehidden; - private boolean mIsHomeStaggeredAnimFinished; // The last recorded displacement before we reached overview. private PointF mStartDisplacement = new PointF(); + private float mStartY; + private AnimatorPlaybackController mOverviewResistYAnim; // Normal to Hint animation has flag SKIP_OVERVIEW, so we update this scrim with this animator. private ObjectAnimator mNormalToHintOverviewScrimAnimator; @@ -123,6 +121,7 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo mToState.getOverviewScrimAlpha(mLauncher)); } mReachedOverview = false; + mOverviewResistYAnim = null; } @Override @@ -160,6 +159,9 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo mNormalToHintOverviewScrimAnimator = null; mCurrentAnimation.dispatchOnCancelWithoutCancelRunnable(() -> { mLauncher.getStateManager().goToState(OVERVIEW, true, () -> { + mOverviewResistYAnim = AnimatorControllerWithResistance + .createRecentsResistanceFromOverviewAnim(mLauncher, null) + .createPlaybackController(); mReachedOverview = true; maybeSwipeInteractionToOverviewComplete(); }); @@ -173,13 +175,6 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo } } - // Used if flinging back to home after reaching overview - private void maybeSwipeInteractionToHomeComplete() { - if (mIsHomeStaggeredAnimFinished && mIsOverviewRehidden) { - onSwipeInteractionCompleted(NORMAL, Touch.FLING); - } - } - @Override protected boolean handlingOverviewAnim() { return mDidTouchStartInNavBar && super.handlingOverviewAnim(); @@ -193,11 +188,17 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo if (mMotionPauseDetector.isPaused()) { if (!mReachedOverview) { mStartDisplacement.set(xDisplacement, yDisplacement); + mStartY = event.getY(); } else { mRecentsView.setTranslationX((xDisplacement - mStartDisplacement.x) * OVERVIEW_MOVEMENT_FACTOR); - mRecentsView.setTranslationY((yDisplacement - mStartDisplacement.y) - * OVERVIEW_MOVEMENT_FACTOR); + float yProgress = (mStartDisplacement.y - yDisplacement) / mStartY; + if (yProgress > 0 && mOverviewResistYAnim != null) { + mOverviewResistYAnim.setPlayFraction(yProgress); + } else { + mRecentsView.setTranslationY((yDisplacement - mStartDisplacement.y) + * OVERVIEW_MOVEMENT_FACTOR); + } } // Stay in Overview. return true; @@ -212,35 +213,8 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo StateManager stateManager = mLauncher.getStateManager(); boolean goToHomeInsteadOfOverview = isFling; if (goToHomeInsteadOfOverview) { - if (velocity > 0) { - stateManager.goToState(NORMAL, true, - () -> onSwipeInteractionCompleted(NORMAL, Touch.FLING)); - } else { - mIsHomeStaggeredAnimFinished = mIsOverviewRehidden = false; - - StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim( - mLauncher, velocity, false /* animateOverviewScrim */); - staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() { - @Override - public void onAnimationSuccess(Animator animator) { - mIsHomeStaggeredAnimFinished = true; - maybeSwipeInteractionToHomeComplete(); - } - }).start(); - - // StaggeredWorkspaceAnim doesn't animate overview, so we handle it here. - stateManager.cancelAnimation(); - StateAnimationConfig config = new StateAnimationConfig(); - config.duration = OVERVIEW.getTransitionDuration(mLauncher); - config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK; - AnimatorSet anim = stateManager.createAtomicAnimation( - stateManager.getState(), NORMAL, config); - anim.addListener(AnimationSuccessListener.forRunnable(() -> { - mIsOverviewRehidden = true; - maybeSwipeInteractionToHomeComplete(); - })); - anim.start(); - } + new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING)) + .animateWithVelocity(velocity); } if (mReachedOverview) { float distanceDp = dpiFromPx(Math.max( @@ -256,6 +230,13 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo .withEndAction(goToHomeInsteadOfOverview ? null : this::maybeSwipeInteractionToOverviewComplete); + if (!goToHomeInsteadOfOverview) { + // Return to normal properties for the overview state. + StateAnimationConfig config = new StateAnimationConfig(); + config.duration = duration; + LauncherState state = mLauncher.getStateManager().getState(); + mLauncher.getStateManager().createAtomicAnimation(state, state, config).start(); + } } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java new file mode 100644 index 0000000000..d2e1dedd2b --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; +import static com.android.launcher3.anim.Interpolators.INSTANT; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; +import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.util.Log; +import android.view.animation.Interpolator; + +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.anim.AnimationSuccessListener; +import com.android.launcher3.statemanager.StateManager; +import com.android.launcher3.states.StateAnimationConfig; +import com.android.quickstep.views.RecentsView; + +/** + * Runs an animation from overview to home. Currently, this animation is just a wrapper around the + * normal state transition, in order to keep RecentsView at the same scale and translationY that + * it started out at as it translates offscreen. It also scrolls RecentsView to page 0 and may play + * a {@link StaggeredWorkspaceAnim} if we're starting from an upward fling. + */ +public class OverviewToHomeAnim { + + private static final String TAG = "OverviewToHomeAnim"; + + // Constants to specify how to scroll RecentsView to the default page if it's not already there. + private static final int DEFAULT_PAGE = 0; + private static final int PER_PAGE_SCROLL_DURATION = 150; + private static final int MAX_PAGE_SCROLL_DURATION = 750; + + private final Launcher mLauncher; + private final Runnable mOnReachedHome; + + // Only run mOnReachedHome when both of these are true. + private boolean mIsHomeStaggeredAnimFinished; + private boolean mIsOverviewHidden; + + public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome) { + mLauncher = launcher; + mOnReachedHome = onReachedHome; + } + + /** + * Starts the animation. If velocity < 0 (i.e. upwards), also plays a + * {@link StaggeredWorkspaceAnim}. + */ + public void animateWithVelocity(float velocity) { + StateManager stateManager = mLauncher.getStateManager(); + LauncherState startState = stateManager.getState(); + if (startState != OVERVIEW) { + Log.e(TAG, "animateFromOverviewToHome: unexpected start state " + startState); + } + + boolean playStaggeredWorkspaceAnim = velocity < 0; + if (playStaggeredWorkspaceAnim) { + StaggeredWorkspaceAnim staggeredWorkspaceAnim = new StaggeredWorkspaceAnim( + mLauncher, velocity, false /* animateOverviewScrim */); + staggeredWorkspaceAnim.addAnimatorListener(new AnimationSuccessListener() { + @Override + public void onAnimationSuccess(Animator animator) { + mIsHomeStaggeredAnimFinished = true; + maybeOverviewToHomeAnimComplete(); + } + }).start(); + } else { + mIsHomeStaggeredAnimFinished = true; + } + + RecentsView recentsView = mLauncher.getOverviewPanel(); + int numPagesToScroll = recentsView.getNextPage() - DEFAULT_PAGE; + int scrollDuration = Math.min(MAX_PAGE_SCROLL_DURATION, + numPagesToScroll * PER_PAGE_SCROLL_DURATION); + int duration = Math.max(scrollDuration, startState.getTransitionDuration(mLauncher)); + + StateAnimationConfig config = new UseFirstInterpolatorStateAnimConfig(); + config.duration = duration; + config.animFlags = playStaggeredWorkspaceAnim + // StaggeredWorkspaceAnim doesn't animate overview, so we handle it here. + ? PLAY_ATOMIC_OVERVIEW_PEEK + : ANIM_ALL_COMPONENTS; + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, DEACCEL); + config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME); + config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME); + config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT); + AnimatorSet anim = stateManager.createAtomicAnimation( + startState, NORMAL, config); + anim.addListener(new AnimationSuccessListener() { + @Override + public void onAnimationSuccess(Animator animator) { + mIsOverviewHidden = true; + maybeOverviewToHomeAnimComplete(); + } + }); + stateManager.cancelAnimation(); + anim.start(); + recentsView.snapToPage(DEFAULT_PAGE, duration); + } + + private void maybeOverviewToHomeAnimComplete() { + if (mIsHomeStaggeredAnimFinished && mIsOverviewHidden) { + mOnReachedHome.run(); + } + } + + /** + * Wrapper around StateAnimationConfig that doesn't allow interpolators to be set if they are + * already set. This ensures they aren't overridden before being used. + */ + private static class UseFirstInterpolatorStateAnimConfig extends StateAnimationConfig { + @Override + public void setInterpolator(int animId, Interpolator interpolator) { + if (mInterpolators[animId] == null || interpolator == null) { + super.setInterpolator(animId, interpolator); + } + } + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java index 79d57c55a2..1bf2fbf81f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java @@ -105,6 +105,7 @@ public class OverviewActionsView extends FrameLayo public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr, 0); mMultiValueAlpha = new MultiValueAlpha(this, 4); + mMultiValueAlpha.setUpdateVisibility(true); } @Override @@ -168,7 +169,6 @@ public class OverviewActionsView extends FrameLayo } boolean isHidden = mHiddenFlags != 0; mMultiValueAlpha.getProperty(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1); - setVisibility(isHidden ? INVISIBLE : VISIBLE); } /** diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java index 23b02d5665..a19a67c8fc 100644 --- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java +++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java @@ -18,6 +18,8 @@ package com.android.quickstep.util; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS; +import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; +import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import android.animation.TimeInterpolator; import android.content.Context; @@ -27,12 +29,16 @@ import android.graphics.Rect; import android.graphics.RectF; import android.util.FloatProperty; +import androidx.annotation.Nullable; + +import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.SysUINavigationMode; +import com.android.quickstep.views.RecentsView; /** * Controls an animation that can go beyond progress = 1, at which point resistance should be @@ -48,15 +54,32 @@ public class AnimatorControllerWithResistance { */ public static final float TWO_BUTTON_EXTRA_DRAG_FACTOR = 0.25f; - /** - * Start slowing down the rate of scaling down when recents view is smaller than this scale. - */ - private static final float RECENTS_SCALE_START_RESIST = 0.75f; + private enum RecentsParams { + FROM_APP(0.75f, 0.5f, 1f), + FROM_OVERVIEW(1f, 0.75f, 0.5f); - /** - * Recents view will reach this scale at the very end of the drag. - */ - private static final float RECENTS_SCALE_MAX_RESIST = 0.5f; + RecentsParams(float scaleStartResist, float scaleMaxResist, float translationFactor) { + this.scaleStartResist = scaleStartResist; + this.scaleMaxResist = scaleMaxResist; + this.translationFactor = translationFactor; + } + + /** + * Start slowing down the rate of scaling down when recents view is smaller than this scale. + */ + public final float scaleStartResist; + + /** + * Recents view will reach this scale at the very end of the drag. + */ + public final float scaleMaxResist; + + /** + * How much translation to apply to RecentsView when the drag reaches the top of the screen, + * where 0 will keep it centered and 1 will have it barely touch the top of the screen. + */ + public final float translationFactor; + } private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL; private static final TimeInterpolator RECENTS_TRANSLATE_RESIST_INTERPOLATOR = LINEAR; @@ -115,6 +138,24 @@ public class AnimatorControllerWithResistance { RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget, FloatProperty scaleProperty, TRANSLATION translationTarget, FloatProperty translationProperty) { + + PendingAnimation resistAnim = createRecentsResistanceAnim(null, context, + recentsOrientedState, dp, scaleTarget, scaleProperty, translationTarget, + translationProperty, RecentsParams.FROM_APP); + + AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController(); + return new AnimatorControllerWithResistance(normalController, resistanceController); + } + + /** + * Creates the resistance animation for {@link #createForRecents}, or can be used separately + * when starting from recents, i.e. {@link #createRecentsResistanceFromOverviewAnim}. + */ + public static PendingAnimation createRecentsResistanceAnim( + @Nullable PendingAnimation resistAnim, Context context, + RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget, + FloatProperty scaleProperty, TRANSLATION translationTarget, + FloatProperty translationProperty, RecentsParams params) { Rect startRect = new Rect(); LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect, recentsOrientedState.getOrientationHandler()); @@ -125,7 +166,9 @@ public class AnimatorControllerWithResistance { distanceToCover = (long) ((dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR); } - PendingAnimation resistAnim = new PendingAnimation(distanceToCover * 2); + if (resistAnim == null) { + resistAnim = new PendingAnimation(distanceToCover * 2); + } PointF pivot = new PointF(); float fullscreenScale = recentsOrientedState.getFullScreenScaleAndPivot( @@ -141,9 +184,9 @@ public class AnimatorControllerWithResistance { } else { // Create an interpolator that resists the scale so the scale doesn't get smaller than // RECENTS_SCALE_MAX_RESIST. - float startResist = Utilities.getProgress(RECENTS_SCALE_START_RESIST, startScale, + float startResist = Utilities.getProgress(params.scaleStartResist , startScale, endScale); - float maxResist = Utilities.getProgress(RECENTS_SCALE_MAX_RESIST, startScale, endScale); + float maxResist = Utilities.getProgress(params.scaleMaxResist, startScale, endScale); scaleInterpolator = t -> { if (t < startResist) { return t; @@ -160,17 +203,28 @@ public class AnimatorControllerWithResistance { // Compute where the task view would be based on the end scale, if we didn't translate. RectF endRectF = new RectF(startRect); Matrix temp = new Matrix(); - temp.setScale(RECENTS_SCALE_MAX_RESIST, RECENTS_SCALE_MAX_RESIST, pivot.x, pivot.y); + temp.setScale(params.scaleMaxResist, params.scaleMaxResist, pivot.x, pivot.y); temp.mapRect(endRectF); // Translate such that the task view touches the top of the screen when drag does. float endTranslation = endRectF.top * recentsOrientedState.getOrientationHandler() - .getSecondaryTranslationDirectionFactor(); + .getSecondaryTranslationDirectionFactor() * params.translationFactor; resistAnim.addFloat(translationTarget, translationProperty, 0, endTranslation, RECENTS_TRANSLATE_RESIST_INTERPOLATOR); } - AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController(); - return new AnimatorControllerWithResistance(normalController, resistanceController); + return resistAnim; } + /** + * Helper method to update or create a PendingAnimation suitable for animating + * a RecentsView interaction that started from the overview state. + */ + public static PendingAnimation createRecentsResistanceFromOverviewAnim( + BaseDraggingActivity activity, @Nullable PendingAnimation resistanceAnim) { + RecentsView recentsView = activity.getOverviewPanel(); + return createRecentsResistanceAnim(resistanceAnim, activity, + recentsView.getPagedViewOrientedState(), activity.getDeviceProfile(), + recentsView, RECENTS_SCALE_PROPERTY, recentsView, TASK_SECONDARY_TRANSLATION, + RecentsParams.FROM_OVERVIEW); + } } diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java index f90ad3cd0b..8b7217709f 100644 --- a/src/com/android/launcher3/states/StateAnimationConfig.java +++ b/src/com/android/launcher3/states/StateAnimationConfig.java @@ -71,6 +71,7 @@ public class StateAnimationConfig { ANIM_ALL_APPS_HEADER_FADE, ANIM_OVERVIEW_MODAL, ANIM_DEPTH, + ANIM_OVERVIEW_ACTIONS_FADE, }) @Retention(RetentionPolicy.SOURCE) public @interface AnimType {} @@ -89,10 +90,11 @@ public class StateAnimationConfig { public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions public static final int ANIM_OVERVIEW_MODAL = 13; public static final int ANIM_DEPTH = 14; + public static final int ANIM_OVERVIEW_ACTIONS_FADE = 15; - private static final int ANIM_TYPES_COUNT = 15; + private static final int ANIM_TYPES_COUNT = 16; - private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT]; + protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT]; public StateAnimationConfig() { } diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java index a8642b05c0..5be95292b4 100644 --- a/src/com/android/launcher3/util/MultiValueAlpha.java +++ b/src/com/android/launcher3/util/MultiValueAlpha.java @@ -19,6 +19,8 @@ package com.android.launcher3.util; import android.util.FloatProperty; import android.view.View; +import com.android.launcher3.anim.AlphaUpdateListener; + import java.util.Arrays; /** @@ -44,6 +46,8 @@ public class MultiValueAlpha { private final AlphaProperty[] mMyProperties; private int mValidMask; + // Whether we should change from INVISIBLE to VISIBLE and vice versa at low alpha values. + private boolean mUpdateVisibility; public MultiValueAlpha(View view, int size) { mView = view; @@ -66,6 +70,11 @@ public class MultiValueAlpha { return mMyProperties[index]; } + /** Sets whether we should update between INVISIBLE and VISIBLE based on alpha. */ + public void setUpdateVisibility(boolean updateVisibility) { + mUpdateVisibility = updateVisibility; + } + public class AlphaProperty { private final int mMyMask; @@ -99,6 +108,9 @@ public class MultiValueAlpha { mValue = value; mView.setAlpha(mOthers * mValue); + if (mUpdateVisibility) { + AlphaUpdateListener.updateVisibility(mView); + } } public float getValue() { From 06513f11c2304a371a7c79cec371562d65393322 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 10 Aug 2020 15:06:02 -0700 Subject: [PATCH 43/51] Don't reapply window transform if we are already running a window anim Bug: 149934536 Change-Id: I3fa7f0b2581ca83923a42f37f52850b02c22e995 Merged-In: I3fa7f0b2581ca83923a42f37f52850b02c22e995 --- .../src/com/android/quickstep/BaseSwipeUpHandlerV2.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index ed33532e6d..0aa14862a7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -493,7 +493,11 @@ public abstract class BaseSwipeUpHandlerV2, Q exte // much the window is bound by overscroll (vs moving freely). if (animate) { ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1); - reapplyWindowTransformAnim.addUpdateListener(anim -> applyWindowTransform()); + reapplyWindowTransformAnim.addUpdateListener(anim -> { + if (mRunningWindowAnim == null) { + applyWindowTransform(); + } + }); reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start(); } else { applyWindowTransform(); From fac87415221447f8f47ef4a88d187b7e175a6296 Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Mon, 10 Aug 2020 15:51:45 -0700 Subject: [PATCH 44/51] Overscroll plugin - give the plugin its own factory. Separate out the overscroll plugin from the task overlay. These two classes aren't really related. Bug: 162012217 Tested: checked plugin still works Change-Id: Id89eff1ad2ae9766efaaecd8cfc66d6521b9ca8c --- .../quickstep/OverscrollPluginFactory.java | 40 +++++++++++++++++++ .../android/quickstep/TaskOverlayFactory.java | 8 ---- .../quickstep/TouchInteractionService.java | 5 +-- quickstep/res/values/config.xml | 2 + 4 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java new file mode 100644 index 0000000000..4c261abc7a --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep; + +import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; + +import com.android.launcher3.R; +import com.android.launcher3.util.MainThreadInitializedObject; +import com.android.launcher3.util.ResourceBasedOverride; +import com.android.systemui.plugins.OverscrollPlugin; + +/** + * Resource overrideable factory for forcing a local overscroll plugin. + * Override {@link R.string#overscroll_plugin_factory_class} to set a different class. + */ +public class OverscrollPluginFactory implements ResourceBasedOverride { + public static final MainThreadInitializedObject INSTANCE = forOverride( + OverscrollPluginFactory.class, + R.string.overscroll_plugin_factory_class); + + /** + * Get the plugin that is defined locally in launcher, as opposed to a dynamic side loaded one. + */ + public OverscrollPlugin getLocalOverscrollPlugin() { + return null; + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index db512fa0f9..3039511027 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -45,7 +45,6 @@ import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; -import com.android.systemui.plugins.OverscrollPlugin; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -94,13 +93,6 @@ public class TaskOverlayFactory implements ResourceBasedOverride { public static final MainThreadInitializedObject INSTANCE = forOverride(TaskOverlayFactory.class, R.string.task_overlay_factory_class); - /** - * @return a launcher-provided OverscrollPlugin if available, otherwise null - */ - public OverscrollPlugin getLocalOverscrollPlugin() { - return null; - } - public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) { return new TaskOverlay(thumbnailView); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 13adff53f3..7b91001c5f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -597,9 +597,8 @@ public class TouchInteractionService extends Service implements PluginListener + + com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity From 9367f98348f9db5b5b6840b8003dd62c037d8be8 Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Mon, 10 Aug 2020 12:44:48 -0700 Subject: [PATCH 45/51] [Overview Actions] Set launcher state to Overview when rotate in recents. Test: local Bug: 160718310 Change-Id: I73f498151d7cc6a9db9d352549124c9d550ae6f2 Merged-In: I73f498151d7cc6a9db9d352549124c9d550ae6f2 --- .../src/com/android/quickstep/views/RecentsView.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 217997db7f..80a3b94962 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -24,6 +24,7 @@ import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAG import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; +import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.Utilities.mapToRange; import static com.android.launcher3.Utilities.squaredHypot; @@ -93,6 +94,7 @@ import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.LauncherState; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -1712,6 +1714,11 @@ public abstract class RecentsView extends PagedView if (mOrientationState.setRecentsRotation(mActivity.getDisplay().getRotation())) { updateOrientationHandler(); } + // If overview is in modal state when rotate, reset it to overview state without running + // animation. + if (mActivity.isInState(OVERVIEW_MODAL_TASK)) { + mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false); + } } public void setLayoutRotation(int touchRotation, int displayRotation) { From cf82754384a26d2038ba1f13c0ecea57c0d3116d Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Tue, 11 Aug 2020 16:17:41 -0700 Subject: [PATCH 46/51] TaskOverlayFactory - remove static factory. Make the overlay factory a member of the recents view. Before the factory was static. The factory has references to activity objects so was causing leaks. Bug: 162012217 Tested: local, factory still works Change-Id: I2283134f3008b630ba2056f07e65ac042957cdbd --- .../android/quickstep/TaskOverlayFactory.java | 17 ++++++++++++----- .../android/quickstep/views/RecentsView.java | 15 +++++++++++++++ .../quickstep/views/TaskThumbnailView.java | 15 ++++++++------- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index 3039511027..36579ec736 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -18,7 +18,6 @@ package com.android.quickstep; import static android.view.Surface.ROTATION_0; -import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL; import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED; @@ -39,7 +38,6 @@ import com.android.launcher3.R; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.SystemShortcut; -import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.ResourceBasedOverride; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.views.OverviewActionsView; @@ -90,13 +88,22 @@ public class TaskOverlayFactory implements ResourceBasedOverride { return shortcuts; } - public static final MainThreadInitializedObject INSTANCE = - forOverride(TaskOverlayFactory.class, R.string.task_overlay_factory_class); - public TaskOverlay createOverlay(TaskThumbnailView thumbnailView) { return new TaskOverlay(thumbnailView); } + /** + * Subclasses can attach any system listeners in this method, must be paired with + * {@link #removeListeners()} + */ + public void initListeners() { } + + /** + * Subclasses should remove any system listeners in this method, must be paired with + * {@link #initListeners()} + */ + public void removeListeners() { } + /** Note that these will be shown in order from top to bottom, if available for the task. */ private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[]{ TaskShortcutFactory.APP_INFO, diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 217997db7f..eeff422a5d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -115,6 +115,7 @@ import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.DynamicResource; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.OverScroller; +import com.android.launcher3.util.ResourceBasedOverride.Overrides; import com.android.launcher3.util.Themes; import com.android.launcher3.util.ViewPool; import com.android.quickstep.BaseActivityInterface; @@ -123,6 +124,7 @@ import com.android.quickstep.RecentsAnimationTargets; import com.android.quickstep.RecentsModel; import com.android.quickstep.RecentsModel.TaskVisualsChangeListener; import com.android.quickstep.SystemUiProxy; +import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskThumbnailCache; import com.android.quickstep.TaskUtils; import com.android.quickstep.ViewUtils; @@ -277,6 +279,8 @@ public abstract class RecentsView extends PagedView private final ViewPool mTaskViewPool; + private final TaskOverlayFactory mTaskOverlayFactory; + private boolean mDwbToastShown; protected boolean mDisallowScrollToClearAll; private boolean mOverlayEnabled; @@ -464,6 +468,11 @@ public abstract class RecentsView extends PagedView updateEmptyMessage(); mOrientationHandler = mOrientationState.getOrientationHandler(); + mTaskOverlayFactory = Overrides.getObject( + TaskOverlayFactory.class, + context.getApplicationContext(), + R.string.task_overlay_factory_class); + // Initialize quickstep specific cache params here, as this is constructed only once mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5); } @@ -557,6 +566,7 @@ public abstract class RecentsView extends PagedView mIPinnedStackAnimationListener); mOrientationState.initListeners(); SplitScreenBounds.INSTANCE.addOnChangeListener(this); + mTaskOverlayFactory.initListeners(); } @Override @@ -573,6 +583,7 @@ public abstract class RecentsView extends PagedView SplitScreenBounds.INSTANCE.removeOnChangeListener(this); mIPinnedStackAnimationListener.setActivity(null); mOrientationState.destroyListeners(); + mTaskOverlayFactory.removeListeners(); } @Override @@ -2424,6 +2435,10 @@ public abstract class RecentsView extends PagedView */ public void setModalStateEnabled(boolean isModalState) { } + public TaskOverlayFactory getTaskOverlayFactory() { + return mTaskOverlayFactory; + } + public BaseActivityInterface getSizeStrategy() { return mSizeStrategy; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index fad64271f3..607672a751 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -52,7 +52,6 @@ import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; -import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskOverlayFactory.TaskOverlay; import com.android.quickstep.views.TaskView.FullscreenDrawParams; import com.android.systemui.plugins.OverviewScreenshotActions; @@ -85,7 +84,7 @@ public class TaskThumbnailView extends View implements PluginListener Date: Fri, 31 Jul 2020 15:54:36 -0700 Subject: [PATCH 47/51] Overview Actions - enable proactive actions flag. Bug: 162623012 Test: local Change-Id: I343ae83601ebdab4dacc9f4611b069f87b5542eb --- src/com/android/launcher3/config/FeatureFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 45116b6b27..88a9abaf8d 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -92,7 +92,7 @@ public final class FeatureFlags { // Keep as DeviceFlag to allow remote disable in emergency. public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag( - "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", false, "Show chip hints on the overview screen"); + "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", true, "Show chip hints on the overview screen"); public static final BooleanFlag FOLDER_NAME_SUGGEST = new DeviceFlag( "FOLDER_NAME_SUGGEST", true, From a14567096922f23d6e03c84fc930e3451e7471c2 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 12 Aug 2020 16:48:33 -0700 Subject: [PATCH 48/51] Store mHistoricTimes as longs intead of floats The loss of precision was causing us to miscalculate the age of events, and thus not detecting any pause due to denominator = 0. Test: have a device that hasn't been rebooted for a certain amount of time such that SystemClock#uptimeMillis can't be accurately converted to a float, then try to swipe up and hold Fixes: 160568387 Change-Id: Idef112187f34a18feea7e6a0b77258626f9d0ed4 --- .../android/quickstep/util/MotionPauseDetector.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java index 969fa5067d..f60f7ad6d8 100644 --- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java +++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java @@ -276,7 +276,7 @@ public class MotionPauseDetector { private static final int HISTORY_SIZE = 20; // Position history are stored in a circular array - private final float[] mHistoricTimes = new float[HISTORY_SIZE]; + private final long[] mHistoricTimes = new long[HISTORY_SIZE]; private final float[] mHistoricPos = new float[HISTORY_SIZE]; private int mHistoryCount = 0; private int mHistoryStart = 0; @@ -292,7 +292,7 @@ public class MotionPauseDetector { mHistoryCount = mHistoryStart = 0; } - private void addPositionAndTime(float eventTime, float eventPosition) { + private void addPositionAndTime(long eventTime, float eventPosition) { mHistoricTimes[mHistoryStart] = eventTime; mHistoricPos[mHistoryStart] = eventPosition; mHistoryStart++; @@ -322,7 +322,7 @@ public class MotionPauseDetector { * Based on solveUnweightedLeastSquaresDeg2 in VelocityTracker.cpp */ private Float solveUnweightedLeastSquaresDeg2(final int pointPos) { - final float eventTime = mHistoricTimes[pointPos]; + final long eventTime = mHistoricTimes[pointPos]; float sxi = 0, sxiyi = 0, syi = 0, sxi2 = 0, sxi3 = 0, sxi2yi = 0, sxi4 = 0; int count = 0; @@ -332,8 +332,8 @@ public class MotionPauseDetector { index += HISTORY_SIZE; } - float time = mHistoricTimes[index]; - float age = eventTime - time; + long time = mHistoricTimes[index]; + long age = eventTime - time; if (age > HORIZON_MS) { break; } @@ -364,7 +364,7 @@ public class MotionPauseDetector { if (endPos < 0) { endPos += HISTORY_SIZE; } - float denominator = eventTime - mHistoricTimes[endPos]; + long denominator = eventTime - mHistoricTimes[endPos]; if (denominator != 0) { return (mHistoricPos[pointPos] - mHistoricPos[endPos]) / denominator; } From ba6fec3eaeb2087428c8e33826429d72ad0290cf Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Wed, 12 Aug 2020 17:17:00 -0700 Subject: [PATCH 49/51] [Overview Actions] Reset the modal task view when rotate from select mode. Test: local Bug: 161901771 Change-Id: I103e59ad68874db7fcb39556764d315983ac047c --- .../src/com/android/quickstep/views/RecentsView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 80a3b94962..46e6892782 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -1718,6 +1718,7 @@ public abstract class RecentsView extends PagedView // animation. if (mActivity.isInState(OVERVIEW_MODAL_TASK)) { mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false); + resetModalVisuals(); } } From 9dfcc316c1519978e49462707ba36156d7abb2e5 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 10 Aug 2020 18:33:01 -0700 Subject: [PATCH 50/51] Track OverviewToHomeAnim with StateManager This way we mark the the current state as NORMAL at the start of the animation, and cancel it as part of other state transitions. This allows us to interact with launcher (e.g. to go to all apps or pull down the notification shade) during the animation. Also use OverviewToHomeAnim from RecentsView#startHome() to ensure the animation is consistent, e.g. doesn't fade out RecentsView, scrolls to page 1, etc. Bug: 144170434 Change-Id: I5348565b9e705d8ffba39818dde9efe82b16bb7a Merged-In: I5348565b9e705d8ffba39818dde9efe82b16bb7a --- .../quickstep/util/OverviewToHomeAnim.java | 11 +++++--- .../quickstep/views/LauncherRecentsView.java | 7 ++++-- .../uioverrides/states/AllAppsState.java | 4 ++- .../PortraitStatesTouchController.java | 4 +++ .../launcher3/statemanager/StateManager.java | 25 ++++++++++++++++--- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java index d2e1dedd2b..6278e147c0 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java @@ -76,6 +76,7 @@ public class OverviewToHomeAnim { if (startState != OVERVIEW) { Log.e(TAG, "animateFromOverviewToHome: unexpected start state " + startState); } + AnimatorSet anim = new AnimatorSet(); boolean playStaggeredWorkspaceAnim = velocity < 0; if (playStaggeredWorkspaceAnim) { @@ -87,7 +88,8 @@ public class OverviewToHomeAnim { mIsHomeStaggeredAnimFinished = true; maybeOverviewToHomeAnimComplete(); } - }).start(); + }); + anim.play(staggeredWorkspaceAnim.getAnimators()); } else { mIsHomeStaggeredAnimFinished = true; } @@ -108,16 +110,17 @@ public class OverviewToHomeAnim { config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME); config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT); - AnimatorSet anim = stateManager.createAtomicAnimation( + AnimatorSet stateAnim = stateManager.createAtomicAnimation( startState, NORMAL, config); - anim.addListener(new AnimationSuccessListener() { + stateAnim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { mIsOverviewHidden = true; maybeOverviewToHomeAnimComplete(); } }); - stateManager.cancelAnimation(); + anim.play(stateAnim); + stateManager.setCurrentAnimation(anim, NORMAL); anim.start(); recentsView.snapToPage(DEFAULT_PAGE, duration); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index 79028d1cc2..b934c29d2f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -51,6 +51,7 @@ import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.ScrimView; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.SysUINavigationMode; +import com.android.quickstep.util.OverviewToHomeAnim; import com.android.quickstep.util.TransformParams; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.RecentsExtraCard; @@ -105,12 +106,14 @@ public class LauncherRecentsView extends RecentsView @Override public void startHome() { + Runnable onReachedHome = () -> mActivity.getStateManager().goToState(NORMAL, false); + OverviewToHomeAnim overviewToHomeAnim = new OverviewToHomeAnim(mActivity, onReachedHome); if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { switchToScreenshot(null, () -> finishRecentsAnimation(true /* toRecents */, - () -> mActivity.getStateManager().goToState(NORMAL))); + () -> overviewToHomeAnim.animateWithVelocity(0))); } else { - mActivity.getStateManager().goToState(NORMAL); + overviewToHomeAnim.animateWithVelocity(0); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java index e7cd39381d..29a6be0779 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides.states; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; +import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import android.content.Context; @@ -92,7 +93,8 @@ public class AllAppsState extends LauncherState { @Override public float[] getOverviewScaleAndOffset(Launcher launcher) { - return new float[] {0.9f, 0}; + float offset = ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher) ? 1 : 0; + return new float[] {0.9f, offset}; } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index 20ee61db9b..a684b9d7fb 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -142,6 +142,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "PortraitStatesTouchController.getTargetState 1"); } + if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(mLauncher)) { + // Don't allow swiping down to overview. + return NORMAL; + } return TouchInteractionService.isConnected() ? mLauncher.getStateManager().getLastState() : NORMAL; } else if (fromState == OVERVIEW) { diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java index 60b87d984b..27923089fb 100644 --- a/src/com/android/launcher3/statemanager/StateManager.java +++ b/src/com/android/launcher3/statemanager/StateManager.java @@ -311,7 +311,13 @@ public class StateManager> { handler.setStateWithAnimation(state, mConfig, builder); } } - builder.addListener(new AnimationSuccessListener() { + builder.addListener(createStateAnimationListener(state)); + mConfig.setAnimation(builder.buildAnim(), state); + return builder; + } + + private AnimatorListener createStateAnimationListener(STATE_TYPE state) { + return new AnimationSuccessListener() { @Override public void onAnimationStart(Animator animation) { @@ -326,9 +332,7 @@ public class StateManager> { } onStateTransitionEnd(state); } - }); - mConfig.setAnimation(builder.buildAnim(), state); - return builder; + }; } private void onStateTransitionStart(STATE_TYPE state) { @@ -395,6 +399,19 @@ public class StateManager> { mConfig.playbackController = controller; } + /** + * @see #setCurrentAnimation(AnimatorSet, Animator...). Using this method tells the StateManager + * that this is a custom animation to the given state, and thus the StateManager will add an + * animation listener to call {@link #onStateTransitionStart} and {@link #onStateTransitionEnd}. + * @param anim The custom animation to the given state. + * @param toState The state we are animating towards. + */ + public void setCurrentAnimation(AnimatorSet anim, STATE_TYPE toState) { + cancelAnimation(); + setCurrentAnimation(anim); + anim.addListener(createStateAnimationListener(toState)); + } + /** * Sets the animation as the current state animation, i.e., canceled when * starting another animation and may block some launcher interactions while running. From 107fe60f6ef5b3336ece35122650d9ccc1c69913 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 12 Aug 2020 12:30:00 -0700 Subject: [PATCH 51/51] Ensure we clearState() when going to Overview from home We need to do this before potentially starting another interaction during the animation, or we could end up in an inconsistent state. Fixes: 160759508 Change-Id: Ia28dceddcc258679fc0b968f5a83fae5ef3f5acb --- .../NoButtonNavbarToOverviewTouchController.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index dbff20ae6c..8f0f683d18 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -136,6 +136,11 @@ public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchCo public void onDragEnd(float velocity) { super.onDragEnd(velocity); mNormalToHintOverviewScrimAnimator = null; + if (mLauncher.isInState(OVERVIEW)) { + // Normally we would cleanup the state based on mCurrentAnimation, but since we stop + // using that when we pause to go to Overview, we need to clean up ourselves. + clearState(); + } } @Override