From 768fe5585d564d5bc294559a6c5cb2aec3f89da9 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 6 May 2022 20:17:57 +0100 Subject: [PATCH 01/44] Add DisplayController in PreviewContext's allowed objects Fix: 231526132 Test: switch grids Change-Id: Ie43c54c5fbbea51ee3b795be6baa9c2eaf5e15e4 (cherry picked from commit 114572268581eead50b6f536959c50ef9da9d276) Merged-In: Ie43c54c5fbbea51ee3b795be6baa9c2eaf5e15e4 --- .../android/launcher3/graphics/LauncherPreviewRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index a11bd4fdad1..d5bcb0cbcb5 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -83,6 +83,7 @@ import com.android.launcher3.uioverrides.PredictedAppIconInflater; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext; @@ -129,7 +130,7 @@ public PreviewContext(Context base, InvariantDeviceProfile idp) { super(base, UserCache.INSTANCE, InstallSessionHelper.INSTANCE, LauncherAppState.INSTANCE, InvariantDeviceProfile.INSTANCE, CustomWidgetManager.INSTANCE, PluginManagerWrapper.INSTANCE, - WindowManagerProxy.INSTANCE); + WindowManagerProxy.INSTANCE, DisplayController.INSTANCE); mIdp = idp; mObjectMap.put(InvariantDeviceProfile.INSTANCE, idp); mObjectMap.put(LauncherAppState.INSTANCE, From f6ec317d8f8e634fe499a84a4ab6668261a87d50 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 23 Jun 2022 12:00:57 -0700 Subject: [PATCH 02/44] Moving widget padding to drawable instead of using itemDecorator ItemDecorator uses item position which is not stable during animations. Moving it to the background allows the padding to be stable Bug: 236961658 Test: Verified that the app doesn't crash. Change-Id: Ied12077de4097e827c5c4157f5196346a301f185 (cherry picked from commit ed681548fcc3519ed4c28d758a2a2cbbc22fd2db) Merged-In: Ied12077de4097e827c5c4157f5196346a301f185 --- res/layout/widgets_list_row_header.xml | 1 - .../picker/WidgetsListDrawableFactory.java | 11 ++++- .../widget/picker/WidgetsRecyclerView.java | 41 +------------------ 3 files changed, 12 insertions(+), 41 deletions(-) diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml index 3cdc2e844b5..35bea279c0a 100644 --- a/res/layout/widgets_list_row_header.xml +++ b/res/layout/widgets_list_row_header.xml @@ -19,7 +19,6 @@ android:id="@+id/widgets_list_header" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingVertical="@dimen/widget_list_header_view_vertical_padding" android:orientation="horizontal" android:importantForAccessibility="yes" android:focusable="true" diff --git a/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java b/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java index c61e3a43491..984a2741e7d 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java +++ b/src/com/android/launcher3/widget/picker/WidgetsListDrawableFactory.java @@ -27,6 +27,7 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.InsetDrawable; import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.StateListDrawable; @@ -40,6 +41,8 @@ final class WidgetsListDrawableFactory { private final float mMiddleCornerRadius; private final ColorStateList mSurfaceColor; private final ColorStateList mRippleColor; + private final int mVerticalPadding; + private final int mHeaderMargin; WidgetsListDrawableFactory(Context context) { Resources res = context.getResources(); @@ -48,6 +51,9 @@ final class WidgetsListDrawableFactory { mSurfaceColor = context.getColorStateList(R.color.surface); mRippleColor = ColorStateList.valueOf( Themes.getAttrColor(context, android.R.attr.colorControlHighlight)); + mVerticalPadding = + res.getDimensionPixelSize(R.dimen.widget_list_header_view_vertical_padding); + mHeaderMargin = res.getDimensionPixelSize(R.dimen.widget_list_entry_spacing); } /** @@ -74,7 +80,10 @@ Drawable createHeaderBackgroundDrawable() { stateList.addState( LAST.mStateSet, createRoundedRectDrawable(mMiddleCornerRadius, mTopBottomCornerRadius)); - return new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList); + RippleDrawable ripple = + new RippleDrawable(mRippleColor, /* content= */ stateList, /* mask= */ stateList); + ripple.setPadding(0, mVerticalPadding, 0, mVerticalPadding); + return new InsetDrawable(ripple, 0, mHeaderMargin, 0, 0); } /** diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java index daa67a973c8..4c0e0d595fd 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java +++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java @@ -16,18 +16,12 @@ package com.android.launcher3.widget.picker; -import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_HEADER; -import static com.android.launcher3.widget.picker.WidgetsListAdapter.VIEW_TYPE_WIDGETS_SEARCH_HEADER; - import android.content.Context; import android.graphics.Point; -import android.graphics.Rect; import android.util.AttributeSet; import android.util.SparseIntArray; import android.view.MotionEvent; -import android.view.View; -import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; @@ -55,7 +49,6 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte * VIEW_TYPE_WIDGETS_LIST is not visible on the screen. */ private final SparseIntArray mCachedSizes = new SparseIntArray(); - private final SpacingDecoration mSpacingDecoration; public WidgetsRecyclerView(Context context) { this(context, null); @@ -70,9 +63,6 @@ public WidgetsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr super(context, attrs, defStyleAttr); mScrollbarTop = getResources().getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin); addOnItemTouchListener(this); - - mSpacingDecoration = new SpacingDecoration(context); - addItemDecoration(mSpacingDecoration); } @Override @@ -183,7 +173,7 @@ public void setHeaderViewDimensionsProvider( @Override protected int getItemsHeight(int untilIndex) { // Initialize cache - int childCount = getChildCount(); + int childCount = Math.min(getChildCount(), getAdapter().getItemCount()); int startPosition; if (childCount > 0 && ((startPosition = getChildAdapterPosition(getChildAt(0))) != NO_POSITION)) { @@ -200,7 +190,7 @@ protected int getItemsHeight(int untilIndex) { int totalItemsHeight = 0; for (int i = 0; i < untilIndex; i++) { int type = mAdapter.getItemViewType(i); - totalItemsHeight += mCachedSizes.get(type) + mSpacingDecoration.getSpacing(i, type); + totalItemsHeight += mCachedSizes.get(type); } return totalItemsHeight; } @@ -216,31 +206,4 @@ public interface HeaderViewDimensionsProvider { */ int getHeaderViewHeight(); } - - private static class SpacingDecoration extends RecyclerView.ItemDecoration { - - private final int mSpacingBetweenEntries; - - SpacingDecoration(@NonNull Context context) { - mSpacingBetweenEntries = - context.getResources().getDimensionPixelSize(R.dimen.widget_list_entry_spacing); - } - - @Override - public void getItemOffsets( - @NonNull Rect outRect, - @NonNull View view, - @NonNull RecyclerView parent, - @NonNull RecyclerView.State state) { - super.getItemOffsets(outRect, view, parent, state); - int position = parent.getChildAdapterPosition(view); - outRect.top += getSpacing(position, parent.getAdapter().getItemViewType(position)); - } - - public int getSpacing(int position, int type) { - boolean isHeader = type == VIEW_TYPE_WIDGETS_SEARCH_HEADER - || type == VIEW_TYPE_WIDGETS_HEADER; - return position > 0 && isHeader ? mSpacingBetweenEntries : 0; - } - } } From 2294c05c451cae78718071893d585758c1b948ad Mon Sep 17 00:00:00 2001 From: Stefan Andonian Date: Tue, 21 Feb 2023 18:10:08 +0000 Subject: [PATCH 03/44] Revert "Migrate IDP_GRID_NAME usage to LauncherPrefs" This reverts commit 6f9a57186c53fe3352a12a27e566ffff3c5c64e0. Reason for revert: A Bug where only device preferences were being used, not the main shared preference file. Bug: 269569568 Test: Verified this on device. Change-Id: I8422b2d7073537bd46c3a91033bd2281bbd306b7 (cherry picked from commit df11959779ca08a48308d9e390eb5b3fdb4bbf35) Merged-In: I8422b2d7073537bd46c3a91033bd2281bbd306b7 --- .../launcher3/InvariantDeviceProfile.java | 13 +++-- src/com/android/launcher3/LauncherPrefs.kt | 52 +++++++++---------- .../android/launcher3/LauncherPrefsTest.kt | 2 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 2fb0fa62079..604c1b87e68 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -16,7 +16,6 @@ package com.android.launcher3; -import static com.android.launcher3.LauncherPrefs.GRID_NAME; import static com.android.launcher3.Utilities.dpiFromPx; import static com.android.launcher3.config.FeatureFlags.ENABLE_DEVICE_PROFILE_LOGGING; import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME; @@ -94,6 +93,8 @@ public class InvariantDeviceProfile { public static final int TYPE_MULTI_DISPLAY = 1; public static final int TYPE_TABLET = 2; + private static final String KEY_IDP_GRID_NAME = "idp_grid_name"; + private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48; // Constants that affects the interpolation curve between statically defined device profile @@ -206,7 +207,8 @@ private InvariantDeviceProfile(Context context) { String gridName = getCurrentGridName(context); String newGridName = initGrid(context, gridName); if (!newGridName.equals(gridName)) { - LauncherPrefs.get(context).put(GRID_NAME, newGridName); + LauncherPrefs.getPrefs(context).edit().putString(KEY_IDP_GRID_NAME, newGridName) + .apply(); } new DeviceGridState(this).writeToPrefs(context); @@ -314,7 +316,7 @@ public void reinitializeAfterRestore(Context context) { } public static String getCurrentGridName(Context context) { - return LauncherPrefs.get(context).get(GRID_NAME); + return LauncherPrefs.getPrefs(context).getString(KEY_IDP_GRID_NAME, null); } private String initGrid(Context context, String gridName) { @@ -456,8 +458,9 @@ public void removeOnChangeListener(OnIDPChangeListener listener) { public void setCurrentGrid(Context context, String gridName) { - LauncherPrefs.get(context).put(GRID_NAME, gridName); - MAIN_EXECUTOR.execute(() -> onConfigChanged(context.getApplicationContext())); + Context appContext = context.getApplicationContext(); + LauncherPrefs.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply(); + MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext)); } private Object[] toModelState() { diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt index befaa64d506..2e07e3022a7 100644 --- a/src/com/android/launcher3/LauncherPrefs.kt +++ b/src/com/android/launcher3/LauncherPrefs.kt @@ -4,8 +4,6 @@ import android.content.Context import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener import androidx.annotation.VisibleForTesting -import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY -import com.android.launcher3.LauncherFiles.SHARED_PREFERENCES_KEY import com.android.launcher3.allapps.WorkProfileManager import com.android.launcher3.model.DeviceGridState import com.android.launcher3.pm.InstallSessionHelper @@ -22,10 +20,11 @@ import com.android.launcher3.util.Themes class LauncherPrefs(private val context: Context) { /** Wrapper around `getInner` for a `ContextualItem` */ - fun get(item: ContextualItem): T = getInner(item, item.defaultValueFromContext(context)) + fun get(item: ContextualItem): T = + getInner(item, item.defaultValueFromContext(context)) /** Wrapper around `getInner` for an `Item` */ - fun get(item: ConstantItem): T = getInner(item, item.defaultValue) + fun get(item: ConstantItem): T = getInner(item, item.defaultValue) /** * Retrieves the value for an [Item] from [SharedPreferences]. It handles method typing via the @@ -33,11 +32,11 @@ class LauncherPrefs(private val context: Context) { * `String`, `Boolean`, `Float`, `Int`, `Long`, or `Set`. */ @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST") - private fun getInner(item: Item, default: T): T { + private fun getInner(item: Item, default: T): T { val sp = context.getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE) - return when (item.type) { - String::class.java -> sp.getString(item.sharedPrefKey, default as? String) + return when (default::class.java) { + String::class.java -> sp.getString(item.sharedPrefKey, default as String) Boolean::class.java, java.lang.Boolean::class.java -> sp.getBoolean(item.sharedPrefKey, default as Boolean) Int::class.java, @@ -46,10 +45,11 @@ class LauncherPrefs(private val context: Context) { java.lang.Float::class.java -> sp.getFloat(item.sharedPrefKey, default as Float) Long::class.java, java.lang.Long::class.java -> sp.getLong(item.sharedPrefKey, default as Long) - Set::class.java -> sp.getStringSet(item.sharedPrefKey, default as? Set) + Set::class.java -> sp.getStringSet(item.sharedPrefKey, default as Set) else -> throw IllegalArgumentException( - "item type: ${item.type}" + " is not compatible with sharedPref methods" + "item type: ${default::class.java}" + + " is not compatible with sharedPref methods" ) } as T @@ -224,36 +224,39 @@ class LauncherPrefs(private val context: Context) { backedUpItem(RestoreDbTask.RESTORED_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE) @JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "") @JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "") - @JvmField val GRID_NAME = ConstantItem("idp_grid_name", true, null, String::class.java) @JvmField val ALLOW_ROTATION = - backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) { + backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY) { RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info) } @VisibleForTesting @JvmStatic fun backedUpItem(sharedPrefKey: String, defaultValue: T): ConstantItem = - ConstantItem(sharedPrefKey, true, defaultValue) + ConstantItem(sharedPrefKey, LauncherFiles.SHARED_PREFERENCES_KEY, defaultValue) @JvmStatic fun backedUpItem( sharedPrefKey: String, - type: Class, defaultValueFromContext: (c: Context) -> T - ): ContextualItem = ContextualItem(sharedPrefKey, true, defaultValueFromContext, type) + ): ContextualItem = + ContextualItem( + sharedPrefKey, + LauncherFiles.SHARED_PREFERENCES_KEY, + defaultValueFromContext + ) @VisibleForTesting @JvmStatic fun nonRestorableItem(sharedPrefKey: String, defaultValue: T): ConstantItem = - ConstantItem(sharedPrefKey, false, defaultValue) + ConstantItem(sharedPrefKey, LauncherFiles.DEVICE_PREFERENCES_KEY, defaultValue) @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") @JvmStatic fun getPrefs(context: Context): SharedPreferences { // Use application context for shared preferences, so we use single cached instance return context.applicationContext.getSharedPreferences( - SHARED_PREFERENCES_KEY, + LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE ) } @@ -263,7 +266,7 @@ class LauncherPrefs(private val context: Context) { fun getDevicePrefs(context: Context): SharedPreferences { // Use application context for shared preferences, so we use a single cached instance return context.applicationContext.getSharedPreferences( - DEVICE_PREFERENCES_KEY, + LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE ) } @@ -272,26 +275,21 @@ class LauncherPrefs(private val context: Context) { abstract class Item { abstract val sharedPrefKey: String - abstract val isBackedUp: Boolean - abstract val type: Class<*> - val sharedPrefFile: String = if (isBackedUp) SHARED_PREFERENCES_KEY else DEVICE_PREFERENCES_KEY + abstract val sharedPrefFile: String fun to(value: T): Pair = Pair(this, value) } data class ConstantItem( override val sharedPrefKey: String, - override val isBackedUp: Boolean, - val defaultValue: T, - // The default value can be null. If so, the type needs to be explicitly stated, or else NPE - override val type: Class = defaultValue!!::class.java + override val sharedPrefFile: String, + val defaultValue: T ) : Item() data class ContextualItem( override val sharedPrefKey: String, - override val isBackedUp: Boolean, - private val defaultSupplier: (c: Context) -> T, - override val type: Class + override val sharedPrefFile: String, + private val defaultSupplier: (c: Context) -> T ) : Item() { private var default: T? = null diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/src/com/android/launcher3/LauncherPrefsTest.kt index d40a7bcf8ca..31e8d3099b3 100644 --- a/tests/src/com/android/launcher3/LauncherPrefsTest.kt +++ b/tests/src/com/android/launcher3/LauncherPrefsTest.kt @@ -13,7 +13,7 @@ import org.junit.runner.RunWith private val TEST_BOOLEAN_ITEM = LauncherPrefs.nonRestorableItem("1", false) private val TEST_STRING_ITEM = LauncherPrefs.nonRestorableItem("2", "( ͡❛ ͜ʖ ͡❛)") private val TEST_INT_ITEM = LauncherPrefs.nonRestorableItem("3", -1) -private val TEST_CONTEXTUAL_ITEM = ContextualItem("4", true, { true }, Boolean::class.java) +private val TEST_CONTEXTUAL_ITEM = LauncherPrefs.backedUpItem("4") { true } @SmallTest @RunWith(AndroidJUnit4::class) From cce551df7b9bb20dae70a5e61ac8e9c0e6d46b9a Mon Sep 17 00:00:00 2001 From: Stefan Andonian Date: Tue, 21 Feb 2023 18:10:08 +0000 Subject: [PATCH 04/44] Revert "Migrate IDP_GRID_NAME usage to LauncherPrefs" This reverts commit 6f9a57186c53fe3352a12a27e566ffff3c5c64e0. Reason for revert: A Bug where only device preferences were being used, not the main shared preference file. Bug: 269569568 Test: Verified this on device. Change-Id: I8422b2d7073537bd46c3a91033bd2281bbd306b7 (cherry picked from commit df11959779ca08a48308d9e390eb5b3fdb4bbf35) Merged-In: I8422b2d7073537bd46c3a91033bd2281bbd306b7 --- .../launcher3/InvariantDeviceProfile.java | 13 +++-- src/com/android/launcher3/LauncherPrefs.kt | 52 +++++++++---------- .../android/launcher3/LauncherPrefsTest.kt | 2 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 2fb0fa62079..604c1b87e68 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -16,7 +16,6 @@ package com.android.launcher3; -import static com.android.launcher3.LauncherPrefs.GRID_NAME; import static com.android.launcher3.Utilities.dpiFromPx; import static com.android.launcher3.config.FeatureFlags.ENABLE_DEVICE_PROFILE_LOGGING; import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME; @@ -94,6 +93,8 @@ public class InvariantDeviceProfile { public static final int TYPE_MULTI_DISPLAY = 1; public static final int TYPE_TABLET = 2; + private static final String KEY_IDP_GRID_NAME = "idp_grid_name"; + private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48; // Constants that affects the interpolation curve between statically defined device profile @@ -206,7 +207,8 @@ private InvariantDeviceProfile(Context context) { String gridName = getCurrentGridName(context); String newGridName = initGrid(context, gridName); if (!newGridName.equals(gridName)) { - LauncherPrefs.get(context).put(GRID_NAME, newGridName); + LauncherPrefs.getPrefs(context).edit().putString(KEY_IDP_GRID_NAME, newGridName) + .apply(); } new DeviceGridState(this).writeToPrefs(context); @@ -314,7 +316,7 @@ public void reinitializeAfterRestore(Context context) { } public static String getCurrentGridName(Context context) { - return LauncherPrefs.get(context).get(GRID_NAME); + return LauncherPrefs.getPrefs(context).getString(KEY_IDP_GRID_NAME, null); } private String initGrid(Context context, String gridName) { @@ -456,8 +458,9 @@ public void removeOnChangeListener(OnIDPChangeListener listener) { public void setCurrentGrid(Context context, String gridName) { - LauncherPrefs.get(context).put(GRID_NAME, gridName); - MAIN_EXECUTOR.execute(() -> onConfigChanged(context.getApplicationContext())); + Context appContext = context.getApplicationContext(); + LauncherPrefs.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply(); + MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext)); } private Object[] toModelState() { diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt index befaa64d506..2e07e3022a7 100644 --- a/src/com/android/launcher3/LauncherPrefs.kt +++ b/src/com/android/launcher3/LauncherPrefs.kt @@ -4,8 +4,6 @@ import android.content.Context import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener import androidx.annotation.VisibleForTesting -import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY -import com.android.launcher3.LauncherFiles.SHARED_PREFERENCES_KEY import com.android.launcher3.allapps.WorkProfileManager import com.android.launcher3.model.DeviceGridState import com.android.launcher3.pm.InstallSessionHelper @@ -22,10 +20,11 @@ import com.android.launcher3.util.Themes class LauncherPrefs(private val context: Context) { /** Wrapper around `getInner` for a `ContextualItem` */ - fun get(item: ContextualItem): T = getInner(item, item.defaultValueFromContext(context)) + fun get(item: ContextualItem): T = + getInner(item, item.defaultValueFromContext(context)) /** Wrapper around `getInner` for an `Item` */ - fun get(item: ConstantItem): T = getInner(item, item.defaultValue) + fun get(item: ConstantItem): T = getInner(item, item.defaultValue) /** * Retrieves the value for an [Item] from [SharedPreferences]. It handles method typing via the @@ -33,11 +32,11 @@ class LauncherPrefs(private val context: Context) { * `String`, `Boolean`, `Float`, `Int`, `Long`, or `Set`. */ @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST") - private fun getInner(item: Item, default: T): T { + private fun getInner(item: Item, default: T): T { val sp = context.getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE) - return when (item.type) { - String::class.java -> sp.getString(item.sharedPrefKey, default as? String) + return when (default::class.java) { + String::class.java -> sp.getString(item.sharedPrefKey, default as String) Boolean::class.java, java.lang.Boolean::class.java -> sp.getBoolean(item.sharedPrefKey, default as Boolean) Int::class.java, @@ -46,10 +45,11 @@ class LauncherPrefs(private val context: Context) { java.lang.Float::class.java -> sp.getFloat(item.sharedPrefKey, default as Float) Long::class.java, java.lang.Long::class.java -> sp.getLong(item.sharedPrefKey, default as Long) - Set::class.java -> sp.getStringSet(item.sharedPrefKey, default as? Set) + Set::class.java -> sp.getStringSet(item.sharedPrefKey, default as Set) else -> throw IllegalArgumentException( - "item type: ${item.type}" + " is not compatible with sharedPref methods" + "item type: ${default::class.java}" + + " is not compatible with sharedPref methods" ) } as T @@ -224,36 +224,39 @@ class LauncherPrefs(private val context: Context) { backedUpItem(RestoreDbTask.RESTORED_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE) @JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "") @JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "") - @JvmField val GRID_NAME = ConstantItem("idp_grid_name", true, null, String::class.java) @JvmField val ALLOW_ROTATION = - backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) { + backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY) { RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info) } @VisibleForTesting @JvmStatic fun backedUpItem(sharedPrefKey: String, defaultValue: T): ConstantItem = - ConstantItem(sharedPrefKey, true, defaultValue) + ConstantItem(sharedPrefKey, LauncherFiles.SHARED_PREFERENCES_KEY, defaultValue) @JvmStatic fun backedUpItem( sharedPrefKey: String, - type: Class, defaultValueFromContext: (c: Context) -> T - ): ContextualItem = ContextualItem(sharedPrefKey, true, defaultValueFromContext, type) + ): ContextualItem = + ContextualItem( + sharedPrefKey, + LauncherFiles.SHARED_PREFERENCES_KEY, + defaultValueFromContext + ) @VisibleForTesting @JvmStatic fun nonRestorableItem(sharedPrefKey: String, defaultValue: T): ConstantItem = - ConstantItem(sharedPrefKey, false, defaultValue) + ConstantItem(sharedPrefKey, LauncherFiles.DEVICE_PREFERENCES_KEY, defaultValue) @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") @JvmStatic fun getPrefs(context: Context): SharedPreferences { // Use application context for shared preferences, so we use single cached instance return context.applicationContext.getSharedPreferences( - SHARED_PREFERENCES_KEY, + LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE ) } @@ -263,7 +266,7 @@ class LauncherPrefs(private val context: Context) { fun getDevicePrefs(context: Context): SharedPreferences { // Use application context for shared preferences, so we use a single cached instance return context.applicationContext.getSharedPreferences( - DEVICE_PREFERENCES_KEY, + LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE ) } @@ -272,26 +275,21 @@ class LauncherPrefs(private val context: Context) { abstract class Item { abstract val sharedPrefKey: String - abstract val isBackedUp: Boolean - abstract val type: Class<*> - val sharedPrefFile: String = if (isBackedUp) SHARED_PREFERENCES_KEY else DEVICE_PREFERENCES_KEY + abstract val sharedPrefFile: String fun to(value: T): Pair = Pair(this, value) } data class ConstantItem( override val sharedPrefKey: String, - override val isBackedUp: Boolean, - val defaultValue: T, - // The default value can be null. If so, the type needs to be explicitly stated, or else NPE - override val type: Class = defaultValue!!::class.java + override val sharedPrefFile: String, + val defaultValue: T ) : Item() data class ContextualItem( override val sharedPrefKey: String, - override val isBackedUp: Boolean, - private val defaultSupplier: (c: Context) -> T, - override val type: Class + override val sharedPrefFile: String, + private val defaultSupplier: (c: Context) -> T ) : Item() { private var default: T? = null diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/src/com/android/launcher3/LauncherPrefsTest.kt index d40a7bcf8ca..31e8d3099b3 100644 --- a/tests/src/com/android/launcher3/LauncherPrefsTest.kt +++ b/tests/src/com/android/launcher3/LauncherPrefsTest.kt @@ -13,7 +13,7 @@ import org.junit.runner.RunWith private val TEST_BOOLEAN_ITEM = LauncherPrefs.nonRestorableItem("1", false) private val TEST_STRING_ITEM = LauncherPrefs.nonRestorableItem("2", "( ͡❛ ͜ʖ ͡❛)") private val TEST_INT_ITEM = LauncherPrefs.nonRestorableItem("3", -1) -private val TEST_CONTEXTUAL_ITEM = ContextualItem("4", true, { true }, Boolean::class.java) +private val TEST_CONTEXTUAL_ITEM = LauncherPrefs.backedUpItem("4") { true } @SmallTest @RunWith(AndroidJUnit4::class) From 21cec7e9ffbeedddbd761aeee1772d50d38aa3d9 Mon Sep 17 00:00:00 2001 From: Stefan Andonian Date: Tue, 21 Feb 2023 18:10:08 +0000 Subject: [PATCH 05/44] Revert "Migrate IDP_GRID_NAME usage to LauncherPrefs" This reverts commit 6f9a57186c53fe3352a12a27e566ffff3c5c64e0. Reason for revert: A Bug where only device preferences were being used, not the main shared preference file. Bug: 269569568 Test: Verified this on device. Change-Id: I8422b2d7073537bd46c3a91033bd2281bbd306b7 (cherry picked from commit df11959779ca08a48308d9e390eb5b3fdb4bbf35) Merged-In: I8422b2d7073537bd46c3a91033bd2281bbd306b7 --- .../launcher3/InvariantDeviceProfile.java | 13 +++-- src/com/android/launcher3/LauncherPrefs.kt | 52 +++++++++---------- .../android/launcher3/LauncherPrefsTest.kt | 2 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 2fb0fa62079..604c1b87e68 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -16,7 +16,6 @@ package com.android.launcher3; -import static com.android.launcher3.LauncherPrefs.GRID_NAME; import static com.android.launcher3.Utilities.dpiFromPx; import static com.android.launcher3.config.FeatureFlags.ENABLE_DEVICE_PROFILE_LOGGING; import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME; @@ -94,6 +93,8 @@ public class InvariantDeviceProfile { public static final int TYPE_MULTI_DISPLAY = 1; public static final int TYPE_TABLET = 2; + private static final String KEY_IDP_GRID_NAME = "idp_grid_name"; + private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48; // Constants that affects the interpolation curve between statically defined device profile @@ -206,7 +207,8 @@ private InvariantDeviceProfile(Context context) { String gridName = getCurrentGridName(context); String newGridName = initGrid(context, gridName); if (!newGridName.equals(gridName)) { - LauncherPrefs.get(context).put(GRID_NAME, newGridName); + LauncherPrefs.getPrefs(context).edit().putString(KEY_IDP_GRID_NAME, newGridName) + .apply(); } new DeviceGridState(this).writeToPrefs(context); @@ -314,7 +316,7 @@ public void reinitializeAfterRestore(Context context) { } public static String getCurrentGridName(Context context) { - return LauncherPrefs.get(context).get(GRID_NAME); + return LauncherPrefs.getPrefs(context).getString(KEY_IDP_GRID_NAME, null); } private String initGrid(Context context, String gridName) { @@ -456,8 +458,9 @@ public void removeOnChangeListener(OnIDPChangeListener listener) { public void setCurrentGrid(Context context, String gridName) { - LauncherPrefs.get(context).put(GRID_NAME, gridName); - MAIN_EXECUTOR.execute(() -> onConfigChanged(context.getApplicationContext())); + Context appContext = context.getApplicationContext(); + LauncherPrefs.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply(); + MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext)); } private Object[] toModelState() { diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt index befaa64d506..2e07e3022a7 100644 --- a/src/com/android/launcher3/LauncherPrefs.kt +++ b/src/com/android/launcher3/LauncherPrefs.kt @@ -4,8 +4,6 @@ import android.content.Context import android.content.SharedPreferences import android.content.SharedPreferences.OnSharedPreferenceChangeListener import androidx.annotation.VisibleForTesting -import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY -import com.android.launcher3.LauncherFiles.SHARED_PREFERENCES_KEY import com.android.launcher3.allapps.WorkProfileManager import com.android.launcher3.model.DeviceGridState import com.android.launcher3.pm.InstallSessionHelper @@ -22,10 +20,11 @@ import com.android.launcher3.util.Themes class LauncherPrefs(private val context: Context) { /** Wrapper around `getInner` for a `ContextualItem` */ - fun get(item: ContextualItem): T = getInner(item, item.defaultValueFromContext(context)) + fun get(item: ContextualItem): T = + getInner(item, item.defaultValueFromContext(context)) /** Wrapper around `getInner` for an `Item` */ - fun get(item: ConstantItem): T = getInner(item, item.defaultValue) + fun get(item: ConstantItem): T = getInner(item, item.defaultValue) /** * Retrieves the value for an [Item] from [SharedPreferences]. It handles method typing via the @@ -33,11 +32,11 @@ class LauncherPrefs(private val context: Context) { * `String`, `Boolean`, `Float`, `Int`, `Long`, or `Set`. */ @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST") - private fun getInner(item: Item, default: T): T { + private fun getInner(item: Item, default: T): T { val sp = context.getSharedPreferences(item.sharedPrefFile, Context.MODE_PRIVATE) - return when (item.type) { - String::class.java -> sp.getString(item.sharedPrefKey, default as? String) + return when (default::class.java) { + String::class.java -> sp.getString(item.sharedPrefKey, default as String) Boolean::class.java, java.lang.Boolean::class.java -> sp.getBoolean(item.sharedPrefKey, default as Boolean) Int::class.java, @@ -46,10 +45,11 @@ class LauncherPrefs(private val context: Context) { java.lang.Float::class.java -> sp.getFloat(item.sharedPrefKey, default as Float) Long::class.java, java.lang.Long::class.java -> sp.getLong(item.sharedPrefKey, default as Long) - Set::class.java -> sp.getStringSet(item.sharedPrefKey, default as? Set) + Set::class.java -> sp.getStringSet(item.sharedPrefKey, default as Set) else -> throw IllegalArgumentException( - "item type: ${item.type}" + " is not compatible with sharedPref methods" + "item type: ${default::class.java}" + + " is not compatible with sharedPref methods" ) } as T @@ -224,36 +224,39 @@ class LauncherPrefs(private val context: Context) { backedUpItem(RestoreDbTask.RESTORED_DEVICE_TYPE, InvariantDeviceProfile.TYPE_PHONE) @JvmField val APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_IDS, "") @JvmField val OLD_APP_WIDGET_IDS = backedUpItem(RestoreDbTask.APPWIDGET_OLD_IDS, "") - @JvmField val GRID_NAME = ConstantItem("idp_grid_name", true, null, String::class.java) @JvmField val ALLOW_ROTATION = - backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) { + backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY) { RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info) } @VisibleForTesting @JvmStatic fun backedUpItem(sharedPrefKey: String, defaultValue: T): ConstantItem = - ConstantItem(sharedPrefKey, true, defaultValue) + ConstantItem(sharedPrefKey, LauncherFiles.SHARED_PREFERENCES_KEY, defaultValue) @JvmStatic fun backedUpItem( sharedPrefKey: String, - type: Class, defaultValueFromContext: (c: Context) -> T - ): ContextualItem = ContextualItem(sharedPrefKey, true, defaultValueFromContext, type) + ): ContextualItem = + ContextualItem( + sharedPrefKey, + LauncherFiles.SHARED_PREFERENCES_KEY, + defaultValueFromContext + ) @VisibleForTesting @JvmStatic fun nonRestorableItem(sharedPrefKey: String, defaultValue: T): ConstantItem = - ConstantItem(sharedPrefKey, false, defaultValue) + ConstantItem(sharedPrefKey, LauncherFiles.DEVICE_PREFERENCES_KEY, defaultValue) @Deprecated("Don't use shared preferences directly. Use other LauncherPref methods.") @JvmStatic fun getPrefs(context: Context): SharedPreferences { // Use application context for shared preferences, so we use single cached instance return context.applicationContext.getSharedPreferences( - SHARED_PREFERENCES_KEY, + LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE ) } @@ -263,7 +266,7 @@ class LauncherPrefs(private val context: Context) { fun getDevicePrefs(context: Context): SharedPreferences { // Use application context for shared preferences, so we use a single cached instance return context.applicationContext.getSharedPreferences( - DEVICE_PREFERENCES_KEY, + LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE ) } @@ -272,26 +275,21 @@ class LauncherPrefs(private val context: Context) { abstract class Item { abstract val sharedPrefKey: String - abstract val isBackedUp: Boolean - abstract val type: Class<*> - val sharedPrefFile: String = if (isBackedUp) SHARED_PREFERENCES_KEY else DEVICE_PREFERENCES_KEY + abstract val sharedPrefFile: String fun to(value: T): Pair = Pair(this, value) } data class ConstantItem( override val sharedPrefKey: String, - override val isBackedUp: Boolean, - val defaultValue: T, - // The default value can be null. If so, the type needs to be explicitly stated, or else NPE - override val type: Class = defaultValue!!::class.java + override val sharedPrefFile: String, + val defaultValue: T ) : Item() data class ContextualItem( override val sharedPrefKey: String, - override val isBackedUp: Boolean, - private val defaultSupplier: (c: Context) -> T, - override val type: Class + override val sharedPrefFile: String, + private val defaultSupplier: (c: Context) -> T ) : Item() { private var default: T? = null diff --git a/tests/src/com/android/launcher3/LauncherPrefsTest.kt b/tests/src/com/android/launcher3/LauncherPrefsTest.kt index d40a7bcf8ca..31e8d3099b3 100644 --- a/tests/src/com/android/launcher3/LauncherPrefsTest.kt +++ b/tests/src/com/android/launcher3/LauncherPrefsTest.kt @@ -13,7 +13,7 @@ import org.junit.runner.RunWith private val TEST_BOOLEAN_ITEM = LauncherPrefs.nonRestorableItem("1", false) private val TEST_STRING_ITEM = LauncherPrefs.nonRestorableItem("2", "( ͡❛ ͜ʖ ͡❛)") private val TEST_INT_ITEM = LauncherPrefs.nonRestorableItem("3", -1) -private val TEST_CONTEXTUAL_ITEM = ContextualItem("4", true, { true }, Boolean::class.java) +private val TEST_CONTEXTUAL_ITEM = LauncherPrefs.backedUpItem("4") { true } @SmallTest @RunWith(AndroidJUnit4::class) From 41d57e9fcf637820ee59387192c80090bcbada61 Mon Sep 17 00:00:00 2001 From: Sam Dubey Date: Mon, 20 Mar 2023 16:10:58 +0000 Subject: [PATCH 06/44] Revert "Move recents animation controller to shell" Revert submission 21912191-recents_to_shell Reason for revert: Testing b/274454574 Reverted changes: /q/submissionid:21912191-recents_to_shell Change-Id: If1732c1f539a973a2ef0dc0f05302fcaaf366300 (cherry picked from commit on googleplex-android-review.googlesource.com host: 1c52543678526aaae4a14bea7bdab12a92302aab) Merged-In: If1732c1f539a973a2ef0dc0f05302fcaaf366300 --- .../com/android/quickstep/SystemUiProxy.java | 55 ------------------- .../quickstep/TaskAnimationManager.java | 8 ++- 2 files changed, 6 insertions(+), 57 deletions(-) diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index d8f49fffddc..52b32d77858 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -21,7 +21,6 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.app.ActivityManager; -import android.app.ActivityOptions; import android.app.PendingIntent; import android.app.PictureInPictureParams; import android.content.ComponentName; @@ -39,8 +38,6 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; -import android.view.IRecentsAnimationController; -import android.view.IRecentsAnimationRunner; import android.view.IRemoteAnimationRunner; import android.view.MotionEvent; import android.view.RemoteAnimationAdapter; @@ -48,7 +45,6 @@ import android.view.SurfaceControl; import android.window.IOnBackInvokedCallback; import android.window.RemoteTransition; -import android.window.TaskSnapshot; import android.window.TransitionFilter; import androidx.annotation.Nullable; @@ -59,9 +55,6 @@ import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.systemui.shared.recents.ISystemUiProxy; -import com.android.systemui.shared.recents.model.ThumbnailData; -import com.android.systemui.shared.system.RecentsAnimationControllerCompat; -import com.android.systemui.shared.system.RecentsAnimationListener; import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController; import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController; import com.android.systemui.shared.system.smartspace.SmartspaceState; @@ -142,20 +135,9 @@ public class SystemUiProxy implements ISystemUiProxy { // TODO(141886704): Find a way to remove this private int mLastSystemUiStateFlags; - /** - * This is a singleton pending intent that is used to start recents via Shell (which is a - * different process). It is bare-bones, so it's expected that the component and options will - * be provided via fill-in intent. - */ - private final PendingIntent mRecentsPendingIntent; - public SystemUiProxy(Context context) { mContext = context; mAsyncHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessageAsync); - final Intent baseIntent = new Intent().setPackage(mContext.getPackageName()); - mRecentsPendingIntent = PendingIntent.getActivity(mContext, 0, baseIntent, - PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT - | Intent.FILL_IN_COMPONENT); } @Override @@ -1097,41 +1079,4 @@ public void setUnfoldAnimationListener(IUnfoldTransitionListener callback) { Log.e(TAG, "Failed call setUnfoldAnimationListener", e); } } - - - /** - * Starts the recents activity. The caller should manage the thread on which this is called. - */ - public boolean startRecentsActivity(Intent intent, ActivityOptions options, - RecentsAnimationListener listener) { - final IRecentsAnimationRunner runner = new IRecentsAnimationRunner.Stub() { - @Override - public void onAnimationStart(IRecentsAnimationController controller, - RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, - Rect homeContentInsets, Rect minimizedHomeBounds) { - listener.onAnimationStart(new RecentsAnimationControllerCompat(controller), apps, - wallpapers, homeContentInsets, minimizedHomeBounds); - } - - @Override - public void onAnimationCanceled(int[] taskIds, TaskSnapshot[] taskSnapshots) { - listener.onAnimationCanceled( - ThumbnailData.wrap(taskIds, taskSnapshots)); - } - - @Override - public void onTasksAppeared(RemoteAnimationTarget[] apps) { - listener.onTasksAppeared(apps); - } - }; - final Bundle optsBundle = options.toBundle(); - try { - mRecentTasks.startRecentsTransition(mRecentsPendingIntent, intent, optsBundle, - mContext.getIApplicationThread(), runner); - } catch (RemoteException e) { - Log.e(TAG, "Error starting recents via shell", e); - return false; - } - return true; - } } diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 5010ea564eb..2c95516b686 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -22,6 +22,7 @@ import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED; import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION; +import static com.android.systemui.shared.system.RemoteTransitionCompat.newRemoteTransition; import android.app.ActivityManager; import android.app.ActivityOptions; @@ -30,6 +31,7 @@ import android.os.SystemProperties; import android.util.Log; import android.view.RemoteAnimationTarget; +import android.window.RemoteTransition; import androidx.annotation.Nullable; import androidx.annotation.UiThread; @@ -228,7 +230,9 @@ public boolean onSwitchToScreenshot(Runnable onFinished) { mCallbacks.addListener(listener); if (ENABLE_SHELL_TRANSITIONS) { - final ActivityOptions options = ActivityOptions.makeBasic(); + RemoteTransition transition = newRemoteTransition(mCallbacks, + mCtx.getIApplicationThread()); + final ActivityOptions options = ActivityOptions.makeRemoteTransition(transition); // Allowing to pause Home if Home is top activity and Recents is not Home. So when user // start home when recents animation is playing, the home activity can be resumed again // to let the transition controller collect Home activity. @@ -244,7 +248,7 @@ public boolean onSwitchToScreenshot(Runnable onFinished) { options.setTransientLaunch(); } options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime); - SystemUiProxy.INSTANCE.getNoCreate().startRecentsActivity(intent, options, mCallbacks); + UI_HELPER_EXECUTOR.execute(() -> mCtx.startActivity(intent, options.toBundle())); } else { UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance() .startRecentsActivity(intent, eventTime, mCallbacks, null, null)); From cdac560c87c5980c046a5f22a28d3d8b84b0dd5a Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Tue, 30 May 2023 18:06:36 +0000 Subject: [PATCH 07/44] Enabled trackpad gestures To be cherrypicked (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:55140bd010203a60cdec8378bdacc90e010c6f02) Merged-In: Id6831da122398de34ddaae8134995aa42be5eae6 Change-Id: Id6831da122398de34ddaae8134995aa42be5eae6 --- 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 621c2abb906..edf41c34b31 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -381,7 +381,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable initiating split screen from workspace to workspace."); public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401, - "ENABLE_TRACKPAD_GESTURE", DISABLED, "Enables trackpad gesture."); + "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture."); // TODO(Block 29): Clean up flags public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897, From 5148c096e1f99d2c88158ba5b6deb3c50a01e587 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 26 Jun 2023 07:08:08 +0000 Subject: [PATCH 08/44] Fix NPE due to invalid RecentsView access Fixes: 288829919 Test: N/a, reorganizing code behind null check (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:cdf410f1349edf3451e1a8af64ea2d8cd676ffaa) Merged-In: I9efe48cab239b521f7e729af06706c352be2499c Change-Id: I9efe48cab239b521f7e729af06706c352be2499c --- .../com/android/quickstep/views/TaskView.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 17d83ec208e..83a5c721279 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -841,17 +841,20 @@ public void launchTask(@NonNull Consumer callback, boolean isQuickswitc // the actual overview state failureListener.register(mActivity, mTask.key.id, () -> { notifyTaskLaunchFailed(TAG); - // Disable animations for now, as it is an edge case and the app usually covers - // launcher and also any state transition animation also gets clobbered by - // QuickstepTransitionManager.createWallpaperOpenAnimations when launcher - // shows again - getRecentsView().startHome(false /* animated */); RecentsView rv = getRecentsView(); - if (rv != null && rv.mSizeStrategy.getTaskbarController() != null) { - // LauncherTaskbarUIController depends on the launcher state when checking - // whether to handle resume, but that can come in before startHome() changes - // the state, so force-refresh here to ensure the taskbar is updated - rv.mSizeStrategy.getTaskbarController().refreshResumedState(); + if (rv != null) { + // Disable animations for now, as it is an edge case and the app usually + // covers launcher and also any state transition animation also gets + // clobbered by QuickstepTransitionManager.createWallpaperOpenAnimations + // when launcher shows again + rv.startHome(false /* animated */); + if (rv.mSizeStrategy.getTaskbarController() != null) { + // LauncherTaskbarUIController depends on the launcher state when + // checking whether to handle resume, but that can come in before + // startHome() changes the state, so force-refresh here to ensure the + // taskbar is updated + rv.mSizeStrategy.getTaskbarController().refreshResumedState(); + } } }); } From 18f815a7fda64344783c8b92be7d60153c2e50e8 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 23 Jun 2023 18:14:00 +0000 Subject: [PATCH 09/44] Restore strong reference to animation runner - The remote animation factory needs to be strongly referenced since the only other reference is a weakly held one from LauncherAnimationRunner, and if a gc happens in between starting the animation and the onAnimationStart() callback, then the animation will not play. Fixes: 284106887 Test: Force a gc after creating a remote app launch animation and ensure that the runner still exists when the animation starts (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6cfe2e6cbe52f5fc9aa0eb94afaeb7679810cc13) Merged-In: I5f584451b41c666916801b8ea0cb470c7ab9fc51 Change-Id: I5f584451b41c666916801b8ea0cb470c7ab9fc51 --- .../com/android/launcher3/QuickstepTransitionManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index e5fd6059046..33a9f48a82d 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -229,6 +229,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener private RemoteAnimationProvider mRemoteAnimationProvider; // Strong refs to runners which are cleared when the launcher activity is destroyed private RemoteAnimationFactory mWallpaperOpenRunner; + private RemoteAnimationFactory mAppLaunchRunner; private RemoteAnimationFactory mKeyguardGoingAwayRunner; private RemoteAnimationFactory mWallpaperOpenTransitionRunner; @@ -298,17 +299,17 @@ public ActivityOptionsWrapper getActivityLaunchOptions(View v) { boolean fromRecents = isLaunchingFromRecents(v, null /* targets */); RunnableList onEndCallback = new RunnableList(); - RemoteAnimationFactory delegateRunner = new AppLaunchAnimationRunner(v, onEndCallback); + mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback); ItemInfo tag = (ItemInfo) v.getTag(); if (tag != null && tag.shouldUseBackgroundAnimation()) { ContainerAnimationRunner containerAnimationRunner = ContainerAnimationRunner.from(v, mStartingWindowListener, onEndCallback); if (containerAnimationRunner != null) { - delegateRunner = containerAnimationRunner; + mAppLaunchRunner = containerAnimationRunner; } } RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner( - mHandler, delegateRunner, true /* startAtFrontOfQueue */); + mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */); // Note that this duration is a guess as we do not know if the animation will be a // recents launch or not for sure until we know the opening app targets. @@ -1164,6 +1165,7 @@ private void unregisterRemoteAnimations() { // Also clear strong references to the runners registered with the remote animation // definition so we don't have to wait for the system gc mWallpaperOpenRunner = null; + mAppLaunchRunner = null; mKeyguardGoingAwayRunner = null; } } From 8a7181d45ea5f3d4e228a92c4113585337264461 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Mon, 26 Jun 2023 12:23:08 +0000 Subject: [PATCH 10/44] Prevent exception when quick switching between two split pairs When switching in between two split pairs just quick enough, it is possible to send the second entering split transition while it is animating the first entering split transition which is merged to a recents-during-split transition. The split parents might not be collected into the second transition because the split parents are already visible at that time, and there is no recents transition to merge to. So updates to not throwing when there is no split parent when composing a recents-to-split animation. Bug: 236226779 Test: repro steps of the bug and the Launcher won't throw (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:97eb471f2efda1eccce7eba8c68301b2fa34c5e7) Merged-In: I3a595722721186e8de7d60c9fb8c099ec799804a Change-Id: I3a595722721186e8de7d60c9fb8c099ec799804a --- quickstep/src/com/android/quickstep/TaskViewUtils.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 499a2601a9f..1238819acdb 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -473,16 +473,14 @@ public void onAnimationEnd(Animator animation) { throw new IllegalStateException( "Expected task to be showing, but it is " + mode); } - if (change.getParent() == null) { - throw new IllegalStateException("Initiating multi-split launch but the split" - + "root of " + taskId + " is already visible or has broken hierarchy."); - } } if (taskId == initialTaskId) { - splitRoot1 = transitionInfo.getChange(change.getParent()); + splitRoot1 = change.getParent() == null ? change : + transitionInfo.getChange(change.getParent()); } if (taskId == secondTaskId) { - splitRoot2 = transitionInfo.getChange(change.getParent()); + splitRoot2 = change.getParent() == null ? change : + transitionInfo.getChange(change.getParent()); } } From 5cdfa120df03fd9d983c8469508d7d73bd1198c7 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Fri, 23 Jun 2023 16:34:32 +0000 Subject: [PATCH 11/44] Workaround for handling the restart of an already visible task - If a task is already visible, then startActivity is a no-op and the remote transition that launcher expects to run is not started. As a workaround (until restarts are an actual transition), listen for the case where a task is restarted and invoke the end callbacks Fixes: 286016555 Test: Repro steps on the bug (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:57c2a79e47bc583306bd77ea3039d821a8d33dde) Merged-In: Iec3ab97c8817a5e95399cec90f891d65f369d234 Change-Id: Iec3ab97c8817a5e95399cec90f891d65f369d234 --- .../launcher3/QuickstepTransitionManager.java | 7 ++ .../uioverrides/QuickstepLauncher.java | 8 ++- .../TaskRestartedDuringLaunchListener.java | 72 +++++++++++++++++++ 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 33a9f48a82d..dfea5159eb5 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -144,6 +144,7 @@ import com.android.quickstep.util.SurfaceTransaction; import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties; import com.android.quickstep.util.SurfaceTransactionApplier; +import com.android.quickstep.util.TaskRestartedDuringLaunchListener; import com.android.quickstep.util.WorkspaceRevealAnim; import com.android.quickstep.views.FloatingWidgetView; import com.android.quickstep.views.RecentsView; @@ -299,6 +300,12 @@ public ActivityOptionsWrapper getActivityLaunchOptions(View v) { boolean fromRecents = isLaunchingFromRecents(v, null /* targets */); RunnableList onEndCallback = new RunnableList(); + // Handle the case where an already visible task is launched which results in no transition + TaskRestartedDuringLaunchListener restartedListener = + new TaskRestartedDuringLaunchListener(); + restartedListener.register(onEndCallback::executeAllAndDestroy); + onEndCallback.add(restartedListener::unregister); + mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback); ItemInfo tag = (ItemInfo) v.getTag(); if (tag != null && tag.shouldUseBackgroundAnimation()) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 658bf2d865a..2f13c5de44d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -345,11 +345,13 @@ public void onConfigurationChanged(Configuration newConfig) { @Override public RunnableList startActivitySafely(View v, Intent intent, ItemInfo item) { - // Only pause is taskbar controller is not present + // Only pause is taskbar controller is not present until the transition (if it exists) ends mHotseatPredictionController.setPauseUIUpdate(getTaskbarUIController() == null); RunnableList result = super.startActivitySafely(v, intent, item); - if (getTaskbarUIController() == null && result == null) { - mHotseatPredictionController.setPauseUIUpdate(false); + if (result == null) { + if (getTaskbarUIController() == null) { + mHotseatPredictionController.setPauseUIUpdate(false); + } } else { result.add(() -> mHotseatPredictionController.setPauseUIUpdate(false)); } diff --git a/quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java b/quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java new file mode 100644 index 00000000000..91e83769901 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/TaskRestartedDuringLaunchListener.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2023 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.app.ActivityTaskManager.INVALID_TASK_ID; + +import android.app.Activity; +import android.app.ActivityManager; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter; +import com.android.quickstep.RecentsModel; +import com.android.systemui.shared.system.TaskStackChangeListener; +import com.android.systemui.shared.system.TaskStackChangeListeners; + +/** + * This class tracks the failure of a task launch through the Launcher.startActivitySafely() call, + * in an edge case in which a task may already be visible on screen (ie. in PIP) and no transition + * will be run in WM, which results in expected callbacks to not be processed. + * + * We transiently register a task stack listener during a task launch and if the restart signal is + * received, then the registered callback will be notified. + */ +public class TaskRestartedDuringLaunchListener implements TaskStackChangeListener { + + private static final String TAG = "TaskRestartedDuringLaunchListener"; + + private @NonNull Runnable mTaskRestartedCallback = null; + + /** + * Registers a failure listener callback if it detects a scenario in which an app launch + * resulted in an already existing task to be "restarted". + */ + public void register(@NonNull Runnable taskRestartedCallback) { + TaskStackChangeListeners.getInstance().registerTaskStackListener(this); + mTaskRestartedCallback = taskRestartedCallback; + } + + /** + * Unregisters the failure listener. + */ + public void unregister() { + TaskStackChangeListeners.getInstance().unregisterTaskStackListener(this); + mTaskRestartedCallback = null; + } + + @Override + public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, + boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { + if (wasVisible) { + Log.d(TAG, "Detected activity restart during launch for task=" + task.taskId); + mTaskRestartedCallback.run(); + unregister(); + } + } +} From 4fdf5684feebd99c4f0973db2df50be55934f5e8 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Tue, 27 Jun 2023 17:07:13 +0000 Subject: [PATCH 12/44] Polish home-key from split to pip transition Includes WINDOWING_MODE_MULTI_WINDOW closing target to the condition of playing fallback animation. So the remaining splitting task won't be play with iconview animation when home-key to auto-pip consumed another splitting task in pip transition handler. Bug: 281476331 Test: repro steps of the bug Test: pass existing tests Video: http://recall/-/fLARJNt42LVxc3tt86SneW/eelqATeE1REoOtOEDxeDVR (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:365105118220b218005225b038142273524877cc) Merged-In: If05d8841a6a940e61f71683422ef1a3d4e3597c7 Change-Id: If05d8841a6a940e61f71683422ef1a3d4e3597c7 --- .../launcher3/QuickstepTransitionManager.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index dfea5159eb5..ca9c5771b12 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -18,6 +18,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; @@ -1210,14 +1211,15 @@ private boolean launcherIsATargetWithMode(RemoteAnimationTarget[] targets, int m return false; } - private boolean hasMultipleTargetsWithMode(RemoteAnimationTarget[] targets, int mode) { + private boolean shouldPlayFallbackClosingAnimation(RemoteAnimationTarget[] targets) { int numTargets = 0; for (RemoteAnimationTarget target : targets) { - if (target.mode == mode) { + if (target.mode == MODE_CLOSING) { numTargets++; - } - if (numTargets > 1) { - return true; + if (numTargets > 1 || target.windowConfiguration.getWindowingMode() + == WINDOWING_MODE_MULTI_WINDOW) { + return true; + } } } return false; @@ -1604,7 +1606,7 @@ public Pair createWallpaperOpenAnimations( boolean playFallBackAnimation = (launcherView == null && launcherIsForceInvisibleOrOpening) || mLauncher.getWorkspace().isOverlayShown() - || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING); + || shouldPlayFallbackClosingAnimation(appTargets); boolean playWorkspaceReveal = true; boolean skipAllAppsScale = false; From 170ad5b4d61ed7df202c1633ebc00724320174cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ciche=C5=84ski?= Date: Tue, 27 Jun 2023 02:58:26 +0000 Subject: [PATCH 13/44] Remove the keep clear areas XML tag from Hotseat It reports its size through SystemUiProxy and this tag causes it to report the region twice. Additionally upon screen rotation the value is getting updated with a delay, so for a moment two keep clear areas for Launcher are present - one from the previous orientation (on the side), and one from the current orientation (matching the proxy value in unrestrictedKeepClearAreas). Bug: 285242520 Test: before http://recall/-/ekEuGtt9d9HWqkUtAzpHx8/cLtiXGYUyItm2kNCCEkkWA Test: after http://recall/-/ekEuGtt9d9HWqkUtAzpHx8/iPs6fwdSXG3TE0IERmxA8 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b5b218eea929f719703ca91df6b9868645909f4c) Merged-In: I40dfe08680c944f2be5db0f6b15515492f409565 Change-Id: I40dfe08680c944f2be5db0f6b15515492f409565 --- res/layout/hotseat.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/res/layout/hotseat.xml b/res/layout/hotseat.xml index 95ebd94d0e0..82b0b8d74e3 100644 --- a/res/layout/hotseat.xml +++ b/res/layout/hotseat.xml @@ -21,5 +21,4 @@ android:layout_height="match_parent" android:theme="@style/HomeScreenElementTheme" android:importantForAccessibility="no" - android:preferKeepClear="true" launcher:containerType="hotseat" /> \ No newline at end of file From df537ccdb7eee3dfab6eb8cda662d26110e86279 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 28 Jun 2023 19:29:19 -0700 Subject: [PATCH 14/44] Cleans up bad state when transient taskbar shows on home. Bug: 279514548 Test: open transparent activity on top of launcher unstash taskbar go home (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3bad3ebaad529a8be587b9c0eae61faf87ea8505) Merged-In: I13ab79b334e1f8feda441a82cc4d035c0142f513 Change-Id: I13ab79b334e1f8feda441a82cc4d035c0142f513 --- .../launcher3/taskbar/TaskbarLauncherStateController.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 17e7e1b9bbd..ddea51f737b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -202,6 +202,11 @@ public void onStateTransitionStart(LauncherState toState) { public void onStateTransitionComplete(LauncherState finalState) { mLauncherState = finalState; updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, false); + // TODO(b/279514548) Cleans up bad state that can occur when user interacts with + // taskbar on top of transparent activity. + if (finalState == LauncherState.NORMAL && mLauncher.isResumed()) { + updateStateForFlag(FLAG_RESUMED, true); + } applyState(); boolean disallowLongClick = finalState == LauncherState.OVERVIEW_SPLIT_SELECT; com.android.launcher3.taskbar.Utilities.setOverviewDragState( From 7cc6f650113da7f4435399b9929eabc2b344bd4f Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Wed, 28 Jun 2023 11:51:18 -0700 Subject: [PATCH 15/44] Taskbar All Apps Shortcut Menu Acccessibility Focus Bug: 280657266 Test: manual Flag: not needed (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:53d953ccd24cd378418d9bd8c9964589fb1af44a) Merged-In: I2426636067ce3635b8b24b9f5d093dad7d9ddf4c Change-Id: I2426636067ce3635b8b24b9f5d093dad7d9ddf4c --- .../launcher3/taskbar/TaskbarPopupController.java | 1 - .../android/launcher3/popup/PopupContainerWithArrow.java | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index 5eec726e27e..512b77a92a4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -177,7 +177,6 @@ public PopupContainerWithArrow showForIcon(BubbleTextView ic systemShortcuts); } - icon.clearAccessibilityFocus(); container.addOnAttachStateChangeListener( new PopupLiveUpdateHandler(context, container) { @Override diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 8274789ef50..1f26bab502f 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -125,6 +125,14 @@ public PopupContainerWithArrow(Context context) { this(context, null, 0); } + @Override + protected View getAccessibilityInitialFocusView() { + if (mSystemShortcutContainer != null) { + return mSystemShortcutContainer.getChildAt(0); + } + return super.getAccessibilityInitialFocusView(); + } + public LauncherAccessibilityDelegate getAccessibilityDelegate() { return mAccessibilityDelegate; } @@ -242,7 +250,6 @@ public static PopupContainerWithArrow showForIcon(BubbleTextView icon) popupDataProvider.getNotificationKeysForItem(item), systemShortcuts); } - launcher.tryClearAccessibilityFocus(icon); launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item)); container.requestFocus(); return container; From 1f6a5f50e522cea404f414dbfe30940fce65532f Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 6 Jul 2023 04:34:54 +0000 Subject: [PATCH 16/44] Ignore recents transition if there are no closing tasks - In the case where Launcher calls startRecentsTransition while there are no other visible tasks, we should not be continuing with the transition as there are no tasks for Launcher to control. This was previously handled in RecentsAnimationController in legacy transitions, but the safer fix is to ignore it on the Launcher side for this release. Bug: 289175232 Test: Manually trigger empty targets and verify no issues (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6f7e15ff644bac2f11ecb779030255efebc18885) Merged-In: I3657c000cbc8c14c9ac989c2a57715515c96edb6 Change-Id: I3657c000cbc8c14c9ac989c2a57715515c96edb6 --- .../quickstep/RecentsAnimationCallbacks.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index 523a98ec4bf..2256cbf14bf 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -15,6 +15,7 @@ */ package com.android.quickstep; +import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; @@ -37,6 +38,7 @@ import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Set; @@ -101,9 +103,22 @@ public final void onAnimationStart(RecentsAnimationControllerCompat animationCon RemoteAnimationTarget[] appTargets, RemoteAnimationTarget[] wallpaperTargets, Rect homeContentInsets, Rect minimizedHomeBounds) { + long appCount = Arrays.stream(appTargets) + .filter(app -> app.mode == MODE_CLOSING) + .count(); + if (appCount == 0) { + // Edge case, if there are no closing app targets, then Launcher has nothing to handle + ActiveGestureLog.INSTANCE.addLog( + /* event= */ "RecentsAnimationCallbacks.onAnimationStart (canceled)", + /* extras= */ 0, + /* gestureEvent= */ START_RECENTS_ANIMATION); + notifyAnimationCanceled(); + animationController.finish(false /* toHome */, false /* sendUserLeaveHint */); + return; + } + mController = new RecentsAnimationController(animationController, mAllowMinimizeSplitScreen, this::onAnimationFinished); - if (mCancelled) { Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), mController::finishAnimationToApp); From 1672e8a367bf56b5e654e0492385b34e3c02ab63 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 6 Jul 2023 22:01:49 +0000 Subject: [PATCH 17/44] Fix an issue with nav bar translations not being updated - There are flows where the shared taskbar state is updated prior to being destroyed, and not updated to the latest values when the taskbar is recreated. ie. unfolded -> lock screen -> LauncherTaskbarUiController's mTaskbarInAppDisplayProgress[SYSUI_SURFACE_PROGRESS_INDEX] is set to 1 due to the notif shade (lockscreen) showing. This is written into TaskbarSharedState's sysuiStateFlags and inAppDisplayProgressMultiPropValues. fold -> TaskbarActivityContext is destroyed unlock -> TaskbarManager and TaskbarSharedState's sysuiStateFlags are updated while the device is folded unfold -> TaskbarActivityContext is recreated and initialized which restores from the shared state's inAppDisplayProgressMultiPropValues. It also tries to reapply the shared state's sysuiStateFlags, but this doesn't update inAppDisplayProgressMultiPropValues because the state's "enabled" state is not updated (default is no flag set, and lockscreen sysui state is not set anymore). -> The restored inAppDisplayProgressMultiPropValues value results in the wrong translation. - Note that after the above, the NavbarButtonsViewController state is actually correct and reflects the SysUI state, but the LauncherTaskbarUiController state is wrong. This CL tries to manually update the ui controller to the correct state when it is recreated. - CL also fixes a separate issue where LauncherTaskbarUIController could potentially overwrite the saved state progresses while restoring them due to the state callback being called Bug: 283346744 Test: Unfold -> Lockscreen -> Fold -> Unlock -> Unfold and ensure the buttons are translated correctly Signed-off-by: Winson Chung (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ccd359d76c7f42d4fc799f19d54a66c7c2fa462a) Merged-In: I43e473faf4fa2a493b9705506e3755df8f6264e7 Change-Id: I43e473faf4fa2a493b9705506e3755df8f6264e7 --- .../taskbar/LauncherTaskbarUIController.java | 5 +++++ .../taskbar/NavbarButtonsViewController.java | 9 +++++++++ .../launcher3/taskbar/TaskbarActivityContext.java | 4 +--- .../launcher3/taskbar/TaskbarControllers.java | 13 +++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index ba6f1651ed8..abf49eb195f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -50,6 +50,7 @@ import com.android.quickstep.views.RecentsView; import java.io.PrintWriter; +import java.util.Arrays; /** * A data source which integrates with a Launcher instance @@ -105,6 +106,10 @@ protected void init(TaskbarControllers taskbarControllers) { // Restore the in-app display progress from before Taskbar was recreated. float[] prevProgresses = mControllers.getSharedState().inAppDisplayProgressMultiPropValues; + // Make a copy of the previous progress to set since updating the multiprop will update + // the property which also calls onInAppDisplayProgressChanged() which writes the current + // values into the shared state + prevProgresses = Arrays.copyOf(prevProgresses, prevProgresses.length); for (int i = 0; i < prevProgresses.length; i++) { mTaskbarInAppDisplayProgressMultiProp.get(i).setValue(prevProgresses[i]); } diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 9a9e0ba70ce..9c463cb68c5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -923,6 +923,15 @@ private void onComputeInsetsForSeparateWindow(ViewTreeObserver.InternalInsetsInf insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); } + /** + * Called whenever a new ui controller is set, and should update anything that depends on the + * ui controller. + */ + public void onUiControllerChanged() { + updateNavButtonInAppDisplayProgressForSysui(); + updateNavButtonTranslationY(); + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "NavbarButtonsViewController:"); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 43feec716de..a1390aeabb5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -591,9 +591,7 @@ public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInf * Sets a new data-source for this taskbar instance */ public void setUIController(@NonNull TaskbarUIController uiController) { - mControllers.uiController.onDestroy(); - mControllers.uiController = uiController; - mControllers.uiController.init(mControllers); + mControllers.setUiController(uiController); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index 66c2eb33143..d3f80e31cd0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -196,6 +196,19 @@ public void init(@NonNull TaskbarSharedState sharedState) { mPostInitCallbacks.clear(); } + /** + * Sets the ui controller. + */ + public void setUiController(@NonNull TaskbarUIController newUiController) { + uiController.onDestroy(); + uiController = newUiController; + uiController.init(this); + uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags); + + // Notify that the ui controller has changed + navbarButtonsViewController.onUiControllerChanged(); + } + @Nullable public TaskbarSharedState getSharedState() { // This should only be null if called before init() and after destroy(). From fb8a789fc9d1d1877c04f173f64998c5898e6463 Mon Sep 17 00:00:00 2001 From: Andrew Cole Date: Thu, 6 Jul 2023 09:18:33 -0700 Subject: [PATCH 18/44] Updating materialColorSurfaceContainerHighest color access For any view files applying the WidgetConatinerTheme via widgetsTheme they were incorrectly inheriting themes and skipping the AppTheme provided but only in light mode. In dark mode the WidgetContainerTheme.Dark was correctly inheriting the theme. To avoid a risky theme update for all widgetsThemes we just modify the color accessor to use @color instead of ?attr as these colors should not be attributes AFAIKT Bug: b/289305591 Test: Follow repro steps on the bug for smartspace (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a9af3bd03db3c19a07a4015471ee5c83d364fd36) Merged-In: I26cc3239763f8eac3dfe5f094c6757692f46d1bc Change-Id: I26cc3239763f8eac3dfe5f094c6757692f46d1bc --- res/color-v31/surface.xml | 24 ------------------- res/drawable/add_item_dialog_background.xml | 2 +- .../button_top_rounded_bordered_ripple.xml | 2 +- 3 files changed, 2 insertions(+), 26 deletions(-) delete mode 100644 res/color-v31/surface.xml diff --git a/res/color-v31/surface.xml b/res/color-v31/surface.xml deleted file mode 100644 index da4571a61c8..00000000000 --- a/res/color-v31/surface.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - diff --git a/res/drawable/add_item_dialog_background.xml b/res/drawable/add_item_dialog_background.xml index c3a82695c27..e279fa051a8 100644 --- a/res/drawable/add_item_dialog_background.xml +++ b/res/drawable/add_item_dialog_background.xml @@ -1,7 +1,7 @@ - + diff --git a/res/drawable/button_top_rounded_bordered_ripple.xml b/res/drawable/button_top_rounded_bordered_ripple.xml index f15a4a0c5f0..f5b68866cb9 100644 --- a/res/drawable/button_top_rounded_bordered_ripple.xml +++ b/res/drawable/button_top_rounded_bordered_ripple.xml @@ -25,7 +25,7 @@ android:topRightRadius="12dp" android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp" /> - + From e0600c6bcae2207e7a6e179305d3298605070a8b Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Fri, 23 Jun 2023 15:43:39 -0700 Subject: [PATCH 19/44] Handle onFlingFinished onRecentsAnimationStart If the onRecentsAnimationStart callback runs after the user lifts their finger and onFlingFinished runs, then onFlingFinished never has another chance to run, leaving the user trapped in a state where the launcher is not started and the AllSetActivity is still present but invisible. Reverted to allow onFlingFinished to run onRecentsAnimationStart to handle this edge case. Flag: not needed Fixes: 285194839 Test: Ran AllSetActivty with a delay in onRecentsAnimationStart (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b2c2e694c6e233057570d3e8b4e5a0aa9c0c51a) Merged-In: I33ce5c1d4955b34d4b77d3b740dc599621bd4ed1 Change-Id: I33ce5c1d4955b34d4b77d3b740dc599621bd4ed1 --- .../inputconsumers/ProgressDelegateInputConsumer.java | 3 ++- .../android/quickstep/interaction/AllSetActivity.java | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java index ab702728520..eac09ad7dc7 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java @@ -103,7 +103,8 @@ public ProgressDelegateInputConsumer(Context context, mStateCallback = new MultiStateCallback(STATE_NAMES); mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED, this::endRemoteAnimation); - mStateCallback.runOnceAtState(STATE_FLING_FINISHED, this::onFlingFinished); + mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_FLING_FINISHED, + this::onFlingFinished); mSwipeDetector = new SingleAxisSwipeDetector(mContext, this, VERTICAL); mSwipeDetector.setDetectableScrollConditions(DIRECTION_POSITIVE, false); diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java index 2eaff467152..6619dd86f68 100644 --- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java @@ -254,6 +254,9 @@ private void onTISConnected(TISBinder binder) { mBinder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null); mBinder.setOverviewTargetChangeListener(mBinder::preloadOverviewForSUWAllSet); mBinder.preloadOverviewForSUWAllSet(); + if (mTaskbarManager != null) { + mLauncherStartAnim = mTaskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION); + } } @Override @@ -328,12 +331,9 @@ private void onSwipeProgressUpdate() { mRootView.setAlpha(alpha); mRootView.setTranslationY((alpha - 1) * mSwipeUpShift); - if (mLauncherStartAnim == null && mTaskbarManager != null) { - mLauncherStartAnim = mTaskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION); - } if (mLauncherStartAnim != null) { - mLauncherStartAnim.setPlayFraction(Utilities.mapBoundToRange( - mSwipeProgress.value, 0, 1, 0, 1, FAST_OUT_SLOW_IN)); + mLauncherStartAnim.setPlayFraction( + FAST_OUT_SLOW_IN.getInterpolation(mSwipeProgress.value)); } maybeResumeOrPauseBackgroundAnimation(); } From ca4e39d402d6bc8453f51834461c1543ff5b84e4 Mon Sep 17 00:00:00 2001 From: Becky Qiu Date: Tue, 11 Jul 2023 17:22:59 -0700 Subject: [PATCH 20/44] Fix the issue that on tablet/unfold, the allapps background color is wrong. As the new spec, it should use materialColorSurfaceDim for all devices. Bug: 288493929 Test: manual, before: https://screenshot.googleplex.com/7YxpFGekwm6Gz6N, after: https://screenshot.googleplex.com/44Gr2dBfWSct7FK Flag: no flag needed. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:aa6612d3731a3e98f716747b0ede473e3bbca161) Merged-In: Ic33d9a758fe9fbaa0f735c874a545df711a18e2f Change-Id: Ic33d9a758fe9fbaa0f735c874a545df711a18e2f --- .../launcher3/allapps/ActivityAllAppsContainerView.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index d4140d851ca..19777045882 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -43,7 +43,6 @@ import android.util.FloatProperty; import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -272,9 +271,8 @@ protected void onFinishInflate() { 0, 0 // Bottom left }; - final TypedValue value = new TypedValue(); - getContext().getTheme().resolveAttribute(android.R.attr.colorBackground, value, true); - mBottomSheetBackgroundColor = value.data; + mBottomSheetBackgroundColor = + Themes.getAttrColor(getContext(), R.attr.materialColorSurfaceDim); updateBackgroundVisibility(mActivityContext.getDeviceProfile()); mSearchUiManager.initializeSearch(this); } From e79837c0f6067e5d3c475ccb27a06fe3ac439fef Mon Sep 17 00:00:00 2001 From: Sebastian Franco Date: Wed, 12 Jul 2023 12:46:53 -0700 Subject: [PATCH 21/44] Creating a correctly populated mOccupied grid when reordering on foldables On ag/21680045 I copy the previous mOccupied but the right thing to do is to create a new one with all the views information. Some test stoped running inadvertently that's why we didn't catch this issue. There is a separate cl with the test to ensure we can catch it later on. Fix: 289584301 Test: ReorderWidgets (cherry picked from commit 1c5514b56619d0ae76948689bb51479f131d0e30) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:52d9d9780fb5a83302dd6fb3d875635a2ee57e1c) Merged-In: I27b5a6e38a556d1c73ff8fbbdd552da6045e5b64 Change-Id: I27b5a6e38a556d1c73ff8fbbdd552da6045e5b64 --- .../celllayout/MulticellReorderAlgorithm.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java b/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java index cb1216109a5..a2e26b37f30 100644 --- a/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java +++ b/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java @@ -19,8 +19,10 @@ import com.android.launcher3.CellLayout; import com.android.launcher3.MultipageCellLayout; +import com.android.launcher3.ShortcutAndWidgetContainer; import com.android.launcher3.util.GridOccupancy; +import java.util.Arrays; import java.util.function.Supplier; /** @@ -79,7 +81,7 @@ void addSeam() { lp.canReorder = false; mcl.setCountX(mcl.getCountX() + 1); mcl.getShortcutsAndWidgets().addViewInLayout(mSeam, lp); - mcl.setOccupied(createGridOccupancyWithSeam(mcl.getOccupied())); + mcl.setOccupied(createGridOccupancyWithSeam()); mcl.mTmpOccupied = new GridOccupancy(mcl.getCountX(), mcl.getCountY()); } @@ -93,7 +95,8 @@ void removeSeam() { /** * The function supplied here will execute while the CellLayout has a simulated seam added. - * @param f function to run under simulation + * + * @param f function to run under simulation * @param return value of the supplied function * @return Value of supplied function */ @@ -110,18 +113,17 @@ public T simulateSeam(Supplier f) { return res; } - GridOccupancy createGridOccupancyWithSeam(GridOccupancy gridOccupancy) { + GridOccupancy createGridOccupancyWithSeam() { + ShortcutAndWidgetContainer shortcutAndWidgets = mCellLayout.getShortcutsAndWidgets(); GridOccupancy grid = new GridOccupancy(mCellLayout.getCountX(), mCellLayout.getCountY()); - for (int x = 0; x < mCellLayout.getCountX(); x++) { - for (int y = 0; y < mCellLayout.getCountY(); y++) { - int offset = x >= mCellLayout.getCountX() / 2 ? 1 : 0; - if (x == mCellLayout.getCountX() / 2) { - grid.cells[x][y] = true; - } else { - grid.cells[x][y] = gridOccupancy.cells[x - offset][y]; - } - } + for (int i = 0; i < shortcutAndWidgets.getChildCount(); i++) { + View view = shortcutAndWidgets.getChildAt(i); + CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams(); + int seamOffset = lp.getCellX() >= mCellLayout.getCountX() / 2 && lp.canReorder ? 1 : 0; + grid.markCells(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, lp.cellVSpan, + true); } + Arrays.fill(grid.cells[mCellLayout.getCountX() / 2], true); return grid; } } From faf861aae5fec56f4b9f1b99ac194491d0a2b457 Mon Sep 17 00:00:00 2001 From: fbaron Date: Wed, 12 Jul 2023 10:16:49 -0700 Subject: [PATCH 22/44] Fix inability to remove or interact with folder when removing 2nd item from folder Fix: 289960317 Test: Verify in unfolded felix that going from 2 icon folder and dragging 2nd icon out of folder lets you open the app that remains where the folder was Test: Verify in unfolded felix that going from 2 icon folder and dragging 2nd icon into remove droptarget removes the folder and turns it into a single clickable icon flag: no flag (cherry picked from commit 5a7ea3069b984aef151fc2486319583c769cf12c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:326ec97ab6a4d348708830cd2860d4dd90a59039) Merged-In: I26138ee9f8e7cdb45cafe2446dc4d1e3d6d8347f Change-Id: I26138ee9f8e7cdb45cafe2446dc4d1e3d6d8347f --- src/com/android/launcher3/Launcher.java | 2 ++ src/com/android/launcher3/folder/LauncherDelegate.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 25eb16079fe..66690431ecb 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2194,6 +2194,8 @@ boolean isHotseatLayout(View layout) { /** * Returns the CellLayout of the specified container at the specified screen. + * + * @param screenId must be presenterPos and not modelPos. */ public CellLayout getCellLayout(int container, int screenId) { return (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java index f15dc833879..7ac2472319a 100644 --- a/src/com/android/launcher3/folder/LauncherDelegate.java +++ b/src/com/android/launcher3/folder/LauncherDelegate.java @@ -93,7 +93,7 @@ public void run() { // Move the item from the folder to the workspace, in the position of the // folder CellLayout cellLayout = mLauncher.getCellLayout(info.container, - info.screenId); + mLauncher.getCellPosMapper().mapModelToPresenter(info).screenId); if (cellLayout == null) { return; } From 8a18bc0f12fc14e69f0e5398488cf989c99cbb49 Mon Sep 17 00:00:00 2001 From: fbaron Date: Wed, 12 Jul 2023 10:16:49 -0700 Subject: [PATCH 23/44] Fix inability to remove or interact with folder when removing 2nd item from folder Fix: 289960317 Test: Verify in unfolded felix that going from 2 icon folder and dragging 2nd icon out of folder lets you open the app that remains where the folder was Test: Verify in unfolded felix that going from 2 icon folder and dragging 2nd icon into remove droptarget removes the folder and turns it into a single clickable icon flag: no flag (cherry picked from commit 5a7ea3069b984aef151fc2486319583c769cf12c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:326ec97ab6a4d348708830cd2860d4dd90a59039) Merged-In: I26138ee9f8e7cdb45cafe2446dc4d1e3d6d8347f Change-Id: I26138ee9f8e7cdb45cafe2446dc4d1e3d6d8347f --- src/com/android/launcher3/Launcher.java | 2 ++ src/com/android/launcher3/folder/LauncherDelegate.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 25eb16079fe..66690431ecb 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2194,6 +2194,8 @@ boolean isHotseatLayout(View layout) { /** * Returns the CellLayout of the specified container at the specified screen. + * + * @param screenId must be presenterPos and not modelPos. */ public CellLayout getCellLayout(int container, int screenId) { return (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java index f15dc833879..7ac2472319a 100644 --- a/src/com/android/launcher3/folder/LauncherDelegate.java +++ b/src/com/android/launcher3/folder/LauncherDelegate.java @@ -93,7 +93,7 @@ public void run() { // Move the item from the folder to the workspace, in the position of the // folder CellLayout cellLayout = mLauncher.getCellLayout(info.container, - info.screenId); + mLauncher.getCellPosMapper().mapModelToPresenter(info).screenId); if (cellLayout == null) { return; } From c59599dc1970324c39e4b85bc6dfeb647baf2b74 Mon Sep 17 00:00:00 2001 From: randypfohl Date: Thu, 20 Jul 2023 12:53:31 -0700 Subject: [PATCH 24/44] Removing obsolete call to start home activity with shell transitions - The second start activity was causing issues with 3p launchers which may not expect another new intent (ie. if it handles gestures at the bottom of the screen). We can't completely remove this logic because for button navigation we don't want to fall through to the launch-next-task animation below, but we can can continue to finish the recents animation immediately. - With shell transitions, leashes for opening apps are always hidden by default so when transitioning to a 3p launcher from RecentsActivity we also need to show the surface if we want to animate it in Bug: 289609734 Test: Set 3p Launcher as default, in both gesture & button navigation - Go from 3p home -> overview, then overview -> 3p home - Go from app -> 3p home - Go from app -> overview, then overview -> 3p home - Quickswitch from app Signed-off-by: Winson Chung (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2b3dc6f73007f8b7d97ae2972e37c5d055659c8b) Merged-In: I6875083931de63a8097d23d180553885ed7cfb01 Change-Id: I6875083931de63a8097d23d180553885ed7cfb01 --- .../android/quickstep/FallbackSwipeHandler.java | 1 + .../android/quickstep/TaskAnimationManager.java | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java index 19130916959..eff53f3c859 100644 --- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java @@ -139,6 +139,7 @@ private void setHomeScaleAndAlpha(SurfaceProperties builder, mTmpMatrix.setScale(scale, scale, app.localBounds.exactCenterX(), app.localBounds.exactCenterY()); builder.setMatrix(mTmpMatrix).setAlpha(alpha); + builder.setShow(); } @Override diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 410ba218662..eacca0dbab5 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -19,6 +19,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; +import static com.android.launcher3.util.NavigationMode.NO_BUTTON; import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED; @@ -37,6 +38,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.util.DisplayController; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.views.DesktopTaskView; @@ -162,10 +164,16 @@ public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) { for (RemoteAnimationTarget compat : appearedTaskTargets) { if (compat.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME - && activityInterface.getCreatedActivity() instanceof RecentsActivity) { - // When receive opening home activity while recents is running, enter home - // and dismiss recents. - ((RecentsActivity) activityInterface.getCreatedActivity()).startHome(); + && activityInterface.getCreatedActivity() instanceof RecentsActivity + && DisplayController.getNavigationMode(mCtx) != NO_BUTTON) { + // The only time we get onTasksAppeared() in button navigation with a + // 3p launcher is if the user goes to overview first, and in this case we + // can immediately finish the transition + RecentsView recentsView = + activityInterface.getCreatedActivity().getOverviewPanel(); + if (recentsView != null) { + recentsView.finishRecentsAnimation(true, null); + } return; } } From 628f74bd7183cc4a07266487d8b30f362bd80575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Franco?= Date: Thu, 27 Jul 2023 18:25:53 +0000 Subject: [PATCH 25/44] Disable FOLDABLE_SINGLE_PAGE The functionality should go back to the same as with phones. There shouldn't be issues with the reorder or similar behavior since we are switching form using the MultipageCellLayout to the regular CellLayout. The things we need to pay attention to is the the behavior of having two panels like adding the right number of panels when loading (folding, unfolding and rotating). Bug: 291822492 Test: ReorderWidgets (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:8d606e89d3511a6f65e3a80add97c0fae580fb97) Merged-In: I903873e32f35c5ee9e0f3da8581a37d4087d021f Change-Id: I903873e32f35c5ee9e0f3da8581a37d4087d021f --- 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 f5f6769c33a..b255ea8a180 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -194,7 +194,7 @@ public static boolean showFlagTogglerUi(Context context) { "In foldables, when reordering the icons and widgets, is now going to use both sides"); public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, - "FOLDABLE_SINGLE_PAGE", ENABLED, "Use a single page for the workspace"); + "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); // TODO(Block 12): Clean up flags public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, From 8e263cb930154eab6900a06a218cda2c0598a6f1 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 26/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 8d1e9f08dfbac3cc1ad2bafd8c4c17bfa111102a Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 27/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 30471b4d6c8e0b0caced395687628dc778f8441c Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Tue, 18 Jul 2023 13:34:07 -0700 Subject: [PATCH 28/44] Log appear animation's scale factor Test: Grabbed a bug report b/291974797 Flag: N/A Bug: 290320302 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2303acd7d4272b063352598d4ec65c5b92e0f0f7) Merged-In: Ic33dc94806b838a03a2203bdd5701a1eeaeeb7bf Change-Id: Ic33dc94806b838a03a2203bdd5701a1eeaeeb7bf --- .../launcher3/QuickstepTransitionManager.java | 4 + .../uioverrides/QuickstepLauncher.java | 5 + .../android/launcher3/util/EventLogArray.kt | 117 ++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 src/com/android/launcher3/util/EventLogArray.kt diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index ca9c5771b12..3966ca43193 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -158,6 +158,7 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.wm.shell.startingsurface.IStartingWindowListener; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -477,6 +478,9 @@ public void setRemoteAnimationProvider(final RemoteAnimationProvider animationPr }); } + /** Dump debug logs to bug report. */ + public void dump(@NonNull String prefix, @NonNull PrintWriter printWriter) {} + /** * Content is everything on screen except the background and the floating view (if any). * diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 3139e4d91ad..b621a287c2f 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -204,6 +204,8 @@ public class QuickstepLauncher extends Launcher { public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false; + protected static final String RING_APPEAR_ANIMATION_PREFIX = "RingAppearAnimation\t"; + private FixedContainerItems mAllAppsPredictions; private HotseatPredictionController mHotseatPredictionController; private DepthController mDepthController; @@ -1336,5 +1338,8 @@ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] if (recentsView != null) { recentsView.getSplitSelectController().dump(prefix, writer); } + if (mAppTransitionManager != null) { + mAppTransitionManager.dump(prefix + "\t" + RING_APPEAR_ANIMATION_PREFIX, writer); + } } } diff --git a/src/com/android/launcher3/util/EventLogArray.kt b/src/com/android/launcher3/util/EventLogArray.kt new file mode 100644 index 00000000000..a17d6509e37 --- /dev/null +++ b/src/com/android/launcher3/util/EventLogArray.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.launcher3.util + +import java.io.PrintWriter +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** + * A utility class to record and log events. Events are stored in a fixed size array and old logs + * are purged as new events come. + */ +class EventLogArray(private val name: String, size: Int) { + + companion object { + private const val TYPE_ONE_OFF = 0 + private const val TYPE_FLOAT = 1 + private const val TYPE_INTEGER = 2 + private const val TYPE_BOOL_TRUE = 3 + private const val TYPE_BOOL_FALSE = 4 + private fun isEntrySame(entry: EventEntry?, type: Int, event: String): Boolean { + return entry != null && entry.type == type && entry.event == event + } + } + + private val logs: Array + private var nextIndex = 0 + + init { + logs = arrayOfNulls(size) + } + + fun addLog(event: String) { + addLog(TYPE_ONE_OFF, event, 0f) + } + + fun addLog(event: String, extras: Int) { + addLog(TYPE_INTEGER, event, extras.toFloat()) + } + + fun addLog(event: String, extras: Float) { + addLog(TYPE_FLOAT, event, extras) + } + + fun addLog(event: String, extras: Boolean) { + addLog(if (extras) TYPE_BOOL_TRUE else TYPE_BOOL_FALSE, event, 0f) + } + + private fun addLog(type: Int, event: String, extras: Float) { + // Merge the logs if it's a duplicate + val last = (nextIndex + logs.size - 1) % logs.size + val secondLast = (nextIndex + logs.size - 2) % logs.size + if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) { + logs[last]!!.update(type, event, extras) + logs[secondLast]!!.duplicateCount++ + return + } + if (logs[nextIndex] == null) { + logs[nextIndex] = EventEntry() + } + logs[nextIndex]!!.update(type, event, extras) + nextIndex = (nextIndex + 1) % logs.size + } + + fun dump(prefix: String, writer: PrintWriter) { + writer.println("$prefix$name event history:") + val sdf = SimpleDateFormat(" HH:mm:ss.SSSZ ", Locale.US) + val date = Date() + for (i in logs.indices) { + val log = logs[(nextIndex + logs.size - i - 1) % logs.size] ?: continue + date.time = log.time + val msg = StringBuilder(prefix).append(sdf.format(date)).append(log.event) + when (log.type) { + TYPE_BOOL_FALSE -> msg.append(": false") + TYPE_BOOL_TRUE -> msg.append(": true") + TYPE_FLOAT -> msg.append(": ").append(log.extras) + TYPE_INTEGER -> msg.append(": ").append(log.extras.toInt()) + else -> {} + } + if (log.duplicateCount > 0) { + msg.append(" & ").append(log.duplicateCount).append(" similar events") + } + writer.println(msg) + } + } + + /** A single event entry. */ + private class EventEntry { + var type = 0 + var event: String? = null + var extras = 0f + var time: Long = 0 + var duplicateCount = 0 + fun update(type: Int, event: String, extras: Float) { + this.type = type + this.event = event + this.extras = extras + time = System.currentTimeMillis() + duplicateCount = 0 + } + } +} From ed1503317c37f999c7214b9ef15ddaa34200e05a Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 29/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 5038853cd7e841dfacd6c428a5424c3ec702e583 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Tue, 18 Jul 2023 13:34:07 -0700 Subject: [PATCH 30/44] Log appear animation's scale factor Test: Grabbed a bug report b/291974797 Flag: N/A Bug: 290320302 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2303acd7d4272b063352598d4ec65c5b92e0f0f7) Merged-In: Ic33dc94806b838a03a2203bdd5701a1eeaeeb7bf Change-Id: Ic33dc94806b838a03a2203bdd5701a1eeaeeb7bf --- .../launcher3/QuickstepTransitionManager.java | 4 + .../uioverrides/QuickstepLauncher.java | 5 + .../android/launcher3/util/EventLogArray.kt | 117 ++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 src/com/android/launcher3/util/EventLogArray.kt diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index ca9c5771b12..3966ca43193 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -158,6 +158,7 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.wm.shell.startingsurface.IStartingWindowListener; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -477,6 +478,9 @@ public void setRemoteAnimationProvider(final RemoteAnimationProvider animationPr }); } + /** Dump debug logs to bug report. */ + public void dump(@NonNull String prefix, @NonNull PrintWriter printWriter) {} + /** * Content is everything on screen except the background and the floating view (if any). * diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 3139e4d91ad..b621a287c2f 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -204,6 +204,8 @@ public class QuickstepLauncher extends Launcher { public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false; + protected static final String RING_APPEAR_ANIMATION_PREFIX = "RingAppearAnimation\t"; + private FixedContainerItems mAllAppsPredictions; private HotseatPredictionController mHotseatPredictionController; private DepthController mDepthController; @@ -1336,5 +1338,8 @@ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] if (recentsView != null) { recentsView.getSplitSelectController().dump(prefix, writer); } + if (mAppTransitionManager != null) { + mAppTransitionManager.dump(prefix + "\t" + RING_APPEAR_ANIMATION_PREFIX, writer); + } } } diff --git a/src/com/android/launcher3/util/EventLogArray.kt b/src/com/android/launcher3/util/EventLogArray.kt new file mode 100644 index 00000000000..a17d6509e37 --- /dev/null +++ b/src/com/android/launcher3/util/EventLogArray.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.launcher3.util + +import java.io.PrintWriter +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** + * A utility class to record and log events. Events are stored in a fixed size array and old logs + * are purged as new events come. + */ +class EventLogArray(private val name: String, size: Int) { + + companion object { + private const val TYPE_ONE_OFF = 0 + private const val TYPE_FLOAT = 1 + private const val TYPE_INTEGER = 2 + private const val TYPE_BOOL_TRUE = 3 + private const val TYPE_BOOL_FALSE = 4 + private fun isEntrySame(entry: EventEntry?, type: Int, event: String): Boolean { + return entry != null && entry.type == type && entry.event == event + } + } + + private val logs: Array + private var nextIndex = 0 + + init { + logs = arrayOfNulls(size) + } + + fun addLog(event: String) { + addLog(TYPE_ONE_OFF, event, 0f) + } + + fun addLog(event: String, extras: Int) { + addLog(TYPE_INTEGER, event, extras.toFloat()) + } + + fun addLog(event: String, extras: Float) { + addLog(TYPE_FLOAT, event, extras) + } + + fun addLog(event: String, extras: Boolean) { + addLog(if (extras) TYPE_BOOL_TRUE else TYPE_BOOL_FALSE, event, 0f) + } + + private fun addLog(type: Int, event: String, extras: Float) { + // Merge the logs if it's a duplicate + val last = (nextIndex + logs.size - 1) % logs.size + val secondLast = (nextIndex + logs.size - 2) % logs.size + if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) { + logs[last]!!.update(type, event, extras) + logs[secondLast]!!.duplicateCount++ + return + } + if (logs[nextIndex] == null) { + logs[nextIndex] = EventEntry() + } + logs[nextIndex]!!.update(type, event, extras) + nextIndex = (nextIndex + 1) % logs.size + } + + fun dump(prefix: String, writer: PrintWriter) { + writer.println("$prefix$name event history:") + val sdf = SimpleDateFormat(" HH:mm:ss.SSSZ ", Locale.US) + val date = Date() + for (i in logs.indices) { + val log = logs[(nextIndex + logs.size - i - 1) % logs.size] ?: continue + date.time = log.time + val msg = StringBuilder(prefix).append(sdf.format(date)).append(log.event) + when (log.type) { + TYPE_BOOL_FALSE -> msg.append(": false") + TYPE_BOOL_TRUE -> msg.append(": true") + TYPE_FLOAT -> msg.append(": ").append(log.extras) + TYPE_INTEGER -> msg.append(": ").append(log.extras.toInt()) + else -> {} + } + if (log.duplicateCount > 0) { + msg.append(" & ").append(log.duplicateCount).append(" similar events") + } + writer.println(msg) + } + } + + /** A single event entry. */ + private class EventEntry { + var type = 0 + var event: String? = null + var extras = 0f + var time: Long = 0 + var duplicateCount = 0 + fun update(type: Int, event: String, extras: Float) { + this.type = type + this.event = event + this.extras = extras + time = System.currentTimeMillis() + duplicateCount = 0 + } + } +} From eb8fb49a963bba3284b7e56a36c5de04cf49e54d Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Wed, 9 Aug 2023 23:19:38 +0000 Subject: [PATCH 31/44] Revert "Log appear animation's scale factor" DO NOT SUBMIT Revert submission 24154592-cherrypick-log-scale-factor-p3v8iq0onb Reason for revert: b/294401542 Reverted changes: /q/submissionid:24154592-cherrypick-log-scale-factor-p3v8iq0onb (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:306ca475386d61367a0b557b8f415eb5bfce5cc9) Merged-In: Ibd4d143838b7cafcfd85a40541295c3332b7be08 Change-Id: Ibd4d143838b7cafcfd85a40541295c3332b7be08 --- .../launcher3/QuickstepTransitionManager.java | 4 - .../uioverrides/QuickstepLauncher.java | 5 - .../android/launcher3/util/EventLogArray.kt | 117 ------------------ 3 files changed, 126 deletions(-) delete mode 100644 src/com/android/launcher3/util/EventLogArray.kt diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 3966ca43193..ca9c5771b12 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -158,7 +158,6 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.wm.shell.startingsurface.IStartingWindowListener; -import java.io.PrintWriter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -478,9 +477,6 @@ public void setRemoteAnimationProvider(final RemoteAnimationProvider animationPr }); } - /** Dump debug logs to bug report. */ - public void dump(@NonNull String prefix, @NonNull PrintWriter printWriter) {} - /** * Content is everything on screen except the background and the floating view (if any). * diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index b621a287c2f..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -204,8 +204,6 @@ public class QuickstepLauncher extends Launcher { public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false; - protected static final String RING_APPEAR_ANIMATION_PREFIX = "RingAppearAnimation\t"; - private FixedContainerItems mAllAppsPredictions; private HotseatPredictionController mHotseatPredictionController; private DepthController mDepthController; @@ -1338,8 +1336,5 @@ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] if (recentsView != null) { recentsView.getSplitSelectController().dump(prefix, writer); } - if (mAppTransitionManager != null) { - mAppTransitionManager.dump(prefix + "\t" + RING_APPEAR_ANIMATION_PREFIX, writer); - } } } diff --git a/src/com/android/launcher3/util/EventLogArray.kt b/src/com/android/launcher3/util/EventLogArray.kt deleted file mode 100644 index a17d6509e37..00000000000 --- a/src/com/android/launcher3/util/EventLogArray.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.launcher3.util - -import java.io.PrintWriter -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale - -/** - * A utility class to record and log events. Events are stored in a fixed size array and old logs - * are purged as new events come. - */ -class EventLogArray(private val name: String, size: Int) { - - companion object { - private const val TYPE_ONE_OFF = 0 - private const val TYPE_FLOAT = 1 - private const val TYPE_INTEGER = 2 - private const val TYPE_BOOL_TRUE = 3 - private const val TYPE_BOOL_FALSE = 4 - private fun isEntrySame(entry: EventEntry?, type: Int, event: String): Boolean { - return entry != null && entry.type == type && entry.event == event - } - } - - private val logs: Array - private var nextIndex = 0 - - init { - logs = arrayOfNulls(size) - } - - fun addLog(event: String) { - addLog(TYPE_ONE_OFF, event, 0f) - } - - fun addLog(event: String, extras: Int) { - addLog(TYPE_INTEGER, event, extras.toFloat()) - } - - fun addLog(event: String, extras: Float) { - addLog(TYPE_FLOAT, event, extras) - } - - fun addLog(event: String, extras: Boolean) { - addLog(if (extras) TYPE_BOOL_TRUE else TYPE_BOOL_FALSE, event, 0f) - } - - private fun addLog(type: Int, event: String, extras: Float) { - // Merge the logs if it's a duplicate - val last = (nextIndex + logs.size - 1) % logs.size - val secondLast = (nextIndex + logs.size - 2) % logs.size - if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) { - logs[last]!!.update(type, event, extras) - logs[secondLast]!!.duplicateCount++ - return - } - if (logs[nextIndex] == null) { - logs[nextIndex] = EventEntry() - } - logs[nextIndex]!!.update(type, event, extras) - nextIndex = (nextIndex + 1) % logs.size - } - - fun dump(prefix: String, writer: PrintWriter) { - writer.println("$prefix$name event history:") - val sdf = SimpleDateFormat(" HH:mm:ss.SSSZ ", Locale.US) - val date = Date() - for (i in logs.indices) { - val log = logs[(nextIndex + logs.size - i - 1) % logs.size] ?: continue - date.time = log.time - val msg = StringBuilder(prefix).append(sdf.format(date)).append(log.event) - when (log.type) { - TYPE_BOOL_FALSE -> msg.append(": false") - TYPE_BOOL_TRUE -> msg.append(": true") - TYPE_FLOAT -> msg.append(": ").append(log.extras) - TYPE_INTEGER -> msg.append(": ").append(log.extras.toInt()) - else -> {} - } - if (log.duplicateCount > 0) { - msg.append(" & ").append(log.duplicateCount).append(" similar events") - } - writer.println(msg) - } - } - - /** A single event entry. */ - private class EventEntry { - var type = 0 - var event: String? = null - var extras = 0f - var time: Long = 0 - var duplicateCount = 0 - fun update(type: Int, event: String, extras: Float) { - this.type = type - this.event = event - this.extras = extras - time = System.currentTimeMillis() - duplicateCount = 0 - } - } -} From 413a2346cbb6c3dcc4dd05e71a83c83c71994e04 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 32/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 0effcbca8480c08cdc1f2386d7a764b4fadae538 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 33/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 5dfa2976bf6ba2eae56dbec3066c0967c7caa0dd Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 34/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 781fcebcc8c1edbaee3edd85fc180cb0744daa65 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 35/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 4c96e5508268f3719576c5bd96746e2f005d2592 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 36/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 1f5e248da0b95ba396d30bf2ecb71da8a0841ab8 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 37/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From 14b4f9edcc92dfb6161272e17921c3271de9c12b Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 26 May 2023 11:50:13 +0100 Subject: [PATCH 38/44] [Unfold animation] Do not preemptively start the animation if it has run already Currently if we open an app, unfold the device and then go to home screen we will start the unfold animation preemptively in Launcher because Launcher activity will receive updated configuration change (where isTablet = true) only after going back to home screen, not when unfolding the device. This causes a problem because SystemUI won't send the unfold animation events after going back home as the animation has already run, so we end up with wrongly started animation in Launcher. This CL fixes the issues by checking if SystemUI has finished the animation (or if it is currently running) to avoid preemptive animation start in this case. This is done by subscribing to the original unfold transition progress provider which emits progress events sent through IPC from SystemUI. Bug: 285150685 Bug: 293131586 Test: open an app on folded screen, unfold, go to home screen => check that icons are not squished Test: fold/unfold when launcher is open (cherry picked from commit 6d756970e77e99ed434c58b815a6eaac1a023a4c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2e53f5ef97a02d25f508774e82985e24dc2f4d2d) Merged-In: Ic437ff4d19cbd5764635f3007d99880622150f5b Change-Id: Ic437ff4d19cbd5764635f3007d99880622150f5b --- .../uioverrides/QuickstepLauncher.java | 4 ++ .../LauncherUnfoldAnimationController.java | 65 ++++++++++++++++++- .../launcher3/config/FeatureFlags.java | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 2f13c5de44d..3139e4d91ad 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -472,6 +472,10 @@ public void bindWorkspaceComponentsRemoved(Predicate matcher) { public void onDestroy() { mAppTransitionManager.onActivityDestroyed(); if (mUnfoldTransitionProgressProvider != null) { + if (FeatureFlags.RECEIVE_UNFOLD_EVENTS_FROM_SYSUI.get()) { + SystemUiProxy.INSTANCE.get(this).setUnfoldAnimationListener(null); + } + mUnfoldTransitionProgressProvider.destroy(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 6d15e8be98c..e0b527268c7 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -60,6 +60,8 @@ public class LauncherUnfoldAnimationController implements OnDeviceProfileChangeL private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider; private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator; private final UnfoldMoveFromCenterWorkspaceAnimator mUnfoldMoveFromCenterWorkspaceAnimator; + private final TransitionStatusProvider mExternalTransitionStatusProvider = + new TransitionStatusProvider(); private PreemptiveUnfoldTransitionProgressProvider mPreemptiveProgressProvider = null; private Boolean mIsTablet = null; @@ -88,6 +90,8 @@ public LauncherUnfoldAnimationController( unfoldTransitionProgressProvider); } + unfoldTransitionProgressProvider.addCallback(mExternalTransitionStatusProvider); + mUnfoldMoveFromCenterHotseatAnimator = new UnfoldMoveFromCenterHotseatAnimator(launcher, windowManager, rotationChangeProvider); mUnfoldMoveFromCenterWorkspaceAnimator = new UnfoldMoveFromCenterWorkspaceAnimator(launcher, @@ -166,11 +170,26 @@ public void onDeviceProfileChanged(DeviceProfile dp) { } if (mIsTablet != null && dp.isTablet != mIsTablet) { - if (dp.isTablet && SystemUiProxy.INSTANCE.get(mLauncher).isActive()) { + // We should preemptively start the animation only if: + // - We changed to the unfolded screen + // - SystemUI IPC connection is alive, so we won't end up in a situation that we won't + // receive transition progress events from SystemUI later because there was no + // IPC connection established (e.g. because of SystemUI crash) + // - SystemUI has not already sent unfold animation progress events. This might happen + // if Launcher was not open during unfold, in this case we receive the configuration + // change only after we went back to home screen and we don't want to start the + // animation in this case. + if (dp.isTablet + && SystemUiProxy.INSTANCE.get(mLauncher).isActive() + && !mExternalTransitionStatusProvider.hasRun()) { // Preemptively start the unfold animation to make sure that we have drawn // the first frame of the animation before the screen gets unblocked preemptivelyStartAnimationOnNextFrame(); } + + if (!dp.isTablet) { + mExternalTransitionStatusProvider.onFolded(); + } } mIsTablet = dp.isTablet; @@ -222,4 +241,48 @@ private void setScale(float value) { HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } + + /** + * Class to track the current status of the external transition provider (the events are coming + * from the SystemUI side through IPC), it allows to check if the transition has already + * finished or currently running on the SystemUI side since last unfold. + */ + private static class TransitionStatusProvider implements TransitionProgressListener { + + private boolean mHasRun = false; + + @Override + public void onTransitionStarted() { + markAsRun(); + } + + @Override + public void onTransitionProgress(float progress) { + markAsRun(); + } + + @Override + public void onTransitionFinished() { + markAsRun(); + } + + /** + * Called when the device is folded, so we can reset the status of the animation + */ + public void onFolded() { + mHasRun = false; + } + + /** + * Returns true if there was an animation already (or it is currently running) after + * unfolding the device + */ + public boolean hasRun() { + return mHasRun; + } + + private void markAsRun() { + mHasRun = true; + } + } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b255ea8a180..76574b69c79 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -302,7 +302,7 @@ public static boolean showFlagTogglerUi(Context context) { "Enable widget transition animation when resizing the widgets"); public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", DISABLED, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); From c02dabfb5973764fbf5dc3c271aaf31d592f61c0 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 3 Aug 2023 15:32:46 +0100 Subject: [PATCH 39/44] Fix return condition in getWorkspacePageTranslationProvider - When EDIT_MODE was introduced, it added a wrong condition to make it always return DEFAULT_PAGE_TRANSLATION_PROVIDER Bug: 294228521 Test: manual (cherry picked from commit c325c686c73498a7041a2bd85a97c03583f2526c) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4bfc0ee720e4ee80035c7ef59cf2d8d095cf9d72) Merged-In: If970949c8ab55bc67f98f987a7654ec2db89cdfb Change-Id: If970949c8ab55bc67f98f987a7654ec2db89cdfb --- src/com/android/launcher3/LauncherState.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 8b124dc847e..6097fb19475 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -331,8 +331,7 @@ public float getPageAlpha(int pageIndex) { * Gets the translation provider for workspace pages. */ public PageTranslationProvider getWorkspacePageTranslationProvider(Launcher launcher) { - if (this != SPRING_LOADED - || this != EDIT_MODE + if (!(this == SPRING_LOADED || this == EDIT_MODE) || !launcher.getDeviceProfile().isTwoPanels) { return DEFAULT_PAGE_TRANSLATION_PROVIDER; } From b38e61a3397806e23e57bfd8c2df0102e8bb64f2 Mon Sep 17 00:00:00 2001 From: Luca Zuccarini Date: Wed, 26 Jul 2023 15:24:43 +0000 Subject: [PATCH 40/44] Animate depth from the right value on Taskbar All Apps launches. `MyDepthController` in `QuickstepTransitionLauncher` assumes that we want the background to always animate the same way, matching the rest state of the workspace (depth == 0). However, in Taskbar All Apps the background is visible, and depth != 0. We now initialize the one-off `DepthController` for launches to take into account the latest depth set by the top level `DepthController`, so there is no jumpcut at the beginning of the animation. Note that in my opinion we should use the same `DepthController` for all cases, rather than having this one-off. I'm looking into the feasibility of that change, but for now this fixes the issue at hand. Fix: 292959100 Flag: N/A Test: manual, see videos in the bug (cherry picked from commit 627d67549f73c4c456537f814e450fa8a1318937) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3e91646d123abbe58ccc0544746145ce5024b923) Merged-In: Id90e8e728cc3e2ccf7d92148fbb0d6ff3e6fd6ca Change-Id: Id90e8e728cc3e2ccf7d92148fbb0d6ff3e6fd6ca --- .../android/launcher3/QuickstepTransitionManager.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index ca9c5771b12..75f25ac7c2b 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -1046,7 +1046,7 @@ private ObjectAnimator getBackgroundAnimator() { boolean allowBlurringLauncher = mLauncher.getStateManager().getState() != OVERVIEW && BlurUtils.supportsBlursOnWindows(); - MyDepthController depthController = new MyDepthController(mLauncher); + LaunchDepthController depthController = new LaunchDepthController(mLauncher); ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController.stateDepth, MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mLauncher)) .setDuration(APP_LAUNCH_DURATION); @@ -2047,11 +2047,14 @@ protected float getWindowAlpha(float progress) { } } - private static class MyDepthController extends DepthController { - MyDepthController(Launcher l) { - super(l); + private static class LaunchDepthController extends DepthController { + LaunchDepthController(QuickstepLauncher launcher) { + super(launcher); setCrossWindowBlursEnabled( CrossWindowBlurListeners.getInstance().isCrossWindowBlurEnabled()); + // Make sure that the starting value matches the current depth set by the main + // controller. + stateDepth.setValue(launcher.getDepthController().stateDepth.getValue()); } } } From c0a78600456d8e7b2d17e5e9c92a0e9793496861 Mon Sep 17 00:00:00 2001 From: MrSluffy Date: Fri, 9 Feb 2024 07:45:04 +0800 Subject: [PATCH 41/44] Fix conflicts --- lawnchair/res/color/widgets_picker_scrim.xml | 22 + .../com/android/quickstep/TaskViewUtils.java | 6 +- .../quickstep/interaction/AllSetActivity.java | 6 +- .../LauncherUnfoldAnimationController.java | 44 -- .../launcher3/config/FeatureFlags.java | 480 ++++++++---------- .../launcher3/folder/LauncherDelegate.java | 4 +- 6 files changed, 241 insertions(+), 321 deletions(-) create mode 100644 lawnchair/res/color/widgets_picker_scrim.xml diff --git a/lawnchair/res/color/widgets_picker_scrim.xml b/lawnchair/res/color/widgets_picker_scrim.xml new file mode 100644 index 00000000000..fd868fb8881 --- /dev/null +++ b/lawnchair/res/color/widgets_picker_scrim.xml @@ -0,0 +1,22 @@ + + + + + diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index b8c9f1e9d62..289801c1a08 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -494,13 +494,11 @@ public void onAnimationEnd(Animator animation) { } } if (taskId == initialTaskId) { - splitRoot1 = change.getParent() == null ? change : - transitionInfo.getChange(change.getParent()); + splitRoot1 = change.getParent() == null ? change : transitionInfo.getChange(change.getParent()); openingTargets.add(splitRoot1.getLeash()); } if (taskId == secondTaskId) { - splitRoot2 = change.getParent() == null ? change : - transitionInfo.getChange(change.getParent()); + splitRoot2 = change.getParent() == null ? change : transitionInfo.getChange(change.getParent()); openingTargets.add(splitRoot2.getLeash()); } } diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java index b4738a027c5..1a820a5c143 100644 --- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java @@ -270,9 +270,9 @@ protected void onResume() { private void onTISConnected(TISBinder binder) { setSetupUIVisible(isResumed()); - mBinder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null); - mBinder.setOverviewTargetChangeListener(mBinder::preloadOverviewForSUWAllSet); - mBinder.preloadOverviewForSUWAllSet(); + binder.setSwipeUpProxy(isResumed() ? this::createSwipeUpProxy : null); + binder.setOverviewTargetChangeListener(binder::preloadOverviewForSUWAllSet); + binder.preloadOverviewForSUWAllSet(); TaskbarManager taskbarManager = binder.getTaskbarManager(); if (taskbarManager != null) { mLauncherStartAnim = taskbarManager.createLauncherStartFromSuwAnim(MAX_SWIPE_DURATION); diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index c3f1bdf4b8f..700e46f7c00 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -293,48 +293,4 @@ private void markAsRun() { mHasRun = true; } } - - /** - * Class to track the current status of the external transition provider (the events are coming - * from the SystemUI side through IPC), it allows to check if the transition has already - * finished or currently running on the SystemUI side since last unfold. - */ - private static class TransitionStatusProvider implements TransitionProgressListener { - - private boolean mHasRun = false; - - @Override - public void onTransitionStarted() { - markAsRun(); - } - - @Override - public void onTransitionProgress(float progress) { - markAsRun(); - } - - @Override - public void onTransitionFinished() { - markAsRun(); - } - - /** - * Called when the device is folded, so we can reset the status of the animation - */ - public void onFolded() { - mHasRun = false; - } - - /** - * Returns true if there was an animation already (or it is currently running) after - * unfolding the device - */ - public boolean hasRun() { - return mHasRun; - } - - private void markAsRun() { - mHasRun = true; - } - } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index cac3763fa7c..8993636c1a5 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -46,273 +46,219 @@ *

All the flags should be defined here with appropriate default values. */ public final class FeatureFlags { - - @VisibleForTesting - public static Predicate sBooleanReader = f -> f.mCurrentValue; - @VisibleForTesting - public static ToIntFunction sIntReader = f -> f.mCurrentValue; - - private FeatureFlags() { } - - public static boolean showFlagTogglerUi(Context context) { - return BuildConfig.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context); - } - - /** - * True when the build has come from Android Studio and is being used for local debugging. - * @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly - */ - @Deprecated - public static final boolean IS_STUDIO_BUILD = BuildConfig.IS_STUDIO_BUILD; - - /** - * Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature - * and should be modified at a project level. - * @deprecated Use {@link BuildConfig#QSB_ON_FIRST_SCREEN} directly - */ - @Deprecated - public static final boolean QSB_ON_FIRST_SCREEN = BuildConfig.QSB_ON_FIRST_SCREEN; - - /** - * Feature flag to handle define config changes dynamically instead of killing the process. - *

- * - * To add a new flag that can be toggled through the flags UI: - *

- * Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"), - * and set a default value for the flag. This will be the default value on Debug builds. - *

- */ - // TODO(Block 1): Clean up flags - public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = getReleaseFlag(270394223, - "ENABLE_ONE_SEARCH_MOTION", ENABLED, "Enables animations in OneSearch."); - - public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag( - 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", DISABLED, - "Enable option to replace decorator-based search result backgrounds with drawables"); - - public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag( - 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", DISABLED, - "Enable option to launch search results using the new view container transitions"); - - // TODO(Block 2): Clean up flags - public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073, - "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED, - "Allow bottom sheet depth to be smaller than 1 for multi-display devices."); - - // TODO(Block 3): Clean up flags - public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476, - "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED, - "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"); - - public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171, - "CONTINUOUS_VIEW_TREE_CAPTURE", ENABLED, "Capture View tree every frame"); - - public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424, - "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED, - "load the current workspace screen visible to the user before the rest rather than " - + "loading all of them at once."); - - public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424, - "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED, - "changes the timing of the loading and binding of delegate items during " - + "data preparation for loading the home screen"); - - // TODO(Block 4): Cleanup flags - public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR = - getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED, - "Keep All Apps search bar at the bottom (but above keyboard if open)"); - - public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW = - getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED, - "Allow entering All Apps from Overview (e.g. long swipe up from app)"); - - public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag( - 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED, - "Enable option to show keyboard when going to all-apps"); - - // TODO(Block 5): Clean up flags - public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851, - "ENABLE_TWOLINE_DEVICESEARCH", TEAMFOOD, - "Enable two line label for icons with labels on device search."); - - public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143, - "ENABLE_ICON_IN_TEXT_HEADER", DISABLED, "Show icon in textheader"); - - public static final BooleanFlag ENABLE_PREMIUM_HAPTICS_ALL_APPS = getDebugFlag(270396358, - "ENABLE_PREMIUM_HAPTICS_ALL_APPS", DISABLED, - "Enables haptics opening/closing All apps"); - - // TODO(Block 6): Clean up flags - public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900, - "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED, - "Enables Search box in Taskbar All Apps."); - - public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140, - "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED, - "Enable dragging and dropping to pin apps within secondary display"); - - // TODO(Block 7): Clean up flags - public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209, - "ENABLE_FORCED_MONO_ICON", DISABLED, - "Enable the ability to generate monochromatic icons, if it is not provided by the app"); - - // TODO(Block 8): Clean up flags - public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516, - "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U"); - - // TODO(Block 9): Clean up flags - public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134, - "ENABLE_DOWNLOAD_APP_UX_V2", ENABLED, "Updates the download app UX" - + " to have better visuals"); - - public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186, - "ENABLE_DOWNLOAD_APP_UX_V3", ENABLED, "Updates the download app UX" - + " to have better visuals, improve contrast, and color"); - - public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278, - "SHOW_DOT_PAGINATION", ENABLED, "Enable showing dot pagination in workspace"); - - public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809, - "LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes " - + "advantage of large screen format"); - - public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220, - "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode " - + "for home screen"); - - // TODO(Block 10): Clean up flags - public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790, - "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED, - "Enables predictive back animation from all apps and widgets to home"); - - // TODO(Block 11): Clean up flags - public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(270392643, - "ENABLE_TWO_PANEL_HOME", ENABLED, - "Uses two panel on home screen. Only applicable on large screen devices."); - - public static final BooleanFlag FOLDABLE_WORKSPACE_REORDER = getDebugFlag(270395070, - "FOLDABLE_WORKSPACE_REORDER", DISABLED, - "In foldables, when reordering the icons and widgets, is now going to use both sides"); - - public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, - "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); - - // TODO(Block 12): Clean up flags - public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, - "ENABLE_MULTI_INSTANCE", DISABLED, - "Enables creation and filtering of multiple task instances in overview"); - - // TODO(Block 13): Clean up flags - public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag( - 270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", DISABLED, - "Allows on device search in all apps logging"); - - // TODO(Block 14): Cleanup flags - public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES", - TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception."); - - public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798, - "ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar."); - - // TODO(Block 16): Clean up flags - // When enabled the promise icon is visible in all apps while installation an app. - public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012, - "PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps"); - - public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904, - "KEYGUARD_ANIMATION", DISABLED, - "Enable animation for keyguard going away on wallpaper"); - - public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907, - "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps"); - - public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930, - "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps"); - - public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779, - "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED, - "Expand and collapse pause work button while scrolling"); - - public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455, - "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log"); - - public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937, - "ENABLE_TWOLINE_ALLAPPS", TEAMFOOD, "Enables two line label inside all apps."); - - public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693, - "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps"); - - public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653, - "ENABLE_PEOPLE_TILE_PREVIEW", DISABLED, - "Experimental: Shows conversation shortcuts on home screen as search results"); - - public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638, - "FOLDER_NAME_MAJORITY_RANKING", ENABLED, - "Suggests folder names based on majority based ranking."); - - public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706, - "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED, - "Inject fallback app corpus result when AiAi fails to return it."); - - // TODO(Block 17): Clean up flags - public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583, - "ENABLE_TASKBAR_PINNING", DISABLED, - "Enables taskbar pinning to allow user to switch between transient and persistent " - + "taskbar flavors"); - - // TODO(Block 18): Clean up flags - public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(270395567, - "ENABLE_LAUNCH_FROM_STAGED_APP", ENABLED, - "Enable the ability to tap a staged app during split select to launch it in full " - + "screen"); - - public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428, - "ENABLE_APP_PAIRS", DISABLED, - "Enables the ability to create and save app pairs on the Home screen for easy" - + " split screen launching."); - - // TODO(Block 19): Clean up flags - public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177, - "SCROLL_TOP_TO_RESET", ENABLED, - "Bring up IME and focus on input when scroll to top if 'Always show keyboard'" - + " is enabled or in prefix state"); - - public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269, - "ENABLE_SEARCH_UNINSTALLED_APPS", DISABLED, "Search uninstalled app results."); - - // TODO(Block 20): Clean up flags - public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276, - "ENABLE_SCRIM_FOR_APP_LAUNCH", DISABLED, "Enables scrim during app launch animation."); - - public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426, - "ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED, - "Enables home animation to icon when user swipes back."); - - // TODO(Block 21): Clean up flags - public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087, - "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut"); - - // TODO(Block 22): Clean up flags - public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209, - "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED, - "Enables receiving unfold animation events from sysui instead of calculating " - + "them in launcher process using hinge sensor values."); - - public static final BooleanFlag ENABLE_WIDGET_TRANSITION_FOR_RESIZING = getDebugFlag(268553314, - "ENABLE_WIDGET_TRANSITION_FOR_RESIZING", DISABLED, - "Enable widget transition animation when resizing the widgets"); - - public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, - "Enables starting the unfold animation preemptively when unfolding, without" - + "waiting for SystemUI and then merging the SystemUI progress whenever we " - + "start receiving the events"); - - // TODO(Block 23): Clean up flags - public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206, - "ENABLE_GRID_ONLY_OVERVIEW", DISABLED, - "Enable a grid-only overview without a focused task."); + @VisibleForTesting + public static Predicate sBooleanReader = f -> f.mCurrentValue; + @VisibleForTesting + public static ToIntFunction sIntReader = f -> f.mCurrentValue; + private FeatureFlags() { } + public static boolean showFlagTogglerUi(Context context) { + return Utilities.isDevelopersOptionsEnabled(context); + } + /** + * True when the build has come from Android Studio and is being used for local debugging. + * @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly + */ + @Deprecated + public static final boolean IS_STUDIO_BUILD = false; + /** + * Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature + * and should be modified at a project level. + * @deprecated Use {@link BuildConfig#QSB_ON_FIRST_SCREEN} directly + */ + @Deprecated + public static boolean topQsbOnFirstScreenEnabled(Context context) { + PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); + return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableSmartspace()); + } + public static boolean showDotPagination(Context context) { + PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); + return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableDotPagination()); + } + public static boolean showMaterialUPopup(Context context) { + PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); + return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableMaterialUPopUp()); + } + /** + * Feature flag to handle define config changes dynamically instead of killing the process. + *

+ * + * To add a new flag that can be toggled through the flags UI: + *

+ * Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"), + * and set a default value for the flag. This will be the default value on Debug builds. + *

+ */ + // TODO(Block 1): Clean up flags + public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag( + 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED, + "Enable option to replace decorator-based search result backgrounds with drawables"); + public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag( + 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED, + "Enable option to launch search results using the new view container transitions"); + // TODO(Block 2): Clean up flags + public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073, + "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED, + "Allow bottom sheet depth to be smaller than 1 for multi-display devices."); + // TODO(Block 3): Clean up flags + public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476, + "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED, + "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"); + public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171, + "CONTINUOUS_VIEW_TREE_CAPTURE", DISABLED, "Capture View tree every frame"); + public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424, + "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED, + "load the current workspace screen visible to the user before the rest rather than " + + "loading all of them at once."); + public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424, + "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED, + "changes the timing of the loading and binding of delegate items during " + + "data preparation for loading the home screen"); + // TODO(Block 4): Cleanup flags + public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR = + getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED, + "Allow search bar to persist and animate across states, and attach to" + + " the keyboard from the bottom of the screen"); + public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW = + getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED, + "Allow entering All Apps from Overview (e.g. long swipe up from app)"); + public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag( + 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED, + "Enable option to show keyboard when going to all-apps"); + // TODO(Block 5): Clean up flags + public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851, + "ENABLE_TWOLINE_DEVICESEARCH", ENABLED, + "Enable two line label for icons with labels on device search."); + public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143, + "ENABLE_ICON_IN_TEXT_HEADER", DISABLED, "Show icon in textheader"); + public static final BooleanFlag ENABLE_PREMIUM_HAPTICS_ALL_APPS = getDebugFlag(270396358, + "ENABLE_PREMIUM_HAPTICS_ALL_APPS", DISABLED, + "Enables haptics opening/closing All apps"); + // TODO(Block 6): Clean up flags + public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900, + "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED, + "Enables Search box in Taskbar All Apps."); + public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140, + "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED, + "Enable dragging and dropping to pin apps within secondary display"); + // TODO(Block 7): Clean up flags + public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209, + "ENABLE_FORCED_MONO_ICON", DISABLED, + "Enable the ability to generate monochromatic icons, if it is not provided by the app"); + // TODO(Block 8): Clean up flags + public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516, + "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U"); + // TODO(Block 9): Clean up flags + public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134, + "ENABLE_DOWNLOAD_APP_UX_V2", ENABLED, "Updates the download app UX" + + " to have better visuals"); + public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186, + "ENABLE_DOWNLOAD_APP_UX_V3", ENABLED, "Updates the download app UX" + + " to have better visuals, improve contrast, and color"); + public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278, + "SHOW_DOT_PAGINATION", ENABLED, "Enable showing dot pagination in workspace"); + public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809, + "LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes " + + "advantage of large screen format"); + public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220, + "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode " + + "for home screen"); + // TODO(Block 10): Clean up flags + public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790, + "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED, + "Enables predictive back animation from all apps and widgets to home"); + // TODO(Block 11): Clean up flags + public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, + "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); + public static final BooleanFlag ENABLE_PARAMETRIZE_REORDER = getDebugFlag(289420844, + "ENABLE_PARAMETRIZE_REORDER", DISABLED, + "Enables generating the reorder using a set of parameters"); + // TODO(Block 12): Clean up flags + public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, + "ENABLE_MULTI_INSTANCE", DISABLED, + "Enables creation and filtering of multiple task instances in overview"); + // TODO(Block 13): Clean up flags + public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag( + 270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", DISABLED, + "Allows on device search in all apps logging"); + // TODO(Block 14): Cleanup flags + public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES", + TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception."); + public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798, + "ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar."); + // TODO(Block 16): Clean up flags + // When enabled the promise icon is visible in all apps while installation an app. + public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012, + "PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps"); + public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904, + "KEYGUARD_ANIMATION", DISABLED, + "Enable animation for keyguard going away on wallpaper"); + public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907, + "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps"); + public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930, + "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps"); + public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779, + "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED, + "Expand and collapse pause work button while scrolling"); + public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455, + "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log"); + public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937, + "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps."); + public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693, + "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps"); + public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653, + "ENABLE_PEOPLE_TILE_PREVIEW", DISABLED, + "Experimental: Shows conversation shortcuts on home screen as search results"); + public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638, + "FOLDER_NAME_MAJORITY_RANKING", ENABLED, + "Suggests folder names based on majority based ranking."); + public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706, + "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED, + "Inject fallback app corpus result when AiAi fails to return it."); + public static final BooleanFlag ENABLE_LONG_PRESS_NAV_HANDLE = + getReleaseFlag(282993230, "ENABLE_LONG_PRESS_NAV_HANDLE_MPR", TEAMFOOD, + "Enables long pressing on the bottom bar nav handle to trigger events."); + // TODO(Block 17): Clean up flags + public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583, + "ENABLE_TASKBAR_PINNING", DISABLED, + "Enables taskbar pinning to allow user to switch between transient and persistent " + + "taskbar flavors"); + // TODO(Block 18): Clean up flags + public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428, + "ENABLE_APP_PAIRS", DISABLED, + "Enables the ability to create and save app pairs on the Home screen for easy" + + " split screen launching."); + // TODO(Block 19): Clean up flags + public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177, + "SCROLL_TOP_TO_RESET", ENABLED, + "Bring up IME and focus on input when scroll to top if 'Always show keyboard'" + + " is enabled or in prefix state"); + public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269, + "ENABLE_SEARCH_UNINSTALLED_APPS", ENABLED, "Search uninstalled app results."); + // TODO(Block 20): Clean up flags + public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276, + "ENABLE_SCRIM_FOR_APP_LAUNCH", DISABLED, "Enables scrim during app launch animation."); + public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426, + "ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED, + "Enables home animation to icon when user swipes back."); + public static final BooleanFlag ENABLE_DYNAMIC_TASKBAR_THRESHOLDS = getDebugFlag(294252473, + "ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED, + "Enables taskbar thresholds that scale based on screen size."); + // TODO(Block 21): Clean up flags + public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087, + "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut"); + // TODO(Block 22): Clean up flags + public static final BooleanFlag ENABLE_WIDGET_TRANSITION_FOR_RESIZING = getDebugFlag(268553314, + "ENABLE_WIDGET_TRANSITION_FOR_RESIZING", DISABLED, + "Enable widget transition animation when resizing the widgets"); + public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, + "Enables starting the unfold animation preemptively when unfolding, without" + + "waiting for SystemUI and then merging the SystemUI progress whenever we " + + "start receiving the events"); + // TODO(Block 23): Clean up flags + public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206, + "ENABLE_GRID_ONLY_OVERVIEW", TEAMFOOD, + "Enable a grid-only overview without a focused task."); public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(270397202, "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED, diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java index 51a37873842..6fea1f96d81 100644 --- a/src/com/android/launcher3/folder/LauncherDelegate.java +++ b/src/com/android/launcher3/folder/LauncherDelegate.java @@ -94,9 +94,7 @@ public void run() { // folder CellLayout cellLayout = mLauncher.getCellLayout(info.container, mLauncher.getCellPosMapper().mapModelToPresenter(info).screenId); - if (cellLayout == null) { - return; - } + if (cellLayout == null) return; finalItem = info.contents.remove(0); newIcon = mLauncher.createShortcut(cellLayout, finalItem); mLauncher.getModelWriter().addOrMoveItemInDatabase(finalItem, From e20638aa2cb8b2ade2f88b8684c38da84a7d24a7 Mon Sep 17 00:00:00 2001 From: Goooler Date: Fri, 9 Feb 2024 09:07:39 +0800 Subject: [PATCH 42/44] Revert format changes --- .../com/android/quickstep/TaskViewUtils.java | 6 +- .../launcher3/config/FeatureFlags.java | 668 +++++++++--------- .../launcher3/folder/LauncherDelegate.java | 4 +- 3 files changed, 341 insertions(+), 337 deletions(-) diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 289801c1a08..b8c9f1e9d62 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -494,11 +494,13 @@ public void onAnimationEnd(Animator animation) { } } if (taskId == initialTaskId) { - splitRoot1 = change.getParent() == null ? change : transitionInfo.getChange(change.getParent()); + splitRoot1 = change.getParent() == null ? change : + transitionInfo.getChange(change.getParent()); openingTargets.add(splitRoot1.getLeash()); } if (taskId == secondTaskId) { - splitRoot2 = change.getParent() == null ? change : transitionInfo.getChange(change.getParent()); + splitRoot2 = change.getParent() == null ? change : + transitionInfo.getChange(change.getParent()); openingTargets.add(splitRoot2.getLeash()); } } diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 8993636c1a5..09db6d15476 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -46,342 +46,342 @@ *

All the flags should be defined here with appropriate default values. */ public final class FeatureFlags { - @VisibleForTesting - public static Predicate sBooleanReader = f -> f.mCurrentValue; - @VisibleForTesting - public static ToIntFunction sIntReader = f -> f.mCurrentValue; - private FeatureFlags() { } - public static boolean showFlagTogglerUi(Context context) { - return Utilities.isDevelopersOptionsEnabled(context); - } - /** - * True when the build has come from Android Studio and is being used for local debugging. - * @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly - */ - @Deprecated - public static final boolean IS_STUDIO_BUILD = false; - /** - * Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature - * and should be modified at a project level. - * @deprecated Use {@link BuildConfig#QSB_ON_FIRST_SCREEN} directly - */ - @Deprecated - public static boolean topQsbOnFirstScreenEnabled(Context context) { - PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); - return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableSmartspace()); - } - public static boolean showDotPagination(Context context) { - PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); - return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableDotPagination()); - } - public static boolean showMaterialUPopup(Context context) { - PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); - return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableMaterialUPopUp()); - } - /** - * Feature flag to handle define config changes dynamically instead of killing the process. - *

- * - * To add a new flag that can be toggled through the flags UI: - *

- * Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"), - * and set a default value for the flag. This will be the default value on Debug builds. - *

- */ - // TODO(Block 1): Clean up flags - public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag( - 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED, - "Enable option to replace decorator-based search result backgrounds with drawables"); - public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag( - 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED, - "Enable option to launch search results using the new view container transitions"); - // TODO(Block 2): Clean up flags - public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073, - "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED, - "Allow bottom sheet depth to be smaller than 1 for multi-display devices."); - // TODO(Block 3): Clean up flags - public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476, - "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED, - "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"); - public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171, - "CONTINUOUS_VIEW_TREE_CAPTURE", DISABLED, "Capture View tree every frame"); - public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424, - "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED, - "load the current workspace screen visible to the user before the rest rather than " - + "loading all of them at once."); - public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424, - "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED, - "changes the timing of the loading and binding of delegate items during " - + "data preparation for loading the home screen"); - // TODO(Block 4): Cleanup flags - public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR = - getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED, - "Allow search bar to persist and animate across states, and attach to" - + " the keyboard from the bottom of the screen"); - public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW = - getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED, - "Allow entering All Apps from Overview (e.g. long swipe up from app)"); - public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag( - 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED, - "Enable option to show keyboard when going to all-apps"); - // TODO(Block 5): Clean up flags - public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851, - "ENABLE_TWOLINE_DEVICESEARCH", ENABLED, - "Enable two line label for icons with labels on device search."); - public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143, - "ENABLE_ICON_IN_TEXT_HEADER", DISABLED, "Show icon in textheader"); - public static final BooleanFlag ENABLE_PREMIUM_HAPTICS_ALL_APPS = getDebugFlag(270396358, - "ENABLE_PREMIUM_HAPTICS_ALL_APPS", DISABLED, - "Enables haptics opening/closing All apps"); - // TODO(Block 6): Clean up flags - public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900, - "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED, - "Enables Search box in Taskbar All Apps."); - public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140, - "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED, - "Enable dragging and dropping to pin apps within secondary display"); - // TODO(Block 7): Clean up flags - public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209, - "ENABLE_FORCED_MONO_ICON", DISABLED, - "Enable the ability to generate monochromatic icons, if it is not provided by the app"); - // TODO(Block 8): Clean up flags - public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516, - "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U"); - // TODO(Block 9): Clean up flags - public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134, - "ENABLE_DOWNLOAD_APP_UX_V2", ENABLED, "Updates the download app UX" - + " to have better visuals"); - public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186, - "ENABLE_DOWNLOAD_APP_UX_V3", ENABLED, "Updates the download app UX" - + " to have better visuals, improve contrast, and color"); - public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278, - "SHOW_DOT_PAGINATION", ENABLED, "Enable showing dot pagination in workspace"); - public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809, - "LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes " - + "advantage of large screen format"); - public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220, - "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode " - + "for home screen"); - // TODO(Block 10): Clean up flags - public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790, - "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED, - "Enables predictive back animation from all apps and widgets to home"); - // TODO(Block 11): Clean up flags - public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, - "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); - public static final BooleanFlag ENABLE_PARAMETRIZE_REORDER = getDebugFlag(289420844, - "ENABLE_PARAMETRIZE_REORDER", DISABLED, - "Enables generating the reorder using a set of parameters"); - // TODO(Block 12): Clean up flags - public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, - "ENABLE_MULTI_INSTANCE", DISABLED, - "Enables creation and filtering of multiple task instances in overview"); - // TODO(Block 13): Clean up flags - public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag( - 270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", DISABLED, - "Allows on device search in all apps logging"); - // TODO(Block 14): Cleanup flags - public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES", - TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception."); - public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798, - "ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar."); - // TODO(Block 16): Clean up flags - // When enabled the promise icon is visible in all apps while installation an app. - public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012, - "PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps"); - public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904, - "KEYGUARD_ANIMATION", DISABLED, - "Enable animation for keyguard going away on wallpaper"); - public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907, - "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps"); - public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930, - "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps"); - public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779, - "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED, - "Expand and collapse pause work button while scrolling"); - public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455, - "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log"); - public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937, - "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps."); - public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693, - "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps"); - public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653, - "ENABLE_PEOPLE_TILE_PREVIEW", DISABLED, - "Experimental: Shows conversation shortcuts on home screen as search results"); - public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638, - "FOLDER_NAME_MAJORITY_RANKING", ENABLED, - "Suggests folder names based on majority based ranking."); - public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706, - "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED, - "Inject fallback app corpus result when AiAi fails to return it."); - public static final BooleanFlag ENABLE_LONG_PRESS_NAV_HANDLE = - getReleaseFlag(282993230, "ENABLE_LONG_PRESS_NAV_HANDLE_MPR", TEAMFOOD, - "Enables long pressing on the bottom bar nav handle to trigger events."); - // TODO(Block 17): Clean up flags - public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583, - "ENABLE_TASKBAR_PINNING", DISABLED, - "Enables taskbar pinning to allow user to switch between transient and persistent " - + "taskbar flavors"); - // TODO(Block 18): Clean up flags - public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428, - "ENABLE_APP_PAIRS", DISABLED, - "Enables the ability to create and save app pairs on the Home screen for easy" - + " split screen launching."); - // TODO(Block 19): Clean up flags - public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177, - "SCROLL_TOP_TO_RESET", ENABLED, - "Bring up IME and focus on input when scroll to top if 'Always show keyboard'" - + " is enabled or in prefix state"); - public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269, - "ENABLE_SEARCH_UNINSTALLED_APPS", ENABLED, "Search uninstalled app results."); - // TODO(Block 20): Clean up flags - public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276, - "ENABLE_SCRIM_FOR_APP_LAUNCH", DISABLED, "Enables scrim during app launch animation."); - public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426, - "ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED, - "Enables home animation to icon when user swipes back."); - public static final BooleanFlag ENABLE_DYNAMIC_TASKBAR_THRESHOLDS = getDebugFlag(294252473, - "ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED, - "Enables taskbar thresholds that scale based on screen size."); - // TODO(Block 21): Clean up flags - public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087, - "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut"); - // TODO(Block 22): Clean up flags - public static final BooleanFlag ENABLE_WIDGET_TRANSITION_FOR_RESIZING = getDebugFlag(268553314, - "ENABLE_WIDGET_TRANSITION_FOR_RESIZING", DISABLED, - "Enable widget transition animation when resizing the widgets"); - public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, - "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, - "Enables starting the unfold animation preemptively when unfolding, without" - + "waiting for SystemUI and then merging the SystemUI progress whenever we " - + "start receiving the events"); - // TODO(Block 23): Clean up flags - public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206, - "ENABLE_GRID_ONLY_OVERVIEW", TEAMFOOD, - "Enable a grid-only overview without a focused task."); + @VisibleForTesting + public static Predicate sBooleanReader = f -> f.mCurrentValue; + @VisibleForTesting + public static ToIntFunction sIntReader = f -> f.mCurrentValue; + private FeatureFlags() { } + public static boolean showFlagTogglerUi(Context context) { + return Utilities.isDevelopersOptionsEnabled(context); + } + /** + * True when the build has come from Android Studio and is being used for local debugging. + * @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly + */ + @Deprecated + public static final boolean IS_STUDIO_BUILD = false; + /** + * Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature + * and should be modified at a project level. + * @deprecated Use {@link BuildConfig#QSB_ON_FIRST_SCREEN} directly + */ + @Deprecated + public static boolean topQsbOnFirstScreenEnabled(Context context) { + PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); + return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableSmartspace()); + } + public static boolean showDotPagination(Context context) { + PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); + return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableDotPagination()); + } + public static boolean showMaterialUPopup(Context context) { + PreferenceManager2 preferenceManager2 = PreferenceManager2.getInstance(context); + return PreferenceExtensionsKt.firstBlocking(preferenceManager2.getEnableMaterialUPopUp()); + } + /** + * Feature flag to handle define config changes dynamically instead of killing the process. + *

+ * + * To add a new flag that can be toggled through the flags UI: + *

+ * Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"), + * and set a default value for the flag. This will be the default value on Debug builds. + *

+ */ + // TODO(Block 1): Clean up flags + public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag( + 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED, + "Enable option to replace decorator-based search result backgrounds with drawables"); + public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag( + 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED, + "Enable option to launch search results using the new view container transitions"); + // TODO(Block 2): Clean up flags + public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073, + "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED, + "Allow bottom sheet depth to be smaller than 1 for multi-display devices."); + // TODO(Block 3): Clean up flags + public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476, + "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED, + "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"); + public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171, + "CONTINUOUS_VIEW_TREE_CAPTURE", DISABLED, "Capture View tree every frame"); + public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424, + "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED, + "load the current workspace screen visible to the user before the rest rather than " + + "loading all of them at once."); + public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424, + "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED, + "changes the timing of the loading and binding of delegate items during " + + "data preparation for loading the home screen"); + // TODO(Block 4): Cleanup flags + public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR = + getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED, + "Allow search bar to persist and animate across states, and attach to" + + " the keyboard from the bottom of the screen"); + public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW = + getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED, + "Allow entering All Apps from Overview (e.g. long swipe up from app)"); + public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag( + 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED, + "Enable option to show keyboard when going to all-apps"); + // TODO(Block 5): Clean up flags + public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851, + "ENABLE_TWOLINE_DEVICESEARCH", ENABLED, + "Enable two line label for icons with labels on device search."); + public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143, + "ENABLE_ICON_IN_TEXT_HEADER", DISABLED, "Show icon in textheader"); + public static final BooleanFlag ENABLE_PREMIUM_HAPTICS_ALL_APPS = getDebugFlag(270396358, + "ENABLE_PREMIUM_HAPTICS_ALL_APPS", DISABLED, + "Enables haptics opening/closing All apps"); + // TODO(Block 6): Clean up flags + public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900, + "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED, + "Enables Search box in Taskbar All Apps."); + public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140, + "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED, + "Enable dragging and dropping to pin apps within secondary display"); + // TODO(Block 7): Clean up flags + public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209, + "ENABLE_FORCED_MONO_ICON", DISABLED, + "Enable the ability to generate monochromatic icons, if it is not provided by the app"); + // TODO(Block 8): Clean up flags + public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516, + "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U"); + // TODO(Block 9): Clean up flags + public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134, + "ENABLE_DOWNLOAD_APP_UX_V2", ENABLED, "Updates the download app UX" + + " to have better visuals"); + public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186, + "ENABLE_DOWNLOAD_APP_UX_V3", ENABLED, "Updates the download app UX" + + " to have better visuals, improve contrast, and color"); + public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278, + "SHOW_DOT_PAGINATION", ENABLED, "Enable showing dot pagination in workspace"); + public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809, + "LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes " + + "advantage of large screen format"); + public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220, + "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode " + + "for home screen"); + // TODO(Block 10): Clean up flags + public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790, + "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED, + "Enables predictive back animation from all apps and widgets to home"); + // TODO(Block 11): Clean up flags + public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, + "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); + public static final BooleanFlag ENABLE_PARAMETRIZE_REORDER = getDebugFlag(289420844, + "ENABLE_PARAMETRIZE_REORDER", DISABLED, + "Enables generating the reorder using a set of parameters"); + // TODO(Block 12): Clean up flags + public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, + "ENABLE_MULTI_INSTANCE", DISABLED, + "Enables creation and filtering of multiple task instances in overview"); + // TODO(Block 13): Clean up flags + public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag( + 270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", DISABLED, + "Allows on device search in all apps logging"); + // TODO(Block 14): Cleanup flags + public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES", + TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception."); + public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798, + "ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar."); + // TODO(Block 16): Clean up flags + // When enabled the promise icon is visible in all apps while installation an app. + public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012, + "PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps"); + public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904, + "KEYGUARD_ANIMATION", DISABLED, + "Enable animation for keyguard going away on wallpaper"); + public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907, + "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps"); + public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930, + "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps"); + public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779, + "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED, + "Expand and collapse pause work button while scrolling"); + public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455, + "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log"); + public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937, + "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps."); + public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693, + "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps"); + public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653, + "ENABLE_PEOPLE_TILE_PREVIEW", DISABLED, + "Experimental: Shows conversation shortcuts on home screen as search results"); + public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638, + "FOLDER_NAME_MAJORITY_RANKING", ENABLED, + "Suggests folder names based on majority based ranking."); + public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706, + "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED, + "Inject fallback app corpus result when AiAi fails to return it."); + public static final BooleanFlag ENABLE_LONG_PRESS_NAV_HANDLE = + getReleaseFlag(282993230, "ENABLE_LONG_PRESS_NAV_HANDLE_MPR", TEAMFOOD, + "Enables long pressing on the bottom bar nav handle to trigger events."); + // TODO(Block 17): Clean up flags + public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583, + "ENABLE_TASKBAR_PINNING", DISABLED, + "Enables taskbar pinning to allow user to switch between transient and persistent " + + "taskbar flavors"); + // TODO(Block 18): Clean up flags + public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428, + "ENABLE_APP_PAIRS", DISABLED, + "Enables the ability to create and save app pairs on the Home screen for easy" + + " split screen launching."); + // TODO(Block 19): Clean up flags + public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177, + "SCROLL_TOP_TO_RESET", ENABLED, + "Bring up IME and focus on input when scroll to top if 'Always show keyboard'" + + " is enabled or in prefix state"); + public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269, + "ENABLE_SEARCH_UNINSTALLED_APPS", ENABLED, "Search uninstalled app results."); + // TODO(Block 20): Clean up flags + public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276, + "ENABLE_SCRIM_FOR_APP_LAUNCH", DISABLED, "Enables scrim during app launch animation."); + public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426, + "ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED, + "Enables home animation to icon when user swipes back."); + public static final BooleanFlag ENABLE_DYNAMIC_TASKBAR_THRESHOLDS = getDebugFlag(294252473, + "ENABLE_DYNAMIC_TASKBAR_THRESHOLDS", ENABLED, + "Enables taskbar thresholds that scale based on screen size."); + // TODO(Block 21): Clean up flags + public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087, + "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut"); + // TODO(Block 22): Clean up flags + public static final BooleanFlag ENABLE_WIDGET_TRANSITION_FOR_RESIZING = getDebugFlag(268553314, + "ENABLE_WIDGET_TRANSITION_FOR_RESIZING", DISABLED, + "Enable widget transition animation when resizing the widgets"); + public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, + "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, + "Enables starting the unfold animation preemptively when unfolding, without" + + "waiting for SystemUI and then merging the SystemUI progress whenever we " + + "start receiving the events"); + // TODO(Block 23): Clean up flags + public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206, + "ENABLE_GRID_ONLY_OVERVIEW", TEAMFOOD, + "Enable a grid-only overview without a focused task."); - public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(270397202, - "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED, - ""); + public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(270397202, + "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED, + ""); - public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209, - "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED, - "Enables receiving unfold animation events from sysui instead of calculating " - + "them in launcher proce"); + public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209, + "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED, + "Enables receiving unfold animation events from sysui instead of calculating " + + "them in launcher proce"); - public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906, - "ENABLE_SPLIT_FROM_WORKSPACE", ENABLED, - "Enable initiating split screen from workspace."); + public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906, + "ENABLE_SPLIT_FROM_WORKSPACE", ENABLED, + "Enable initiating split screen from workspace."); - public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650, - "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD, - "Enables cursor hover states for certain elements."); - // TODO(Block 24): Clean up flags - public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455, - "ENABLE_NEW_MIGRATION_LOGIC", ENABLED, - "Enable the new grid migration logic, keeping pages when src < dest"); - public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(270395008, - "ENABLE_CACHED_WIDGET", ENABLED, - "Show previously cached widgets as opposed to deferred widget where available"); - // TODO(Block 25): Clean up flags - public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(270396257, - "ENABLE_NEW_GESTURE_NAV_TUTORIAL", ENABLED, - "Enable the redesigned gesture navigation tutorial"); - // TODO(Block 26): Clean up flags - public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(270394384, - "ENABLE_WIDGET_HOST_IN_BACKGROUND", ENABLED, - "Enable background widget updates listening for widget holder"); - // TODO(Block 27): Clean up flags - public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(270392629, - "ENABLE_OVERLAY_CONNECTION_OPTIM", DISABLED, - "Enable optimizing overlay service connection"); - /** - * Enables region sampling for text color: Needs system health assessment before turning on - */ - public static final BooleanFlag ENABLE_REGION_SAMPLING = getDebugFlag(270391669, - "ENABLE_REGION_SAMPLING", DISABLED, - "Enable region sampling to determine color of text on screen."); - public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS = - getDebugFlag(270393096, "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", - DISABLED, "Always use hardware optimization for folder animations."); - public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(270392980, - "SEPARATE_RECENTS_ACTIVITY", DISABLED, - "Uses a separate recents activity instead of using the integrated recents+Launcher UI"); - public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = getReleaseFlag(270393258, - "ENABLE_ENFORCED_ROUNDED_CORNERS", ENABLED, - "Enforce rounded corners on all App Widgets"); - public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(270393294, - "ENABLE_ICON_LABEL_AUTO_SCALING", ENABLED, - "Enables scaling/spacing for icon labels to make more characters visible"); - public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(270394973, - "USE_LOCAL_ICON_OVERRIDES", ENABLED, - "Use inbuilt monochrome icons if app doesn't provide one"); - // TODO(Block 28): Clean up flags - public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS = - getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", DISABLED, - "Enable splitting from fullscreen app with keyboard shortcuts"); - public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag( - 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED, - "Enable initiating split screen from workspace to workspace."); - public static final BooleanFlag ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE = getDebugFlag( - 279586624, "ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE", DISABLED, - "Enable initiating split screen from desktop mode to workspace."); - public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401, - "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture."); - // TODO(Block 29): Clean up flags - public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897, - "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", DISABLED, - "Enables displaying the all apps button in the hotseat."); - public static final BooleanFlag ENABLE_KEYBOARD_QUICK_SWITCH = getDebugFlag(270396844, - "ENABLE_KEYBOARD_QUICK_SWITCH", ENABLED, "Enables keyboard quick switching"); - public static final BooleanFlag ENABLE_KEYBOARD_TASKBAR_TOGGLE = getDebugFlag(281726846, - "ENABLE_KEYBOARD_TASKBAR_TOGGLE", ENABLED, - "Enables keyboard taskbar stash toggling"); - // TODO(Block 30): Clean up flags - public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(270395010, - "USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED, - "Use local overrides for search request timeout"); - // TODO(Block 31): Clean up flags - // TODO(Block 32): Clean up flags - public static final BooleanFlag ENABLE_RESPONSIVE_WORKSPACE = getDebugFlag(241386436, - "ENABLE_RESPONSIVE_WORKSPACE", ENABLED, - "Enables new workspace grid calculations method."); - // TODO(Block 33): Clean up flags - public static final BooleanFlag ENABLE_ALL_APPS_RV_PREINFLATION = getDebugFlag(288161355, - "ENABLE_ALL_APPS_RV_PREINFLATION", ENABLED, - "Enables preinflating all apps icons to avoid scrolling jank."); - // TODO(Block 34): Clean up flags - public static final BooleanFlag ALL_APPS_GONE_VISIBILITY = getDebugFlag(291651514, - "ALL_APPS_GONE_VISIBILITY", ENABLED, - "Set all apps container view's hidden visibility to GONE instead of INVISIBLE."); - // TODO(Block 35): Empty block - public static class BooleanFlag { - private final boolean mCurrentValue; - public BooleanFlag(boolean currentValue) { - mCurrentValue = currentValue; - } - public boolean get() { - return sBooleanReader.test(this); - } - } - /** - * Class representing an integer flag - */ - public static class IntFlag { - private final int mCurrentValue; - public IntFlag(int currentValue) { - mCurrentValue = currentValue; - } - public int get() { - return sIntReader.applyAsInt(this); - } - } - /** - * Enabled state for a flag - */ - public enum FlagState { - ENABLED, - DISABLED, - TEAMFOOD // Enabled in team food - } + public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650, + "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD, + "Enables cursor hover states for certain elements."); + // TODO(Block 24): Clean up flags + public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455, + "ENABLE_NEW_MIGRATION_LOGIC", ENABLED, + "Enable the new grid migration logic, keeping pages when src < dest"); + public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(270395008, + "ENABLE_CACHED_WIDGET", ENABLED, + "Show previously cached widgets as opposed to deferred widget where available"); + // TODO(Block 25): Clean up flags + public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(270396257, + "ENABLE_NEW_GESTURE_NAV_TUTORIAL", ENABLED, + "Enable the redesigned gesture navigation tutorial"); + // TODO(Block 26): Clean up flags + public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(270394384, + "ENABLE_WIDGET_HOST_IN_BACKGROUND", ENABLED, + "Enable background widget updates listening for widget holder"); + // TODO(Block 27): Clean up flags + public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(270392629, + "ENABLE_OVERLAY_CONNECTION_OPTIM", DISABLED, + "Enable optimizing overlay service connection"); + /** + * Enables region sampling for text color: Needs system health assessment before turning on + */ + public static final BooleanFlag ENABLE_REGION_SAMPLING = getDebugFlag(270391669, + "ENABLE_REGION_SAMPLING", DISABLED, + "Enable region sampling to determine color of text on screen."); + public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS = + getDebugFlag(270393096, "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", + DISABLED, "Always use hardware optimization for folder animations."); + public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(270392980, + "SEPARATE_RECENTS_ACTIVITY", DISABLED, + "Uses a separate recents activity instead of using the integrated recents+Launcher UI"); + public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = getReleaseFlag(270393258, + "ENABLE_ENFORCED_ROUNDED_CORNERS", ENABLED, + "Enforce rounded corners on all App Widgets"); + public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(270393294, + "ENABLE_ICON_LABEL_AUTO_SCALING", ENABLED, + "Enables scaling/spacing for icon labels to make more characters visible"); + public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(270394973, + "USE_LOCAL_ICON_OVERRIDES", ENABLED, + "Use inbuilt monochrome icons if app doesn't provide one"); + // TODO(Block 28): Clean up flags + public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS = + getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", DISABLED, + "Enable splitting from fullscreen app with keyboard shortcuts"); + public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag( + 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED, + "Enable initiating split screen from workspace to workspace."); + public static final BooleanFlag ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE = getDebugFlag( + 279586624, "ENABLE_SPLIT_FROM_DESKTOP_TO_WORKSPACE", DISABLED, + "Enable initiating split screen from desktop mode to workspace."); + public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401, + "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture."); + // TODO(Block 29): Clean up flags + public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897, + "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", DISABLED, + "Enables displaying the all apps button in the hotseat."); + public static final BooleanFlag ENABLE_KEYBOARD_QUICK_SWITCH = getDebugFlag(270396844, + "ENABLE_KEYBOARD_QUICK_SWITCH", ENABLED, "Enables keyboard quick switching"); + public static final BooleanFlag ENABLE_KEYBOARD_TASKBAR_TOGGLE = getDebugFlag(281726846, + "ENABLE_KEYBOARD_TASKBAR_TOGGLE", ENABLED, + "Enables keyboard taskbar stash toggling"); + // TODO(Block 30): Clean up flags + public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(270395010, + "USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED, + "Use local overrides for search request timeout"); + // TODO(Block 31): Clean up flags + // TODO(Block 32): Clean up flags + public static final BooleanFlag ENABLE_RESPONSIVE_WORKSPACE = getDebugFlag(241386436, + "ENABLE_RESPONSIVE_WORKSPACE", ENABLED, + "Enables new workspace grid calculations method."); + // TODO(Block 33): Clean up flags + public static final BooleanFlag ENABLE_ALL_APPS_RV_PREINFLATION = getDebugFlag(288161355, + "ENABLE_ALL_APPS_RV_PREINFLATION", ENABLED, + "Enables preinflating all apps icons to avoid scrolling jank."); + // TODO(Block 34): Clean up flags + public static final BooleanFlag ALL_APPS_GONE_VISIBILITY = getDebugFlag(291651514, + "ALL_APPS_GONE_VISIBILITY", ENABLED, + "Set all apps container view's hidden visibility to GONE instead of INVISIBLE."); + // TODO(Block 35): Empty block + public static class BooleanFlag { + private final boolean mCurrentValue; + public BooleanFlag(boolean currentValue) { + mCurrentValue = currentValue; + } + public boolean get() { + return sBooleanReader.test(this); + } + } + /** + * Class representing an integer flag + */ + public static class IntFlag { + private final int mCurrentValue; + public IntFlag(int currentValue) { + mCurrentValue = currentValue; + } + public int get() { + return sIntReader.applyAsInt(this); + } + } + /** + * Enabled state for a flag + */ + public enum FlagState { + ENABLED, + DISABLED, + TEAMFOOD // Enabled in team food + } } diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java index 6fea1f96d81..51a37873842 100644 --- a/src/com/android/launcher3/folder/LauncherDelegate.java +++ b/src/com/android/launcher3/folder/LauncherDelegate.java @@ -94,7 +94,9 @@ public void run() { // folder CellLayout cellLayout = mLauncher.getCellLayout(info.container, mLauncher.getCellPosMapper().mapModelToPresenter(info).screenId); - if (cellLayout == null) return; + if (cellLayout == null) { + return; + } finalItem = info.contents.remove(0); newIcon = mLauncher.createShortcut(cellLayout, finalItem); mLauncher.getModelWriter().addOrMoveItemInDatabase(finalItem, From 058e69c3ff746957547838d7b15f9f0720914768 Mon Sep 17 00:00:00 2001 From: Goooler Date: Fri, 9 Feb 2024 09:28:01 +0800 Subject: [PATCH 43/44] Revert format changes in FeatureFlags --- .../launcher3/config/FeatureFlags.java | 171 +++++++++++++----- 1 file changed, 130 insertions(+), 41 deletions(-) diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 09db6d15476..c8807c5e845 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -46,14 +46,18 @@ *

All the flags should be defined here with appropriate default values. */ public final class FeatureFlags { + @VisibleForTesting public static Predicate sBooleanReader = f -> f.mCurrentValue; @VisibleForTesting public static ToIntFunction sIntReader = f -> f.mCurrentValue; + private FeatureFlags() { } + public static boolean showFlagTogglerUi(Context context) { return Utilities.isDevelopersOptionsEnabled(context); } + /** * True when the build has come from Android Studio and is being used for local debugging. * @deprecated Use {@link BuildConfig#IS_STUDIO_BUILD} directly @@ -89,30 +93,40 @@ public static boolean showMaterialUPopup(Context context) { *

*/ // TODO(Block 1): Clean up flags + public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = getReleaseFlag(270394223, + "ENABLE_ONE_SEARCH_MOTION", ENABLED, "Enables animations in OneSearch."); + public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag( 270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED, "Enable option to replace decorator-based search result backgrounds with drawables"); + public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag( 270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED, "Enable option to launch search results using the new view container transitions"); + // TODO(Block 2): Clean up flags public static final BooleanFlag ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH = getDebugFlag(270395073, "ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH", DISABLED, "Allow bottom sheet depth to be smaller than 1 for multi-display devices."); + // TODO(Block 3): Clean up flags public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(270394476, "ENABLE_DISMISS_PREDICTION_UNDO", DISABLED, "Show an 'Undo' snackbar when users dismiss a predicted hotseat item"); + public static final BooleanFlag CONTINUOUS_VIEW_TREE_CAPTURE = getDebugFlag(270395171, "CONTINUOUS_VIEW_TREE_CAPTURE", DISABLED, "Capture View tree every frame"); + public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424, "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", DISABLED, "load the current workspace screen visible to the user before the rest rather than " + "loading all of them at once."); + public static final BooleanFlag CHANGE_MODEL_DELEGATE_LOADING_ORDER = getDebugFlag(251502424, "CHANGE_MODEL_DELEGATE_LOADING_ORDER", DISABLED, "changes the timing of the loading and binding of delegate items during " + "data preparation for loading the home screen"); + // TODO(Block 4): Cleanup flags public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR = getReleaseFlag(268388460, "ENABLE_FLOATING_SEARCH_BAR", DISABLED, @@ -121,96 +135,131 @@ public static boolean showMaterialUPopup(Context context) { public static final BooleanFlag ENABLE_ALL_APPS_FROM_OVERVIEW = getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED, "Allow entering All Apps from Overview (e.g. long swipe up from app)"); + public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag( 270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED, "Enable option to show keyboard when going to all-apps"); + // TODO(Block 5): Clean up flags public static final BooleanFlag ENABLE_TWOLINE_DEVICESEARCH = getDebugFlag(201388851, "ENABLE_TWOLINE_DEVICESEARCH", ENABLED, "Enable two line label for icons with labels on device search."); + public static final BooleanFlag ENABLE_ICON_IN_TEXT_HEADER = getDebugFlag(270395143, "ENABLE_ICON_IN_TEXT_HEADER", DISABLED, "Show icon in textheader"); + public static final BooleanFlag ENABLE_PREMIUM_HAPTICS_ALL_APPS = getDebugFlag(270396358, "ENABLE_PREMIUM_HAPTICS_ALL_APPS", DISABLED, "Enables haptics opening/closing All apps"); + // TODO(Block 6): Clean up flags public static final BooleanFlag ENABLE_ALL_APPS_SEARCH_IN_TASKBAR = getDebugFlag(270393900, "ENABLE_ALL_APPS_SEARCH_IN_TASKBAR", DISABLED, "Enables Search box in Taskbar All Apps."); + public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(270395140, "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED, "Enable dragging and dropping to pin apps within secondary display"); + // TODO(Block 7): Clean up flags public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209, "ENABLE_FORCED_MONO_ICON", DISABLED, "Enable the ability to generate monochromatic icons, if it is not provided by the app"); + // TODO(Block 8): Clean up flags public static final BooleanFlag ENABLE_MATERIAL_U_POPUP = getDebugFlag(270395516, "ENABLE_MATERIAL_U_POPUP", ENABLED, "Switch popup UX to use material U"); + // TODO(Block 9): Clean up flags public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getReleaseFlag(270395134, "ENABLE_DOWNLOAD_APP_UX_V2", ENABLED, "Updates the download app UX" + " to have better visuals"); + public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V3 = getDebugFlag(270395186, "ENABLE_DOWNLOAD_APP_UX_V3", ENABLED, "Updates the download app UX" + " to have better visuals, improve contrast, and color"); + public static final BooleanFlag SHOW_DOT_PAGINATION = getDebugFlag(270395278, "SHOW_DOT_PAGINATION", ENABLED, "Enable showing dot pagination in workspace"); + public static final BooleanFlag LARGE_SCREEN_WIDGET_PICKER = getDebugFlag(270395809, "LARGE_SCREEN_WIDGET_PICKER", ENABLED, "Enable new widget picker that takes " + "advantage of large screen format"); + public static final BooleanFlag MULTI_SELECT_EDIT_MODE = getDebugFlag(270709220, "MULTI_SELECT_EDIT_MODE", DISABLED, "Enable new multi-select edit mode " + "for home screen"); + // TODO(Block 10): Clean up flags public static final BooleanFlag ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION = getDebugFlag(270614790, "ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION", DISABLED, "Enables predictive back animation from all apps and widgets to home"); + // TODO(Block 11): Clean up flags + public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(270392643, + "ENABLE_TWO_PANEL_HOME", ENABLED, + "Uses two panel on home screen. Only applicable on large screen devices."); + + public static final BooleanFlag FOLDABLE_WORKSPACE_REORDER = getDebugFlag(270395070, + "FOLDABLE_WORKSPACE_REORDER", DISABLED, + "In foldables, when reordering the icons and widgets, is now going to use both sides"); + public static final BooleanFlag FOLDABLE_SINGLE_PAGE = getDebugFlag(270395274, "FOLDABLE_SINGLE_PAGE", DISABLED, "Use a single page for the workspace"); - public static final BooleanFlag ENABLE_PARAMETRIZE_REORDER = getDebugFlag(289420844, - "ENABLE_PARAMETRIZE_REORDER", DISABLED, - "Enables generating the reorder using a set of parameters"); + // TODO(Block 12): Clean up flags public static final BooleanFlag ENABLE_MULTI_INSTANCE = getDebugFlag(270396680, "ENABLE_MULTI_INSTANCE", DISABLED, "Enables creation and filtering of multiple task instances in overview"); + // TODO(Block 13): Clean up flags public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = getReleaseFlag( 270391397, "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", DISABLED, "Allows on device search in all apps logging"); + // TODO(Block 14): Cleanup flags public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES", TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception."); + public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(270395798, "ENABLE_TRANSIENT_TASKBAR", ENABLED, "Enables transient taskbar."); + // TODO(Block 16): Clean up flags // When enabled the promise icon is visible in all apps while installation an app. public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(270390012, "PROMISE_APPS_IN_ALL_APPS", DISABLED, "Add promise icon in all-apps"); + public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(270390904, "KEYGUARD_ANIMATION", DISABLED, "Enable animation for keyguard going away on wallpaper"); + public static final BooleanFlag ENABLE_DEVICE_SEARCH = getReleaseFlag(270390907, "ENABLE_DEVICE_SEARCH", ENABLED, "Allows on device search in all apps"); + public static final BooleanFlag ENABLE_HIDE_HEADER = getReleaseFlag(270390930, "ENABLE_HIDE_HEADER", ENABLED, "Hide header on keyboard before typing in all apps"); + public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = getDebugFlag(270390779, "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", DISABLED, "Expand and collapse pause work button while scrolling"); + public static final BooleanFlag COLLECT_SEARCH_HISTORY = getReleaseFlag(270391455, "COLLECT_SEARCH_HISTORY", DISABLED, "Allow launcher to collect search history for log"); + public static final BooleanFlag ENABLE_TWOLINE_ALLAPPS = getDebugFlag(270390937, "ENABLE_TWOLINE_ALLAPPS", DISABLED, "Enables two line label inside all apps."); + public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(270391693, "IME_STICKY_SNACKBAR_EDU", ENABLED, "Show sticky IME edu in AllApps"); + public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(270391653, "ENABLE_PEOPLE_TILE_PREVIEW", DISABLED, "Experimental: Shows conversation shortcuts on home screen as search results"); + public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(270391638, "FOLDER_NAME_MAJORITY_RANKING", ENABLED, "Suggests folder names based on majority based ranking."); + public static final BooleanFlag INJECT_FALLBACK_APP_CORPUS_RESULTS = getReleaseFlag(270391706, "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED, "Inject fallback app corpus result when AiAi fails to return it."); @@ -222,21 +271,31 @@ public static boolean showMaterialUPopup(Context context) { "ENABLE_TASKBAR_PINNING", DISABLED, "Enables taskbar pinning to allow user to switch between transient and persistent " + "taskbar flavors"); + // TODO(Block 18): Clean up flags + public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(270395567, + "ENABLE_LAUNCH_FROM_STAGED_APP", ENABLED, + "Enable the ability to tap a staged app during split select to launch it in full " + + "screen"); + public static final BooleanFlag ENABLE_APP_PAIRS = getDebugFlag(274189428, "ENABLE_APP_PAIRS", DISABLED, "Enables the ability to create and save app pairs on the Home screen for easy" + " split screen launching."); + // TODO(Block 19): Clean up flags public static final BooleanFlag SCROLL_TOP_TO_RESET = getReleaseFlag(270395177, "SCROLL_TOP_TO_RESET", ENABLED, "Bring up IME and focus on input when scroll to top if 'Always show keyboard'" + " is enabled or in prefix state"); + public static final BooleanFlag ENABLE_SEARCH_UNINSTALLED_APPS = getReleaseFlag(270395269, "ENABLE_SEARCH_UNINSTALLED_APPS", ENABLED, "Search uninstalled app results."); + // TODO(Block 20): Clean up flags public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(270393276, "ENABLE_SCRIM_FOR_APP_LAUNCH", DISABLED, "Enables scrim during app launch animation."); + public static final BooleanFlag ENABLE_BACK_SWIPE_HOME_ANIMATION = getDebugFlag(270393426, "ENABLE_BACK_SWIPE_HOME_ANIMATION", ENABLED, "Enables home animation to icon when user swipes back."); @@ -246,80 +305,92 @@ public static boolean showMaterialUPopup(Context context) { // TODO(Block 21): Clean up flags public static final BooleanFlag ENABLE_APP_ICON_FOR_INLINE_SHORTCUTS = getDebugFlag(270395087, "ENABLE_APP_ICON_IN_INLINE_SHORTCUTS", DISABLED, "Show app icon for inline shortcut"); + // TODO(Block 22): Clean up flags + public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209, + "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED, + "Enables receiving unfold animation events from sysui instead of calculating " + + "them in launcher process using hinge sensor values."); + public static final BooleanFlag ENABLE_WIDGET_TRANSITION_FOR_RESIZING = getDebugFlag(268553314, "ENABLE_WIDGET_TRANSITION_FOR_RESIZING", DISABLED, "Enable widget transition animation when resizing the widgets"); + public static final BooleanFlag PREEMPTIVE_UNFOLD_ANIMATION_START = getDebugFlag(270397209, "PREEMPTIVE_UNFOLD_ANIMATION_START", ENABLED, "Enables starting the unfold animation preemptively when unfolding, without" + "waiting for SystemUI and then merging the SystemUI progress whenever we " + "start receiving the events"); + // TODO(Block 23): Clean up flags public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206, "ENABLE_GRID_ONLY_OVERVIEW", TEAMFOOD, "Enable a grid-only overview without a focused task."); - public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(270397202, - "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED, - ""); - - public static final BooleanFlag RECEIVE_UNFOLD_EVENTS_FROM_SYSUI = getDebugFlag(270397209, - "RECEIVE_UNFOLD_EVENTS_FROM_SYSUI", ENABLED, - "Enables receiving unfold animation events from sysui instead of calculating " - + "them in launcher proce"); - - public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906, - "ENABLE_SPLIT_FROM_WORKSPACE", ENABLED, - "Enable initiating split screen from workspace."); - public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650, "ENABLE_CURSOR_HOVER_STATES", TEAMFOOD, "Enables cursor hover states for certain elements."); + // TODO(Block 24): Clean up flags public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455, "ENABLE_NEW_MIGRATION_LOGIC", ENABLED, "Enable the new grid migration logic, keeping pages when src < dest"); + public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(270395008, "ENABLE_CACHED_WIDGET", ENABLED, "Show previously cached widgets as opposed to deferred widget where available"); + // TODO(Block 25): Clean up flags public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(270396257, "ENABLE_NEW_GESTURE_NAV_TUTORIAL", ENABLED, "Enable the redesigned gesture navigation tutorial"); + // TODO(Block 26): Clean up flags public static final BooleanFlag ENABLE_WIDGET_HOST_IN_BACKGROUND = getDebugFlag(270394384, "ENABLE_WIDGET_HOST_IN_BACKGROUND", ENABLED, "Enable background widget updates listening for widget holder"); + // TODO(Block 27): Clean up flags public static final BooleanFlag ENABLE_OVERLAY_CONNECTION_OPTIM = getDebugFlag(270392629, "ENABLE_OVERLAY_CONNECTION_OPTIM", DISABLED, "Enable optimizing overlay service connection"); + /** * Enables region sampling for text color: Needs system health assessment before turning on */ public static final BooleanFlag ENABLE_REGION_SAMPLING = getDebugFlag(270391669, "ENABLE_REGION_SAMPLING", DISABLED, "Enable region sampling to determine color of text on screen."); + public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS = getDebugFlag(270393096, "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", - DISABLED, "Always use hardware optimization for folder animations."); + DISABLED, "Always use hardware optimization for folder animations."); + public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(270392980, "SEPARATE_RECENTS_ACTIVITY", DISABLED, "Uses a separate recents activity instead of using the integrated recents+Launcher UI"); + public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = getReleaseFlag(270393258, "ENABLE_ENFORCED_ROUNDED_CORNERS", ENABLED, "Enforce rounded corners on all App Widgets"); + public static final BooleanFlag ENABLE_ICON_LABEL_AUTO_SCALING = getDebugFlag(270393294, "ENABLE_ICON_LABEL_AUTO_SCALING", ENABLED, "Enables scaling/spacing for icon labels to make more characters visible"); + public static final BooleanFlag USE_LOCAL_ICON_OVERRIDES = getDebugFlag(270394973, "USE_LOCAL_ICON_OVERRIDES", ENABLED, "Use inbuilt monochrome icons if app doesn't provide one"); + // TODO(Block 28): Clean up flags + public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(270393906, + "ENABLE_SPLIT_FROM_WORKSPACE", ENABLED, + "Enable initiating split screen from workspace."); + public static final BooleanFlag ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS = getDebugFlag(270394122, "ENABLE_SPLIT_FROM_FULLSCREEN_SHORTCUT", DISABLED, "Enable splitting from fullscreen app with keyboard shortcuts"); + public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE = getDebugFlag( 270393453, "ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE", DISABLED, "Enable initiating split screen from workspace to workspace."); @@ -328,60 +399,78 @@ public static boolean showMaterialUPopup(Context context) { "Enable initiating split screen from desktop mode to workspace."); public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401, "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture."); + // TODO(Block 29): Clean up flags public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897, "ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", DISABLED, "Enables displaying the all apps button in the hotseat."); + public static final BooleanFlag ENABLE_KEYBOARD_QUICK_SWITCH = getDebugFlag(270396844, "ENABLE_KEYBOARD_QUICK_SWITCH", ENABLED, "Enables keyboard quick switching"); + public static final BooleanFlag ENABLE_KEYBOARD_TASKBAR_TOGGLE = getDebugFlag(281726846, "ENABLE_KEYBOARD_TASKBAR_TOGGLE", ENABLED, "Enables keyboard taskbar stash toggling"); + // TODO(Block 30): Clean up flags public static final BooleanFlag USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES = getDebugFlag(270395010, "USE_SEARCH_REQUEST_TIMEOUT_OVERRIDES", DISABLED, "Use local overrides for search request timeout"); - // TODO(Block 31): Clean up flags - // TODO(Block 32): Clean up flags + + // TODO(Block 31) + public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(279494325, + "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED, + "Use refactored split launching code path"); + + // TODO(Block 32): Empty block + public static final BooleanFlag ENABLE_RESPONSIVE_WORKSPACE = getDebugFlag(241386436, - "ENABLE_RESPONSIVE_WORKSPACE", ENABLED, + "ENABLE_RESPONSIVE_WORKSPACE", DISABLED, "Enables new workspace grid calculations method."); // TODO(Block 33): Clean up flags public static final BooleanFlag ENABLE_ALL_APPS_RV_PREINFLATION = getDebugFlag(288161355, - "ENABLE_ALL_APPS_RV_PREINFLATION", ENABLED, - "Enables preinflating all apps icons to avoid scrolling jank."); + "ENABLE_ALL_APPS_RV_PREINFLATION", ENABLED, + "Enables preinflating all apps icons to avoid scrolling jank."); // TODO(Block 34): Clean up flags public static final BooleanFlag ALL_APPS_GONE_VISIBILITY = getDebugFlag(291651514, - "ALL_APPS_GONE_VISIBILITY", ENABLED, - "Set all apps container view's hidden visibility to GONE instead of INVISIBLE."); + "ALL_APPS_GONE_VISIBILITY", ENABLED, + "Set all apps container view's hidden visibility to GONE instead of INVISIBLE."); // TODO(Block 35): Empty block public static class BooleanFlag { - private final boolean mCurrentValue; - public BooleanFlag(boolean currentValue) { - mCurrentValue = currentValue; - } - public boolean get() { - return sBooleanReader.test(this); - } + + private final boolean mCurrentValue; + + public BooleanFlag(boolean currentValue) { + mCurrentValue = currentValue; + } + + public boolean get() { + return sBooleanReader.test(this); + } } + /** * Class representing an integer flag */ public static class IntFlag { - private final int mCurrentValue; - public IntFlag(int currentValue) { - mCurrentValue = currentValue; - } - public int get() { - return sIntReader.applyAsInt(this); - } + + private final int mCurrentValue; + + public IntFlag(int currentValue) { + mCurrentValue = currentValue; + } + + public int get() { + return sIntReader.applyAsInt(this); + } } + /** * Enabled state for a flag */ public enum FlagState { - ENABLED, - DISABLED, - TEAMFOOD // Enabled in team food + ENABLED, + DISABLED, + TEAMFOOD // Enabled in team food } } From 0fcab6a53a7f5f7d3aa13857e4afc40e62a6d9f9 Mon Sep 17 00:00:00 2001 From: Goooler Date: Fri, 9 Feb 2024 09:58:36 +0800 Subject: [PATCH 44/44] Revert "Sort app results first if they start with the query (#4044)" This reverts commit 1c69639bc9e2fffc27a93bac6b3dc3f4ab7a225f. --- .../search/LawnchairAppSearchAlgorithm.kt | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lawnchair/src/app/lawnchair/search/LawnchairAppSearchAlgorithm.kt b/lawnchair/src/app/lawnchair/search/LawnchairAppSearchAlgorithm.kt index 8ca8f5d5bef..48e6d901b8e 100644 --- a/lawnchair/src/app/lawnchair/search/LawnchairAppSearchAlgorithm.kt +++ b/lawnchair/src/app/lawnchair/search/LawnchairAppSearchAlgorithm.kt @@ -173,7 +173,6 @@ class LawnchairAppSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm(c return apps.asSequence() .filter { StringMatcherUtility.matches(queryTextLower, it.title.toString(), matcher) } .filterHiddenApps(queryTextLower) - .sortedWith(queryComparator(queryTextLower)) .take(maxResultsCount) .toList() } @@ -183,7 +182,7 @@ class LawnchairAppSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm(c val filteredApps = apps.asSequence() .filterHiddenApps(queryTextLower) .toList() - val matches = FuzzySearch.extractTop( + val matches = FuzzySearch.extractSorted( queryTextLower, filteredApps, { it.sectionName + it.title }, @@ -191,10 +190,8 @@ class LawnchairAppSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm(c 65, ) - return matches + return matches.take(maxResultsCount) .map { it.referent } - .sortedWith(queryComparator(queryTextLower)) - .take(maxResultsCount) } private fun Sequence.filterHiddenApps(query: String): Sequence { @@ -209,11 +206,4 @@ class LawnchairAppSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm(c filter { it.toComponentKey().toString() !in hiddenApps } } } - - private fun queryComparator(query: String): Comparator { - return compareBy( - { it.title.toString().startsWith(query, true).not() }, - { it.title.toString() }, - ) - } }