From 8cd020bb1dbc0846aeb04ebbccf1cc0972abdc72 Mon Sep 17 00:00:00 2001 From: Thales Lima Date: Tue, 15 Mar 2022 20:15:14 +0000 Subject: [PATCH 01/17] Reset the size of hotseat cells When resetting the hotseat layout, the size of cells also can be changed based on changes in DeviceProfile. In this case, the border size changes when rotating the device. Fixes 216071526 Test: manual and HSV Change-Id: Idf7b7972e7be347a991cad1cb8ee8cf95cbc4a87 --- src/com/android/launcher3/CellLayout.java | 52 +++++++++++++++-------- src/com/android/launcher3/Hotseat.java | 1 + 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index ad4cae4440..d235180314 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -93,7 +93,7 @@ public class CellLayout extends ViewGroup { private int mFixedCellWidth; private int mFixedCellHeight; @ViewDebug.ExportedProperty(category = "launcher") - private final Point mBorderSpace; + private Point mBorderSpace; @ViewDebug.ExportedProperty(category = "launcher") private int mCountX; @@ -238,22 +238,7 @@ public class CellLayout extends ViewGroup { mActivity = ActivityContext.lookupContext(context); DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - switch (mContainerType) { - case FOLDER: - mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx); - break; - case HOTSEAT: - mBorderSpace = new Point(deviceProfile.hotseatBorderSpace, - deviceProfile.hotseatBorderSpace); - break; - case WORKSPACE: - default: - mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx); - break; - } - - mCellWidth = mCellHeight = -1; - mFixedCellWidth = mFixedCellHeight = -1; + resetCellSizeInternal(deviceProfile); mCountX = deviceProfile.inv.numColumns; mCountY = deviceProfile.inv.numRows; @@ -376,6 +361,12 @@ public class CellLayout extends ViewGroup { return mShortcutsAndWidgets.getLayerType() == LAYER_TYPE_HARDWARE; } + /** + * Change sizes of cells + * + * @param width the new width of the cells + * @param height the new height of the cells + */ public void setCellDimensions(int width, int height) { mFixedCellWidth = mCellWidth = width; mFixedCellHeight = mCellHeight = height; @@ -383,6 +374,33 @@ public class CellLayout extends ViewGroup { mBorderSpace); } + private void resetCellSizeInternal(DeviceProfile deviceProfile) { + switch (mContainerType) { + case FOLDER: + mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx); + break; + case HOTSEAT: + mBorderSpace = new Point(deviceProfile.hotseatBorderSpace, + deviceProfile.hotseatBorderSpace); + break; + case WORKSPACE: + default: + mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx); + break; + } + + mCellWidth = mCellHeight = -1; + mFixedCellWidth = mFixedCellHeight = -1; + } + + /** + * Reset the cell sizes and border space + */ + public void resetCellSize(DeviceProfile deviceProfile) { + resetCellSizeInternal(deviceProfile); + requestLayout(); + } + public void setGridSize(int x, int y) { mCountX = x; mCountY = y; diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index e1680fc7e7..d7cdb8f283 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -84,6 +84,7 @@ public class Hotseat extends CellLayout implements Insettable { removeAllViewsInLayout(); mHasVerticalHotseat = hasVerticalHotseat; DeviceProfile dp = mActivity.getDeviceProfile(); + resetCellSize(dp); if (hasVerticalHotseat) { setGridSize(1, dp.numShownHotseatIcons); } else { From f477ec203272b79699d3173bf3bc4dec16c8bad1 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Tue, 15 Mar 2022 13:46:37 -0700 Subject: [PATCH 02/17] Refactor allapps.search package to depend on ActivityContext. Test: Manual Bug: 216683257 Change-Id: I6230498b24380b37531f8a83db1dc768270e708a --- .../launcher3/allapps/ActivityAllAppsContainerView.java | 5 ----- .../allapps/search/AllAppsSearchBarController.java | 9 ++++----- .../allapps/search/AppsSearchContainerLayout.java | 8 ++++---- .../allapps/search/DefaultSearchAdapterProvider.java | 8 ++++---- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index b94a61251b..f530b0089c 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -103,11 +103,6 @@ public class ActivityAllAppsContainerView extend } } - /** Handles selection on focused view and returns {@code true} on success. */ - public boolean launchHighlightedItem() { - return getMainAdapterProvider().launchHighlightedItem(); - } - @Override protected SearchAdapterProvider createMainAdapterProvider() { return mActivityContext.createSearchAdapterProvider(this); diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java index fd8945a0f6..a6a47a71db 100644 --- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java +++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java @@ -29,14 +29,13 @@ import android.view.inputmethod.EditorInfo; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.ExtendedEditText; -import com.android.launcher3.Launcher; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.search.SearchAlgorithm; import com.android.launcher3.search.SearchCallback; +import com.android.launcher3.views.ActivityContext; /** * An interface to a search box that AllApps can command. @@ -45,7 +44,7 @@ public class AllAppsSearchBarController implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener, OnFocusChangeListener { - protected BaseDraggingActivity mLauncher; + protected ActivityContext mLauncher; protected SearchCallback mCallback; protected ExtendedEditText mInput; protected String mQuery; @@ -62,7 +61,7 @@ public class AllAppsSearchBarController */ public final void initialize( SearchAlgorithm searchAlgorithm, ExtendedEditText input, - BaseDraggingActivity launcher, SearchCallback callback) { + ActivityContext launcher, SearchCallback callback) { mCallback = callback; mLauncher = launcher; @@ -125,7 +124,7 @@ public class AllAppsSearchBarController mLauncher.getStatsLogManager().logger() .log(LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME); // selectFocusedView should return SearchTargetEvent that is passed onto onClick - return Launcher.getLauncher(mLauncher).getAppsView().launchHighlightedItem(); + return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem(); } return false; } diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java index cb459eacb3..893e547340 100644 --- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java +++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java @@ -32,7 +32,6 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.ExtendedEditText; import com.android.launcher3.Insettable; @@ -43,6 +42,7 @@ import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.allapps.SearchUiManager; import com.android.launcher3.search.SearchCallback; +import com.android.launcher3.views.ActivityContext; import java.util.ArrayList; @@ -53,7 +53,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText implements SearchUiManager, SearchCallback, AllAppsStore.OnUpdateListener, Insettable { - private final BaseDraggingActivity mLauncher; + private final ActivityContext mLauncher; private final AllAppsSearchBarController mSearchBarController; private final SpannableStringBuilder mSearchQueryBuilder; @@ -74,7 +74,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText public AppsSearchContainerLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - mLauncher = BaseDraggingActivity.fromContext(context); + mLauncher = ActivityContext.lookupContext(context); mSearchBarController = new AllAppsSearchBarController(); mSearchQueryBuilder = new SpannableStringBuilder(); @@ -134,7 +134,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText mApps = appsView.getApps(); mAppsView = appsView; mSearchBarController.initialize( - new DefaultAppSearchAlgorithm(mLauncher), + new DefaultAppSearchAlgorithm(getContext()), this, mLauncher, this); } diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java index 2fe4915e2f..a95bd514da 100644 --- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java +++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java @@ -23,20 +23,20 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BubbleTextView; import com.android.launcher3.allapps.AllAppsGridAdapter; import com.android.launcher3.model.data.ItemInfo; +import com.android.launcher3.views.AppLauncher; /** - * Provides views for local search results + * Provides views for local search results. */ -public class DefaultSearchAdapterProvider extends SearchAdapterProvider { +public class DefaultSearchAdapterProvider extends SearchAdapterProvider { private final RecyclerView.ItemDecoration mDecoration; private View mHighlightedView; - public DefaultSearchAdapterProvider(BaseDraggingActivity launcher) { + public DefaultSearchAdapterProvider(AppLauncher launcher) { super(launcher); mDecoration = new RecyclerView.ItemDecoration() { @Override From 5eb66d8abbc120c2e07d77029b59fea55ff8613f Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Wed, 16 Mar 2022 09:58:17 -0700 Subject: [PATCH 03/17] Refactor ActivityAllAppsContainerView to depend on ActivityContext. All of the all apps search support is in this class which is also being refactored to depend on ActivityContext. At the end of this refactor, this class can be merged with BaseAllAppsContainerView. Test: Manual Bug: 216683257 Change-Id: I8cbf21c8d9ce97cc60e9846cfe8c2a7bcb800a01 --- src/com/android/launcher3/BaseDraggingActivity.java | 1 + .../allapps/ActivityAllAppsContainerView.java | 9 +++++---- src/com/android/launcher3/views/ActivityContext.java | 12 ++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 3af43c021b..6de3884b93 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -216,6 +216,7 @@ public abstract class BaseDraggingActivity extends BaseActivity * Creates and returns {@link SearchAdapterProvider} for build variant specific search result * views */ + @Override public SearchAdapterProvider createSearchAdapterProvider( ActivityAllAppsContainerView allApps) { return new DefaultSearchAdapterProvider(this); diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index f530b0089c..11e0a1faae 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -26,12 +26,13 @@ import android.widget.RelativeLayout; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.RecyclerView; -import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.DeviceProfile.DeviceProfileListenable; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.search.SearchAdapterProvider; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.views.AppLauncher; import java.util.Objects; @@ -40,8 +41,8 @@ import java.util.Objects; * * @param Type of context inflating all apps. */ -public class ActivityAllAppsContainerView extends - BaseAllAppsContainerView { +public class ActivityAllAppsContainerView extends BaseAllAppsContainerView { protected SearchUiManager mSearchUiManager; /** @@ -104,7 +105,7 @@ public class ActivityAllAppsContainerView extend } @Override - protected SearchAdapterProvider createMainAdapterProvider() { + protected final SearchAdapterProvider createMainAdapterProvider() { return mActivityContext.createSearchAdapterProvider(this); } diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index 3c90eea5d1..50c09dd4d4 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -25,7 +25,9 @@ import android.view.View.AccessibilityDelegate; import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.allapps.ActivityAllAppsContainerView; import com.android.launcher3.allapps.BaseAllAppsContainerView; +import com.android.launcher3.allapps.search.SearchAdapterProvider; import com.android.launcher3.dot.DotInfo; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.folder.FolderIcon; @@ -190,4 +192,14 @@ public interface ActivityContext { default StringCache getStringCache() { return null; } + + /** + * Creates and returns {@link SearchAdapterProvider} for build variant specific search result + * views. + */ + @Nullable + default SearchAdapterProvider createSearchAdapterProvider( + ActivityAllAppsContainerView appsView) { + return null; + } } From c8c761621b6a8481ce2b76381bc4684263f46e7a Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Thu, 17 Mar 2022 12:13:13 -0700 Subject: [PATCH 04/17] Fix overriden deep shortcut titles and icons Bulk Icon loading causes all icons that share a component name to share a title and bitmap. This didn't work for deep shortcuts since they were already being loaded individually. Added a check to filter out deep shortcuts. Note: If future traces show that individual deep shortcut loading is taking too long, then deep shortcut loading can be refactored into bulk icon loading. Fixes: 224891898 Test: manual Change-Id: I112fcd4a889071e5b523d56731bad8ecdee08abc --- .../android/launcher3/icons/IconCache.java | 27 ++++++++++++++----- .../android/launcher3/model/LoaderTask.java | 8 +++++- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index 5ece4a62dd..7ba2317868 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -16,6 +16,7 @@ package com.android.launcher3.icons; +import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY; @@ -340,14 +341,15 @@ public class IconCache extends BaseIconCache { Map, List>> iconLoadSubsectionsMap = iconRequestInfos.stream() .filter(iconRequest -> { - if (iconRequest.itemInfo.getTargetComponent() != null) { - return true; + if (iconRequest.itemInfo.getTargetComponent() == null) { + Log.i(TAG, + "Skipping Item info with null component name: " + + iconRequest.itemInfo); + iconRequest.itemInfo.bitmap = getDefaultIcon( + iconRequest.itemInfo.user); + return false; } - Log.i(TAG, - "Skipping Item info with null component name: " - + iconRequest.itemInfo); - iconRequest.itemInfo.bitmap = getDefaultIcon(iconRequest.itemInfo.user); - return false; + return true; }) .collect(groupingBy(iconRequest -> Pair.create(iconRequest.itemInfo.user, iconRequest.useLowResIcon))); @@ -356,6 +358,17 @@ public class IconCache extends BaseIconCache { iconLoadSubsectionsMap.forEach((sectionKey, filteredList) -> { Map>> duplicateIconRequestsMap = filteredList.stream() + .filter(iconRequest -> { + // Filter out icons that should not share the same bitmap and title + if (iconRequest.itemInfo.itemType == ITEM_TYPE_DEEP_SHORTCUT) { + Log.e(TAG, + "Skipping Item info for deep shortcut: " + + iconRequest.itemInfo, + new IllegalStateException()); + return false; + } + return true; + }) .collect(groupingBy(iconRequest -> iconRequest.itemInfo.getTargetComponent())); diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index b9fa21d10d..f1c5d59fc8 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -615,7 +615,13 @@ public class LoaderTask implements Runnable { } if (info != null) { - iconRequestInfos.add(c.createIconRequestInfo(info, useLowResIcon)); + if (info.itemType + != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) { + // Skip deep shortcuts; their title and icons have already been + // loaded above. + iconRequestInfos.add( + c.createIconRequestInfo(info, useLowResIcon)); + } c.applyCommonProperties(info); From 90ba15622a8794225e72b0d688cadc650c046261 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 16 Mar 2022 11:29:47 -0700 Subject: [PATCH 05/17] Reset the home settings activity when launching it Opening the home settings shouldn't open to a previous state. Updating home setting intents to clear previous tasks. Bug: 187447602 Test: manual Change-Id: I40fa408cdade5003c91136fe54f054e7f0ae07b2 --- src/com/android/launcher3/views/OptionsPopupView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java index 867e488155..2a9a8a5d36 100644 --- a/src/com/android/launcher3/views/OptionsPopupView.java +++ b/src/com/android/launcher3/views/OptionsPopupView.java @@ -229,7 +229,7 @@ public class OptionsPopupView extends ArrowPopup Launcher launcher = Launcher.getLauncher(view.getContext()); launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES) .setPackage(launcher.getPackageName()) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)); return true; } From d478f555cbb90f1d15b175a0c6ac54e4dba510b2 Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Wed, 16 Mar 2022 10:53:39 -0700 Subject: [PATCH 06/17] Have taskbar all apps extend ActivityAllAppsContainerView. This step is necessary to have taskbar support search in all apps. Search is not ready yet, so a fallback search manager is included. Test: Manual Bug: 216683257 Change-Id: Id118388bc4baae4b63ef205295caf46cbd541bc8 --- quickstep/res/layout/taskbar_all_apps.xml | 6 +++ .../launcher3/taskbar/BaseTaskbarContext.java | 4 +- .../allapps/TaskbarAllAppsContainerView.java | 46 ++-------------- .../allapps/TaskbarAllAppsContext.java | 9 ++++ ...TaskbarAllAppsFallbackSearchContainer.java | 54 +++++++++++++++++++ .../launcher3/views/ActivityContext.java | 3 +- 6 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java diff --git a/quickstep/res/layout/taskbar_all_apps.xml b/quickstep/res/layout/taskbar_all_apps.xml index 7dc0cbe1ab..d402469833 100644 --- a/quickstep/res/layout/taskbar_all_apps.xml +++ b/quickstep/res/layout/taskbar_all_apps.xml @@ -51,6 +51,12 @@ + + diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java index 27e89baa90..4e1f54c9a2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java @@ -23,14 +23,14 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile.DeviceProfileListenable; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.util.Themes; -import com.android.launcher3.views.ActivityContext; +import com.android.launcher3.views.AppLauncher; import java.util.ArrayList; import java.util.List; // TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar. /** Base for common behavior between taskbar window contexts. */ -public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext, +public abstract class BaseTaskbarContext extends ContextThemeWrapper implements AppLauncher, DeviceProfileListenable { protected final LayoutInflater mLayoutInflater; diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java index 37cd753ba4..0ea2aa0647 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java @@ -17,22 +17,17 @@ package com.android.launcher3.taskbar.allapps; import android.content.Context; import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import android.view.WindowInsets; -import androidx.recyclerview.widget.RecyclerView; - +import com.android.launcher3.allapps.ActivityAllAppsContainerView; import com.android.launcher3.allapps.AllAppsGridAdapter; import com.android.launcher3.allapps.AlphabeticalAppsList; import com.android.launcher3.allapps.BaseAdapterProvider; import com.android.launcher3.allapps.BaseAllAppsAdapter; -import com.android.launcher3.allapps.BaseAllAppsContainerView; -import com.android.launcher3.allapps.search.SearchAdapterProvider; /** All apps container accessible from taskbar. */ -public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView { +public class TaskbarAllAppsContainerView extends + ActivityAllAppsContainerView { public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -42,41 +37,6 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView createMainAdapterProvider() { - // Taskbar all apps does not yet support search, so this implementation is minimal. - return new SearchAdapterProvider(mActivityContext) { - @Override - public boolean launchHighlightedItem() { - return false; - } - - @Override - public View getHighlightedItem() { - return null; - } - - @Override - public RecyclerView.ItemDecoration getDecorator() { - return null; - } - - @Override - public boolean isViewSupported(int viewType) { - return false; - } - - @Override - public void onBindView(AllAppsGridAdapter.ViewHolder holder, int position) { } - - @Override - public AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater, - ViewGroup parent, int viewType) { - return null; - } - }; - } - @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect()); diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java index 22fffdf317..50dfff0854 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java @@ -32,6 +32,9 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; +import com.android.launcher3.allapps.ActivityAllAppsContainerView; +import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider; +import com.android.launcher3.allapps.search.SearchAdapterProvider; import com.android.launcher3.dot.DotInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.popup.PopupDataProvider; @@ -154,6 +157,12 @@ class TaskbarAllAppsContext extends BaseTaskbarContext { @Override public void onPopupVisibilityChanged(boolean isVisible) {} + @Override + public SearchAdapterProvider createSearchAdapterProvider( + ActivityAllAppsContainerView appsView) { + return new DefaultSearchAdapterProvider(this); + } + /** Root drag layer for this context. */ private static class TaskbarAllAppsDragLayer extends BaseDragLayer implements OnComputeInsetsListener { diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java new file mode 100644 index 0000000000..53fe06d32c --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsFallbackSearchContainer.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.taskbar.allapps; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.launcher3.ExtendedEditText; +import com.android.launcher3.allapps.ActivityAllAppsContainerView; +import com.android.launcher3.allapps.SearchUiManager; + +/** Empty search container for Taskbar All Apps used as a fallback if search is not supported. */ +public class TaskbarAllAppsFallbackSearchContainer extends View implements SearchUiManager { + public TaskbarAllAppsFallbackSearchContainer(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TaskbarAllAppsFallbackSearchContainer( + Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public void initializeSearch(ActivityAllAppsContainerView containerView) { + // Do nothing. + } + + @Override + public void resetSearch() { + // Do nothing. + } + + @Nullable + @Override + public ExtendedEditText getEditText() { + return null; + } +} diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java index 50c09dd4d4..93078e4cf6 100644 --- a/src/com/android/launcher3/views/ActivityContext.java +++ b/src/com/android/launcher3/views/ActivityContext.java @@ -26,7 +26,6 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.allapps.ActivityAllAppsContainerView; -import com.android.launcher3.allapps.BaseAllAppsContainerView; import com.android.launcher3.allapps.search.SearchAdapterProvider; import com.android.launcher3.dot.DotInfo; import com.android.launcher3.dragndrop.DragController; @@ -101,7 +100,7 @@ public interface ActivityContext { /** * The all apps container, if it exists in this context. */ - default BaseAllAppsContainerView getAppsView() { + default ActivityAllAppsContainerView getAppsView() { return null; } From 64212c5439dd40204256630dd7c01cf68a02047f Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Fri, 18 Mar 2022 16:55:17 -0700 Subject: [PATCH 07/17] Fix crash condition by adding a null check in DigitalWellBeingToast Fixes a crash condition where TaskView#getRecentsView() could return null when being called from DigitalWellBeingToast#setBanner(), resulting in a crash. Fixes: 217671133 Test: Manual Change-Id: I964384d97d26336e9a5e8e4c025f66ab78c63e0a --- .../src/com/android/quickstep/views/DigitalWellBeingToast.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java index 27a748d3f2..79b15c713a 100644 --- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -306,7 +306,7 @@ public final class DigitalWellBeingToast { private void setBanner(@Nullable View view) { mBanner = view; - if (view != null) { + if (view != null && mTaskView.getRecentsView() != null) { setupAndAddBanner(); setBannerOutline(); } From 3b687a50922163d4457d319f0ba2f072386d64c2 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Wed, 23 Feb 2022 18:35:47 -0800 Subject: [PATCH 08/17] Fix small positioning bug with DWB banner in landscape The DWB banner is now positioned correctly when the task thumbnail is set as a secondary split view. Fixes: 220637396 Test: Manual testing on local Pixel 6 Change-Id: I3bcb0eb09d2a607b2891bc9f63f3a0b03668f48e (cherry picked from commit 87fad7b9841c4dbc77c20b4e3c0a414d103aba55) --- .../launcher3/touch/PortraitPagedViewHandler.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 2c9afd6506..926946ba7f 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -334,8 +334,14 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { // Set translations if (deviceProfile.isLandscape) { if (desiredTaskId == splitBounds.rightBottomTaskId) { - translationX = ((taskViewWidth * splitBounds.leftTaskPercent) - + (taskViewWidth * splitBounds.dividerWidthPercent)); + float leftTopTaskPercent = splitBounds.appsStackedVertically + ? splitBounds.topTaskPercent + : splitBounds.leftTaskPercent; + float dividerThicknessPercent = splitBounds.appsStackedVertically + ? splitBounds.dividerHeightPercent + : splitBounds.dividerWidthPercent; + translationX = ((taskViewWidth * leftTopTaskPercent) + + (taskViewWidth * dividerThicknessPercent)); } } else { if (desiredTaskId == splitBounds.leftTopTaskId) { From b42345273c7547d9e0de78e76e02d28800ba2cd9 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Sun, 20 Feb 2022 17:39:51 -0800 Subject: [PATCH 09/17] Fix paired icon placement in landscape/seascape In grouped task view, paired icons will now align better with task thumbnails. Fixes: 218783211 Test: Extensive manual testing on local device(s). Change-Id: I372d2ee90302a8d96ace048ff4f82126d9b2b363 (cherry picked from commit d6826c74a4ca9dcec1ae4c9aff713fa0b6014cb1) --- .../quickstep/views/GroupedTaskView.java | 3 +- .../touch/LandscapePagedViewHandler.java | 35 ++++++++-- .../touch/PagedOrientationHandler.java | 3 +- .../touch/PortraitPagedViewHandler.java | 65 +++++++++++++++++-- .../touch/SeascapePagedViewHandler.java | 38 +++++++++-- .../util/SplitConfigurationOptions.java | 19 ++++++ 6 files changed, 146 insertions(+), 17 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index d9f668dd1b..b9615abf1d 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -271,7 +271,8 @@ public class GroupedTaskView extends TaskView { getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2, taskIconHeight, mSnapshotView.getMeasuredWidth(), mSnapshotView.getMeasuredHeight(), - isRtl, deviceProfile, mSplitBoundsConfig); + getMeasuredHeight(), getMeasuredWidth(), isRtl, deviceProfile, + mSplitBoundsConfig); } private void updateSecondaryDwbPlacement() { diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index 2609e549a5..d1f54cea29 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -16,6 +16,7 @@ package com.android.launcher3.touch; +import static android.view.Gravity.BOTTOM; import static android.view.Gravity.CENTER_VERTICAL; import static android.view.Gravity.END; import static android.view.Gravity.START; @@ -468,18 +469,42 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { @Override public void setSplitIconParams(View primaryIconView, View secondaryIconView, int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight, - boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) { + int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl, + DeviceProfile deviceProfile, StagedSplitBounds splitConfig) { FrameLayout.LayoutParams primaryIconParams = (FrameLayout.LayoutParams) primaryIconView.getLayoutParams(); FrameLayout.LayoutParams secondaryIconParams = new FrameLayout.LayoutParams(primaryIconParams); - primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END); + // We calculate the "midpoint" of the thumbnail area, and place the icons there. + // This is the place where the thumbnail area splits by default, in a near-50/50 split. + // It is usually not exactly 50/50, due to insets/screen cutouts. + int fullscreenInsetThickness = deviceProfile.getInsets().top; + int fullscreenMidpointFromBottom = ((deviceProfile.heightPx - fullscreenInsetThickness) + / 2); + float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx; + float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx; + int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx; + int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots; + int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct); + int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct); + + primaryIconParams.gravity = BOTTOM | (isRtl ? START : END); + secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END); primaryIconView.setTranslationX(0); - primaryIconView.setTranslationY(-(taskIconHeight / 2f)); - secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END); secondaryIconView.setTranslationX(0); - secondaryIconView.setTranslationY(taskIconHeight / 2f); + if (splitConfig.initiatedFromSeascape) { + // if the split was initiated from seascape, + // the task on the right (secondary) is slightly larger + primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset); + secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset + + taskIconHeight); + } else { + // if not, + // the task on the left (primary) is slightly larger + primaryIconView.setTranslationY(-bottomToMidpointOffset); + secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight); + } primaryIconView.setLayoutParams(primaryIconParams); secondaryIconView.setLayoutParams(secondaryIconParams); diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index 6e594e9cc6..1b171266fa 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -146,7 +146,8 @@ public interface PagedOrientationHandler { int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl); void setSplitIconParams(View primaryIconView, View secondaryIconView, int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight, - boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig); + int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl, + DeviceProfile deviceProfile, StagedSplitBounds splitConfig); /* * The following two methods try to center the TaskMenuView in landscape by finding the center diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 2c9afd6506..d015191c26 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -18,6 +18,7 @@ package com.android.launcher3.touch; import static android.view.Gravity.BOTTOM; import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.Gravity.END; import static android.view.Gravity.START; import static android.view.Gravity.TOP; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; @@ -559,18 +560,70 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { @Override public void setSplitIconParams(View primaryIconView, View secondaryIconView, int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight, - boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) { + int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl, + DeviceProfile deviceProfile, StagedSplitBounds splitConfig) { FrameLayout.LayoutParams primaryIconParams = (FrameLayout.LayoutParams) primaryIconView.getLayoutParams(); FrameLayout.LayoutParams secondaryIconParams = new FrameLayout.LayoutParams(primaryIconParams); - primaryIconParams.gravity = TOP | CENTER_HORIZONTAL; - // shifts icon half a width left (height is used conveniently here since icons are square) - primaryIconView.setTranslationX(-(taskIconHeight / 2f)); + if (deviceProfile.isLandscape) { + // We calculate the "midpoint" of the thumbnail area, and place the icons there. + // This is the place where the thumbnail area splits by default, in a near-50/50 split. + // It is usually not exactly 50/50, due to insets/screen cutouts. + int fullscreenInsetThickness = deviceProfile.isSeascape() + ? deviceProfile.getInsets().right + : deviceProfile.getInsets().left; + int fullscreenMidpointFromBottom = ((deviceProfile.widthPx + - fullscreenInsetThickness) / 2); + float midpointFromBottomPct = (float) fullscreenMidpointFromBottom + / deviceProfile.widthPx; + float insetPct = (float) fullscreenInsetThickness / deviceProfile.widthPx; + int spaceAboveSnapshots = 0; + int overviewThumbnailAreaThickness = groupedTaskViewWidth - spaceAboveSnapshots; + int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness + * midpointFromBottomPct); + int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct); + + if (deviceProfile.isSeascape()) { + primaryIconParams.gravity = TOP | (isRtl ? END : START); + secondaryIconParams.gravity = TOP | (isRtl ? END : START); + if (splitConfig.initiatedFromSeascape) { + // if the split was initiated from seascape, + // the task on the right (secondary) is slightly larger + primaryIconView.setTranslationX(bottomToMidpointOffset - taskIconHeight); + secondaryIconView.setTranslationX(bottomToMidpointOffset); + } else { + // if not, + // the task on the left (primary) is slightly larger + primaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset + - taskIconHeight); + secondaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset); + } + } else { + primaryIconParams.gravity = TOP | (isRtl ? START : END); + secondaryIconParams.gravity = TOP | (isRtl ? START : END); + if (!splitConfig.initiatedFromSeascape) { + // if the split was initiated from landscape, + // the task on the left (primary) is slightly larger + primaryIconView.setTranslationX(-bottomToMidpointOffset); + secondaryIconView.setTranslationX(-bottomToMidpointOffset + taskIconHeight); + } else { + // if not, + // the task on the right (secondary) is slightly larger + primaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset); + secondaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset + + taskIconHeight); + } + } + } else { + primaryIconParams.gravity = TOP | CENTER_HORIZONTAL; + // shifts icon half a width left (height is used here since icons are square) + primaryIconView.setTranslationX(-(taskIconHeight / 2f)); + secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL; + secondaryIconView.setTranslationX(taskIconHeight / 2f); + } primaryIconView.setTranslationY(0); - secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL; - secondaryIconView.setTranslationX(taskIconHeight / 2f); secondaryIconView.setTranslationY(0); primaryIconView.setLayoutParams(primaryIconParams); diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java index 9151796fc5..74b6a5b28e 100644 --- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java @@ -178,16 +178,46 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { @Override public void setSplitIconParams(View primaryIconView, View secondaryIconView, int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight, - boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) { + int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl, + DeviceProfile deviceProfile, StagedSplitBounds splitConfig) { super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight, - primarySnapshotWidth, primarySnapshotHeight, isRtl, deviceProfile, splitConfig); + primarySnapshotWidth, primarySnapshotHeight, groupedTaskViewHeight, + groupedTaskViewWidth, isRtl, deviceProfile, splitConfig); FrameLayout.LayoutParams primaryIconParams = (FrameLayout.LayoutParams) primaryIconView.getLayoutParams(); FrameLayout.LayoutParams secondaryIconParams = (FrameLayout.LayoutParams) secondaryIconView.getLayoutParams(); - primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START); - secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START); + // We calculate the "midpoint" of the thumbnail area, and place the icons there. + // This is the place where the thumbnail area splits by default, in a near-50/50 split. + // It is usually not exactly 50/50, due to insets/screen cutouts. + int fullscreenInsetThickness = deviceProfile.getInsets().top; + int fullscreenMidpointFromBottom = ((deviceProfile.heightPx + - fullscreenInsetThickness) / 2); + float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx; + float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx; + int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx; + int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots; + int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct); + int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct); + + primaryIconParams.gravity = BOTTOM | (isRtl ? END : START); + secondaryIconParams.gravity = BOTTOM | (isRtl ? END : START); + primaryIconView.setTranslationX(0); + secondaryIconView.setTranslationX(0); + if (splitConfig.initiatedFromSeascape) { + // if the split was initiated from seascape, + // the task on the right (secondary) is slightly larger + primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset); + secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset + + taskIconHeight); + } else { + // if not, + // the task on the left (primary) is slightly larger + primaryIconView.setTranslationY(-bottomToMidpointOffset); + secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight); + } + primaryIconView.setLayoutParams(primaryIconParams); secondaryIconView.setLayoutParams(secondaryIconParams); } diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java index cb714b2a8f..b40493ac25 100644 --- a/src/com/android/launcher3/util/SplitConfigurationOptions.java +++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java @@ -113,6 +113,14 @@ public final class SplitConfigurationOptions { * the bounds were originally in */ public final boolean appsStackedVertically; + /** + * If {@code true}, that means at the time of creation of this object, the phone was in + * seascape orientation. This is important on devices with insets, because they do not split + * evenly -- one of the insets must be slightly larger to account for the inset. + * From landscape, it is the leftTop task that expands slightly. + * From seascape, it is the rightBottom task that expands slightly. + */ + public final boolean initiatedFromSeascape; public final int leftTopTaskId; public final int rightBottomTaskId; @@ -128,11 +136,22 @@ public final class SplitConfigurationOptions { this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom, leftTopBounds.right, rightBottomBounds.top); appsStackedVertically = true; + initiatedFromSeascape = false; } else { // horizontal apps, vertical divider this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top, rightBottomBounds.left, leftTopBounds.bottom); appsStackedVertically = false; + // The following check is unreliable on devices without insets + // (initiatedFromSeascape will always be set to false.) This happens to be OK for + // all our current uses, but should be refactored. + // TODO: Create a more reliable check, or refactor how splitting works on devices + // with insets. + if (rightBottomBounds.width() > leftTopBounds.width()) { + initiatedFromSeascape = true; + } else { + initiatedFromSeascape = false; + } } leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right; From b4b79142d8fd5200191039138ac28617807a090d Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Mon, 7 Mar 2022 15:45:40 -0800 Subject: [PATCH 10/17] Fix UI overlap when rotating in split select mode Fixes an issue where you could trigger a UI overlap by rotating the phone during split select. The issue occurred because devices with insets were calling TaskView#resetViewTransforms during rotation, and not accounting for the fact that an extra transform was applied for split staging. Fixes: 220998096 Test: Manual test on inset and non-inset devices Change-Id: I2d6c969231127aa16c9eae39cf69e08ceb96c44b (cherry picked from commit 51bfabf8b796c88d5053ef1a658a29d4037d13e4) --- quickstep/src/com/android/quickstep/views/TaskView.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 1d621dc740..bf817ec6c4 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -1008,8 +1008,11 @@ public class TaskView extends FrameLayout implements Reusable { // resetViewTransforms is called during Quickswitch scrolling. mDismissTranslationX = mTaskOffsetTranslationX = mTaskResistanceTranslationX = mSplitSelectTranslationX = mGridEndTranslationX = 0f; - mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = - mSplitSelectTranslationY = 0f; + mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f; + if (getRecentsView() == null || !getRecentsView().isSplitSelectionActive()) { + mSplitSelectTranslationY = 0f; + } + setSnapshotScale(1f); applyTranslationX(); applyTranslationY(); From bf6f171f8495f83543455acbf2d139329e2ead09 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Mon, 14 Mar 2022 18:25:47 -0700 Subject: [PATCH 11/17] Fix issue with split thumbnails overflowing during rotation Fixes a set of issues in Overview where you could cause split thumbnails to overflow their contents into each other by rotating the phone in certain ways. The issue occurred because StagedSplitBounds objects have their height and width assigned differently depending on if they were created while the phone was in portrait or landscape. Fixed by adding a conditional check in PortraitPagedViewHandler#setSplitTaskSwipeRect and LandscapePagedViewHandler#setSplitTaskSwipeRect. Fixes: 218784856 Fixes: 218779313 Test: Manual on local devices Change-Id: I04b4f4344250da34616ab1744af22fa41b9aba9b (cherry picked from commit 1d6b7f2abf9b7af77b75d5e47e46233bdc106507) --- .../touch/LandscapePagedViewHandler.java | 15 +++++++++------ .../touch/PortraitPagedViewHandler.java | 17 +++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index 2609e549a5..d0ac3c8017 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -414,14 +414,17 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { @Override public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect, StagedSplitBounds splitInfo, int desiredStagePosition) { - float diff; - float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f; + float topLeftTaskPercent = splitInfo.appsStackedVertically + ? splitInfo.topTaskPercent + : splitInfo.leftTaskPercent; + float dividerBarPercent = splitInfo.appsStackedVertically + ? splitInfo.dividerHeightPercent + : splitInfo.dividerWidthPercent; + if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) { - diff = outRect.height() * (1f - splitInfo.leftTaskPercent) + horizontalDividerDiff; - outRect.bottom -= diff; + outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent); } else { - diff = outRect.height() * splitInfo.leftTaskPercent + horizontalDividerDiff; - outRect.top += diff; + outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent)); } } diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 2c9afd6506..0909e8e753 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -488,19 +488,24 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect, StagedSplitBounds splitInfo, int desiredStagePosition) { boolean isLandscape = dp.isLandscape; + float topLeftTaskPercent = splitInfo.appsStackedVertically + ? splitInfo.topTaskPercent + : splitInfo.leftTaskPercent; + float dividerBarPercent = splitInfo.appsStackedVertically + ? splitInfo.dividerHeightPercent + : splitInfo.dividerWidthPercent; + if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) { if (isLandscape) { - outRect.right = outRect.left + (int) (outRect.width() * splitInfo.leftTaskPercent); + outRect.right = outRect.left + (int) (outRect.width() * topLeftTaskPercent); } else { - outRect.bottom = outRect.top + (int) (outRect.height() * splitInfo.topTaskPercent); + outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent); } } else { if (isLandscape) { - outRect.left += (int) (outRect.width() * - (splitInfo.leftTaskPercent + splitInfo.dividerWidthPercent)); + outRect.left += (int) (outRect.width() * (topLeftTaskPercent + dividerBarPercent)); } else { - outRect.top += (int) (outRect.height() * - (splitInfo.topTaskPercent + splitInfo.dividerHeightPercent)); + outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent)); } } } From 7d149231957467a5cc8b8b889047a4340e4b0518 Mon Sep 17 00:00:00 2001 From: Thales Lima Date: Mon, 21 Mar 2022 18:27:45 +0000 Subject: [PATCH 12/17] Fix height of hotseat Hotseat size was going behind workspace unnecessarily, causing some issues and also had the wrong hotseat height which was cutting the icons in folders. Fixes: 224713923 Fixes: 221101290 Test: manual Change-Id: I2646abc4a6aaa5bf2ea85e55e2f3618f8d7efd9b --- src/com/android/launcher3/DeviceProfile.java | 4 ++-- src/com/android/launcher3/Hotseat.java | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 622d750c83..f9d5a5828d 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -947,7 +947,7 @@ public class DeviceProfile { additionalLeftSpace = qsbWidth + hotseatBorderSpace; } - int hotseatTopDiff = hotseatHeight - taskbarOffset; + int hotseatTopPadding = hotseatHeight - taskbarOffset - hotseatCellHeightPx; int endOffset = ApiWrapper.getHotseatEndOffset(context); int requiredWidth = iconSizePx * numShownHotseatIcons @@ -956,7 +956,7 @@ public class DeviceProfile { int hotseatSize = Math.min(requiredWidth, availableWidthPx - endOffset); int sideSpacing = (availableWidthPx - hotseatSize) / 2; - mHotseatPadding.set(sideSpacing + additionalLeftSpace, hotseatTopDiff, sideSpacing, + mHotseatPadding.set(sideSpacing + additionalLeftSpace, hotseatTopPadding, sideSpacing, taskbarOffset); if (endOffset > sideSpacing) { diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index e1680fc7e7..b0e938a6ed 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -110,10 +110,9 @@ public class Hotseat extends CellLayout implements Insettable { mQsb.setVisibility(View.VISIBLE); lp.gravity = Gravity.BOTTOM; lp.width = ViewGroup.LayoutParams.MATCH_PARENT; - lp.height = (grid.isTaskbarPresent + lp.height = grid.isTaskbarPresent ? grid.workspacePadding.bottom - : grid.hotseatBarSizePx) - + (grid.isTaskbarPresent ? grid.taskbarSize : insets.bottom); + : grid.hotseatBarSizePx + insets.bottom; } Rect padding = grid.getHotseatLayoutPadding(getContext()); From 24fab62d35f1fa20e8a0691231b4a06dfb24f0f1 Mon Sep 17 00:00:00 2001 From: Luca Zuccarini Date: Mon, 21 Mar 2022 17:56:01 +0000 Subject: [PATCH 13/17] [OneSearch] Add a flag to guard QSB animations. Bug: 225749858 Test: manual Change-Id: Ib725b9bcec235d2e23cf93b2f86d0dc9cd0600cb --- src/com/android/launcher3/config/FeatureFlags.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index de33ae5f87..8ba2070ce6 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -258,6 +258,9 @@ public final class FeatureFlags { "ENABLE_NEW_MIGRATION_LOGIC", true, "Enable the new grid migration logic, keeping pages when src < dest"); + public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag( + "ENABLE_ONE_SEARCH_MOTION", false, "Enables animations in OneSearch."); + public static void initialize(Context context) { synchronized (sDebugFlags) { for (DebugFlag flag : sDebugFlags) { From ad9c83966b46097f4049273aa4a89b777b79025c Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Mon, 7 Mar 2022 16:09:56 -0800 Subject: [PATCH 14/17] Add auto-enter-pip support in FallbackSwipeHandler - Deprecate HomeAnimationFactory#supportSwipePipToHome and treat 3rd party Launcher supporting auto-enter-pip transition as well - Add a new FallbackPipToHomeAnimationFactory if auto-enter-pip transition is to be launched - Make sure Launcher is resumed at the end of auto-enter-pip transition to actually trigger the PiP task appearing Video: http://recall/-/aaaaaabFQoRHlzixHdtY/hMPkRXy4vAjC6sQYUIIWUP Bug: 220665901 Test: `m -j Launcher3` and verify the auto-enter-pip transition \ see also the video Change-Id: I6d16f2559d173f695ccbc743eb55e964bf088d04 --- .../android/quickstep/AbsSwipeUpHandler.java | 3 +- .../quickstep/FallbackSwipeHandler.java | 43 +++++++++++++++++-- .../quickstep/LauncherSwipeHandlerV2.java | 5 --- .../quickstep/SwipeUpAnimationLogic.java | 8 ---- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 253903c798..43be051dd3 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1273,8 +1273,7 @@ public abstract class AbsSwipeUpHandler, HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip, runningTaskTarget); - mIsSwipingPipToHome = !mIsSwipeForStagedSplit - && homeAnimFactory.supportSwipePipToHome() && appCanEnterPip; + mIsSwipingPipToHome = !mIsSwipeForStagedSplit && appCanEnterPip; final RectFSpringAnim[] windowAnim; if (mIsSwipingPipToHome) { mSwipePipToHomeAnimator = createWindowAnimationToPip( diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java index 4eb190a2f5..d76484c135 100644 --- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java @@ -50,12 +50,14 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.SpringAnimationBuilder; +import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.util.DisplayController; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsState; @@ -93,6 +95,8 @@ public class FallbackSwipeHandler extends private final Matrix mTmpMatrix = new Matrix(); private float mMaxLauncherScale = 1; + private boolean mAppCanEnterPip; + public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState, TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs, boolean continuingLastGesture, InputConsumerController inputConsumer) { @@ -135,16 +139,27 @@ public class FallbackSwipeHandler extends protected HomeAnimationFactory createHomeAnimationFactory(ArrayList launchCookies, long duration, boolean isTargetTranslucent, boolean appCanEnterPip, RemoteAnimationTargetCompat runningTaskTarget) { + mAppCanEnterPip = appCanEnterPip; + if (appCanEnterPip) { + return new FallbackPipToHomeAnimationFactory(); + } mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration); + startHomeIntent(mActiveAnimationFactory); + return mActiveAnimationFactory; + } + + private void startHomeIntent( + @Nullable FallbackHomeAnimationFactory gestureContractAnimationFactory) { ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); Intent intent = new Intent(mGestureState.getHomeIntent()); - mActiveAnimationFactory.addGestureContract(intent); + if (gestureContractAnimationFactory != null) { + gestureContractAnimationFactory.addGestureContract(intent); + } try { mContext.startActivity(intent, options.toBundle()); } catch (NullPointerException | ActivityNotFoundException | SecurityException e) { mContext.startActivity(createHomeIntent()); } - return mActiveAnimationFactory; } @Override @@ -160,8 +175,19 @@ public class FallbackSwipeHandler extends @Override protected void finishRecentsControllerToHome(Runnable callback) { + final Runnable recentsCallback; + if (mAppCanEnterPip) { + // Make sure Launcher is resumed after auto-enter-pip transition to actually trigger + // the PiP task appearing. + recentsCallback = () -> { + callback.run(); + startHomeIntent(null /* gestureContractAnimationFactory */); + }; + } else { + recentsCallback = callback; + } mRecentsAnimationController.finish( - false /* toRecents */, callback, true /* sendUserLeaveHint */); + mAppCanEnterPip /* toRecents */, recentsCallback, true /* sendUserLeaveHint */); } @Override @@ -186,6 +212,17 @@ public class FallbackSwipeHandler extends } } + private class FallbackPipToHomeAnimationFactory extends HomeAnimationFactory { + @NonNull + @Override + public AnimatorPlaybackController createActivityAnimationToHome() { + // copied from {@link LauncherSwipeHandlerV2.LauncherHomeAnimationFactory} + long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); + return mActivity.getStateManager().createAnimationToNewWorkspace( + RecentsState.HOME, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS); + } + } + private class FallbackHomeAnimationFactory extends HomeAnimationFactory { private final Rect mTempRect = new Rect(); private final TransformParams mHomeAlphaParams = new TransformParams(); diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java index bc7a6ae449..e9571e0ca1 100644 --- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java +++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java @@ -284,10 +284,5 @@ public class LauncherSwipeHandlerV2 extends getViewIgnoredInWorkspaceRevealAnimation()) .start(); } - - @Override - public boolean supportSwipePipToHome() { - return true; - } } } diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java index 8d9a6855af..8862073725 100644 --- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -183,14 +183,6 @@ public abstract class SwipeUpAnimationLogic implements public void onCancel() { } - /** - * @return {@code true} if this factory supports animating an Activity to PiP window on - * swiping up to home. - */ - public boolean supportSwipePipToHome() { - return false; - } - /** * @param progress The progress of the animation to the home screen. * @return The current alpha to set on the animating app window. From a5addf0e898f8086dae5b4c90e193365d585e34f Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Mon, 21 Mar 2022 18:14:01 -0700 Subject: [PATCH 15/17] Keep live tile running when TaskMenuView is showing * Doesn't fix the bug, but a nicer UX to have Bug: 223317893 Test: Live tile was running after tapping app icon. Was able to enter split just fine Change-Id: I50c5d5623546d19d216beae09b76c310e8b3c815 --- .../src/com/android/quickstep/views/TaskView.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 1d621dc740..c4bed26016 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -890,15 +890,7 @@ public class TaskView extends FrameLayout implements Reusable { if (confirmSecondSplitSelectApp()) { return; } - if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) { - RecentsView recentsView = getRecentsView(); - recentsView.switchToScreenshot( - () -> recentsView.finishRecentsAnimation(true /* toRecents */, - false /* shouldPip */, - () -> showTaskMenu(iconView))); - } else { - showTaskMenu(iconView); - } + showTaskMenu(iconView); }); iconView.setOnLongClickListener(v -> { requestDisallowInterceptTouchEvent(true); From b7ef569591faf672f86629bd6bc543afce3b4a1c Mon Sep 17 00:00:00 2001 From: Thales Lima Date: Thu, 10 Mar 2022 10:32:36 +0000 Subject: [PATCH 16/17] Change size of All Apps bottom sheet This brings the size of the bottom sheet closer to the spec provided by UX. For that type of flexibility to be possible, more attributes are introduced and some calculations had to be changed. This shouldn't affect phones. Bug: 218638090 Test: visual, with dumpsys and HSV Change-Id: Ieee7580d80d8e100837b1cdd7a1455c4d65612dc --- res/values-sw600dp-land/dimens.xml | 9 +++-- res/values-sw600dp/dimens.xml | 2 +- res/values-sw720dp-land/dimens.xml | 7 ++++ res/values-sw720dp/dimens.xml | 5 ++- res/values/attrs.xml | 19 +++++++++++ src/com/android/launcher3/DeviceProfile.java | 20 ++++++----- .../launcher3/InvariantDeviceProfile.java | 34 +++++++++++++++++++ .../android/launcher3/DeviceProfileTest.kt | 6 ++++ 8 files changed, 89 insertions(+), 13 deletions(-) diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml index 6c5be914dd..daca048878 100644 --- a/res/values-sw600dp-land/dimens.xml +++ b/res/values-sw600dp-land/dimens.xml @@ -16,14 +16,17 @@ --> - + 44dp - + 11.33dp 11.33dp - + 0dp 16dp + + + 52dp diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml index 501ead685f..73edc6f8bd 100644 --- a/res/values-sw600dp/dimens.xml +++ b/res/values-sw600dp/dimens.xml @@ -23,7 +23,7 @@ 0dp - 46dp + 48dp 75dp diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml index 33da4a1bd8..eb5c751588 100644 --- a/res/values-sw720dp-land/dimens.xml +++ b/res/values-sw720dp-land/dimens.xml @@ -18,13 +18,20 @@ 0dp 32dp + 21.93dp 29.33dp + 64dp + + + 32dp + 49dp + 0dp diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml index b4c8837224..3ec211a142 100644 --- a/res/values-sw720dp/dimens.xml +++ b/res/values-sw720dp/dimens.xml @@ -16,10 +16,12 @@ - 65dp + 28dp + 27.59dp 36dp + 20sp 72dp @@ -28,6 +30,7 @@ 32dp 32dp 32dp + 164dp diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 4ed31f8968..c96a2284e7 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -241,9 +241,28 @@ if not specified --> + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 91fa4ca497..dee7d4ec4f 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -624,14 +624,15 @@ public class DeviceProfile { + textHeight + (topBottomPadding * 2); } - private void updateAllAppsWidth(Resources res) { + private void updateAllAppsContainerWidth(Resources res) { int cellLayoutHorizontalPadding = (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right) / 2; if (isTablet) { - allAppsLeftRightPadding = res.getDimensionPixelSize( - R.dimen.all_apps_bottom_sheet_horizontal_padding) + cellLayoutHorizontalPadding; + allAppsLeftRightPadding = + res.getDimensionPixelSize(R.dimen.all_apps_bottom_sheet_horizontal_padding); + int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns) - + (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1)) + + (allAppsBorderSpacePx.x * (numShownAllAppsColumns - 1)) + allAppsLeftRightPadding * 2; allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2); } else { @@ -755,24 +756,26 @@ public class DeviceProfile { * Updates the iconSize for allApps* variants. */ public void updateAllAppsIconSize(float scale, Resources res) { - if (numShownAllAppsColumns != inv.numColumns) { + //TODO(b/218638090): remove the tablet condition once we have phone specs + if (isScalableGrid && isTablet) { allAppsIconSizePx = pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics); allAppsIconTextSizePx = pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics); allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx; - autoResizeAllAppsCells(); + allAppsCellWidthPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].x, mMetrics, scale); + allAppsCellHeightPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].y, mMetrics, scale); } else { float invIconSizeDp = inv.iconSize[mTypeIndex]; float invIconTextSizeSp = inv.iconTextSize[mTypeIndex]; allAppsIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale)); allAppsIconTextSizePx = (int) (pxFromSp(invIconTextSizeSp, mMetrics) * scale); allAppsIconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale); + allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx); allAppsCellHeightPx = getCellSize().y; } - allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx); - updateAllAppsWidth(res); + updateAllAppsContainerWidth(res); if (isVerticalBarLayout()) { hideWorkspaceLabelsIfNotEnoughSpace(); } @@ -1223,6 +1226,7 @@ public class DeviceProfile { allAppsIconDrawablePaddingPx)); writer.println(prefix + pxToDpStr("allAppsCellHeightPx", allAppsCellHeightPx)); writer.println(prefix + pxToDpStr("allAppsCellWidthPx", allAppsCellWidthPx)); + writer.println(prefix + pxToDpStr("allAppsBorderSpacePx", allAppsBorderSpacePx.x)); writer.println(prefix + "\tnumShownAllAppsColumns: " + numShownAllAppsColumns); writer.println(prefix + pxToDpStr("allAppsLeftRightPadding", allAppsLeftRightPadding)); writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin)); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 9dd1493d16..219ed9e371 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -128,6 +128,7 @@ public class InvariantDeviceProfile { public float[] horizontalMargin; + public PointF[] allAppsCellSize; public float[] allAppsIconSize; public float[] allAppsIconTextSize; public PointF[] allAppsBorderSpaces; @@ -357,6 +358,7 @@ public class InvariantDeviceProfile { numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY ? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns; + allAppsCellSize = displayOption.allAppsCellSize; allAppsBorderSpaces = displayOption.allAppsBorderSpaces; allAppsIconSize = displayOption.allAppsIconSizes; allAppsIconTextSize = displayOption.allAppsIconTextSizes; @@ -798,6 +800,7 @@ public class InvariantDeviceProfile { private final float[] iconSizes = new float[COUNT_SIZES]; private final float[] textSizes = new float[COUNT_SIZES]; + private final PointF[] allAppsCellSize = new PointF[COUNT_SIZES]; private final float[] allAppsIconSizes = new float[COUNT_SIZES]; private final float[] allAppsIconTextSizes = new float[COUNT_SIZES]; private final PointF[] allAppsBorderSpaces = new PointF[COUNT_SIZES]; @@ -873,9 +876,35 @@ public class InvariantDeviceProfile { folderBorderSpace = borderSpace; + x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidth, + minCellSize[INDEX_DEFAULT].x); + y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeight, + minCellSize[INDEX_DEFAULT].y); + allAppsCellSize[INDEX_DEFAULT] = new PointF(x, y); + + x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthLandscape, + allAppsCellSize[INDEX_DEFAULT].x); + y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightLandscape, + allAppsCellSize[INDEX_DEFAULT].y); + allAppsCellSize[INDEX_LANDSCAPE] = new PointF(x, y); + + x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthTwoPanelPortrait, + allAppsCellSize[INDEX_DEFAULT].x); + y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightTwoPanelPortrait, + allAppsCellSize[INDEX_DEFAULT].y); + allAppsCellSize[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y); + + x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthTwoPanelLandscape, + allAppsCellSize[INDEX_DEFAULT].x); + y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightTwoPanelLandscape, + allAppsCellSize[INDEX_DEFAULT].y); + allAppsCellSize[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y); + x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpace, borderSpace); allAppsBorderSpaces[INDEX_DEFAULT] = new PointF(x, y); + x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpaceLandscape, + allAppsBorderSpaces[INDEX_DEFAULT].x); allAppsBorderSpaces[INDEX_LANDSCAPE] = new PointF(x, y); x = y = a.getFloat( R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelPortrait, @@ -971,6 +1000,7 @@ public class InvariantDeviceProfile { textSizes[i] = 0; borderSpaces[i] = new PointF(); minCellSize[i] = new PointF(); + allAppsCellSize[i] = new PointF(); allAppsIconSizes[i] = 0; allAppsIconTextSizes[i] = 0; allAppsBorderSpaces[i] = new PointF(); @@ -987,6 +1017,8 @@ public class InvariantDeviceProfile { minCellSize[i].y *= w; horizontalMargin[i] *= w; hotseatBorderSpaces[i] *= w; + allAppsCellSize[i].x *= w; + allAppsCellSize[i].y *= w; allAppsIconSizes[i] *= w; allAppsIconTextSizes[i] *= w; allAppsBorderSpaces[i].x *= w; @@ -1008,6 +1040,8 @@ public class InvariantDeviceProfile { minCellSize[i].y += p.minCellSize[i].y; horizontalMargin[i] += p.horizontalMargin[i]; hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i]; + allAppsCellSize[i].x += p.allAppsCellSize[i].x; + allAppsCellSize[i].y += p.allAppsCellSize[i].y; allAppsIconSizes[i] += p.allAppsIconSizes[i]; allAppsIconTextSizes[i] += p.allAppsIconTextSizes[i]; allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x; diff --git a/tests/src/com/android/launcher3/DeviceProfileTest.kt b/tests/src/com/android/launcher3/DeviceProfileTest.kt index 75ad21d8aa..d1e91ed072 100644 --- a/tests/src/com/android/launcher3/DeviceProfileTest.kt +++ b/tests/src/com/android/launcher3/DeviceProfileTest.kt @@ -208,6 +208,12 @@ class DeviceProfileTest { PointF(64f, 83f), PointF(64f, 83f) ).toTypedArray() + allAppsCellSize = listOf( + PointF(64f, 83f), + PointF(64f, 83f), + PointF(64f, 83f), + PointF(64f, 83f) + ).toTypedArray() } } } \ No newline at end of file From 44aadeaef613687beccdcd48ee7f1d09ab6884bb Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 9 Mar 2022 10:38:25 -0800 Subject: [PATCH 17/17] Fix issue cauing the taskbar to show in the all set page of the SUW. Some missing state handling was causing the taskbar to show in the all set page of the SUW. Fixes: 218507703 Test: build change, flashed and factory reset device Change-Id: If3a280ef6416f0821cf6a9b1ab0a65d58c5c8221 --- .../taskbar/TaskbarActivityContext.java | 3 ++- .../taskbar/TaskbarStashController.java | 27 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 6c74ae379b..0f3a6eee47 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -442,7 +442,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mControllers.stashedHandleViewController.setIsHomeButtonDisabled( mControllers.navbarButtonsViewController.isHomeDisabled()); mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags); - mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags, fromInit); + mControllers.taskbarStashController.updateStateForSysuiFlags( + systemUiStateFlags, fromInit || !isUserSetupComplete()); mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags, fromInit); mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index f9a282b561..54dd0b2379 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -54,6 +54,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6; public static final int FLAG_STASHED_IN_APP_ALL_APPS = 1 << 7; // All apps is visible. + public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard + + // If any of these flags are enabled, isInApp should return true. + private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP; // If we're in an app and any of these flags are enabled, taskbar should be stashed. private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL @@ -141,7 +145,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba // Evaluate whether the handle should be stashed private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder( flags -> { - boolean inApp = hasAnyFlag(flags, FLAG_IN_APP); + boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP); boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP); boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE); return (inApp && stashedInApp) || (!inApp && stashedLauncherState); @@ -179,10 +183,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba boolean isInSetup = !mActivity.isUserSetupComplete() || sharedState.setupUIVisible; updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup); - if (isInSetup) { - // Update the in-app state to ensure isStashed() reflects right state during SUW - updateStateForFlag(FLAG_IN_APP, true); - } + updateStateForFlag(FLAG_IN_SETUP, isInSetup); applyState(); notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp()); @@ -216,9 +217,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba * Sets the flag indicating setup UI is visible */ protected void setSetupUIVisible(boolean isVisible) { - updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, - isVisible || !mActivity.isUserSetupComplete()); - applyState(); + boolean hideTaskbar = isVisible || !mActivity.isUserSetupComplete(); + updateStateForFlag(FLAG_IN_SETUP, hideTaskbar); + updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, hideTaskbar); + applyState(hideTaskbar ? 0 : TASKBAR_STASH_DURATION); } /** @@ -259,7 +261,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba } private boolean isInApp() { - return hasAnyFlag(FLAG_IN_APP); + return hasAnyFlag(FLAGS_IN_APP); } /** @@ -478,7 +480,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba } public void applyState() { - applyState(TASKBAR_STASH_DURATION); + applyState(hasAnyFlag(FLAG_IN_SETUP) ? 0 : TASKBAR_STASH_DURATION); } public void applyState(long duration) { @@ -568,8 +570,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) { mControllers.uiController.onStashedInAppChanged(); } - if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAG_IN_APP)) { - notifyStashChange(/* visible */ hasAnyFlag(FLAG_IN_APP), + if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAGS_IN_APP)) { + notifyStashChange(/* visible */ hasAnyFlag(FLAGS_IN_APP), /* stashed */ isStashedInApp()); } if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) { @@ -613,6 +615,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba str.add((flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0 ? "FLAG_IN_STASHED_LAUNCHER_STATE" : ""); str.add((flags & FLAG_STASHED_IN_APP_ALL_APPS) != 0 ? "FLAG_STASHED_IN_APP_ALL_APPS" : ""); + str.add((flags & FLAG_IN_SETUP) != 0 ? "FLAG_IN_SETUP" : ""); return str.toString(); }