From 0451d239ed5da8060785741f45ba8a2ad895500f Mon Sep 17 00:00:00 2001 From: Sebastian Franco Date: Wed, 1 Feb 2023 16:43:58 -0800 Subject: [PATCH 1/8] Binding tests to TouchInteractionService to preventing it from getting destroyed Fix: 257514573 Bug: 266716173 Test: atest MemoryTests Test: atest TaplTestsLauncher3#testDragAppIcon Change-Id: Ib53bf11f45f9e05bf55116d52f3406f45dfaf6c2 --- tests/Android.bp | 3 +- .../launcher3/ui/TaplTestsLauncher3.java | 23 +++--- .../launcher3/util/rule/TISBindRule.java | 81 +++++++++++++++++++ 3 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 tests/src/com/android/launcher3/util/rule/TISBindRule.java diff --git a/tests/Android.bp b/tests/Android.bp index 7144d65d64..dfbaf86a50 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -44,6 +44,7 @@ filegroup { srcs: [ "src/com/android/launcher3/ui/AbstractLauncherUiTest.java", "src/com/android/launcher3/ui/PortraitLandscapeRunner.java", + "src/com/android/launcher3/ui/TaplTestsLauncher3.java", "src/com/android/launcher3/util/TestUtil.java", "src/com/android/launcher3/util/Wait.java", "src/com/android/launcher3/util/WidgetUtils.java", @@ -54,7 +55,7 @@ filegroup { "src/com/android/launcher3/util/rule/ShellCommandRule.java", "src/com/android/launcher3/util/rule/SimpleActivityRule.java", "src/com/android/launcher3/util/rule/TestStabilityRule.java", - "src/com/android/launcher3/ui/TaplTestsLauncher3.java", + "src/com/android/launcher3/util/rule/TISBindRule.java", "src/com/android/launcher3/testcomponent/BaseTestingActivity.java", "src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java", "src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java", diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 401c25a4cf..19b8b0caf5 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -51,11 +51,13 @@ import com.android.launcher3.tapl.Widgets; import com.android.launcher3.tapl.Workspace; import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; +import com.android.launcher3.util.rule.TISBindRule; import com.android.launcher3.widget.picker.WidgetsFullSheet; import com.android.launcher3.widget.picker.WidgetsRecyclerView; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -71,6 +73,9 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { private static final String STORE_APP_NAME = "Play Store"; private static final String GMAIL_APP_NAME = "Gmail"; + @Rule + public TISBindRule mTISBindRule = new TISBindRule(); + @Before public void setUp() throws Exception { super.setUp(); @@ -214,7 +219,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { false /* tapRight */); } - @IwTest(focusArea="launcher") + @IwTest(focusArea = "launcher") @Test @ScreenRecord // b/202433017 public void testWorkspace() throws Exception { @@ -341,7 +346,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { } } - @IwTest(focusArea="launcher") + @IwTest(focusArea = "launcher") @Test @PortraitLandscape @ScreenRecord // b/256898879 @@ -610,16 +615,16 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { /** * @return List of workspace grid coordinates. Those are not pixels. See {@link - * Workspace#getIconGridDimensions()} + * Workspace#getIconGridDimensions()} */ private Point[] getCornersAndCenterPositions() { final Point dimensions = mLauncher.getWorkspace().getIconGridDimensions(); - return new Point[] { - new Point(0, 1), - new Point(0, dimensions.y - 2), - new Point(dimensions.x - 1, 1), - new Point(dimensions.x - 1, dimensions.y - 2), - new Point(dimensions.x / 2, dimensions.y / 2) + return new Point[]{ + new Point(0, 1), + new Point(0, dimensions.y - 2), + new Point(dimensions.x - 1, 1), + new Point(dimensions.x - 1, dimensions.y - 2), + new Point(dimensions.x / 2, dimensions.y / 2) }; } diff --git a/tests/src/com/android/launcher3/util/rule/TISBindRule.java b/tests/src/com/android/launcher3/util/rule/TISBindRule.java new file mode 100644 index 0000000000..3ec4a29cdf --- /dev/null +++ b/tests/src/com/android/launcher3/util/rule/TISBindRule.java @@ -0,0 +1,81 @@ +/* + * 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.rule; + +import android.app.UiAutomation; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +public class TISBindRule implements TestRule { + public static String TAG = "TISBindRule"; + public static String INTENT_FILTER = "android.intent.action.QUICKSTEP_SERVICE"; + public static String TIS_PERMISSIONS = "android.permission.STATUS_BAR_SERVICE"; + + private String getLauncherPackageName(Context context) { + return ComponentName.unflattenFromString(context.getString( + com.android.internal.R.string.config_recentsComponentName)).getPackageName(); + } + + private ServiceConnection createConnection() { + return new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + Log.d(TAG, "Connected to TouchInteractionService"); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + Log.d(TAG, "Disconnected from TouchInteractionService"); + } + }; + } + + @NonNull + @Override + public Statement apply(@NonNull Statement base, @NonNull Description description) { + return new Statement() { + + @Override + public void evaluate() throws Throwable { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + final ServiceConnection connection = createConnection(); + UiAutomation uiAutomation = + InstrumentationRegistry.getInstrumentation().getUiAutomation(); + uiAutomation.adoptShellPermissionIdentity(TIS_PERMISSIONS); + Intent launchIntent = new Intent(INTENT_FILTER); + launchIntent.setPackage(getLauncherPackageName(context)); + context.bindService(launchIntent, connection, Context.BIND_AUTO_CREATE); + uiAutomation.dropShellPermissionIdentity(); + try { + base.evaluate(); + } finally { + context.unbindService(connection); + } + } + }; + } +} From 6b94a960c0310454eb3f06206bca2e66dc1ba4d9 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Wed, 22 Feb 2023 12:08:21 -0800 Subject: [PATCH 2/8] Add debug logs to debug flaky workspace binding Bug: 270216650 Test: ReorderWidgets Change-Id: I6fa2eab98c0268000ef4c44980c2917d5ef1bc89 --- src/com/android/launcher3/Launcher.java | 9 +++++++++ .../android/launcher3/model/BaseLauncherBinder.java | 6 ++++++ .../android/launcher3/testing/shared/TestProtocol.java | 1 + .../android/launcher3/celllayout/ReorderWidgets.java | 10 +++++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 8e5310172c..7dffd33052 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1877,6 +1877,9 @@ public class Launcher extends StatefulActivity } private void setWorkspaceLoading(boolean value) { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.FLAKY_BINDING, "running: setWorkspaceLoading=" + value); + } mWorkspaceLoading = value; } @@ -2323,6 +2326,9 @@ public class Launcher extends StatefulActivity */ public void startBinding() { Object traceToken = TraceHelper.INSTANCE.beginSection("startBinding"); + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.FLAKY_BINDING, "running: startBinding"); + } // Floating panels (except the full widget sheet) are associated with individual icons. If // we are starting a fresh bind, close all such panels as all the icons are about // to go away. @@ -2795,6 +2801,9 @@ public class Launcher extends StatefulActivity */ public void finishBindingItems(IntSet pagesBoundFirst) { Object traceToken = TraceHelper.INSTANCE.beginSection("finishBindingItems"); + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.FLAKY_BINDING, "running: finishBindingItems"); + } mWorkspace.restoreInstanceStateForRemainingPages(); setWorkspaceLoading(false); diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java index 9f8db51629..8519a3ef52 100644 --- a/src/com/android/launcher3/model/BaseLauncherBinder.java +++ b/src/com/android/launcher3/model/BaseLauncherBinder.java @@ -246,6 +246,9 @@ public abstract class BaseLauncherBinder { sortWorkspaceItemsSpatially(idp, otherWorkspaceItems); // Tell the workspace that we're about to start binding items + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.FLAKY_BINDING, "scheduling: startBinding"); + } executeCallbacksTask(c -> { c.clearPendingBinds(); c.startBinding(); @@ -264,6 +267,9 @@ public abstract class BaseLauncherBinder { Executor pendingExecutor = pendingTasks::add; bindWorkspaceItems(otherWorkspaceItems, pendingExecutor); bindAppWidgets(otherAppWidgets, pendingExecutor); + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.FLAKY_BINDING, "scheduling: finishBindingItems"); + } executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor); pendingExecutor.execute( () -> { diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java index 65873f199e..cc6fa33609 100644 --- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java +++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java @@ -154,6 +154,7 @@ public final class TestProtocol { public static final String MISSING_PROMISE_ICON = "b/202985412"; public static final String TASKBAR_IN_APP_STATE = "b/227657604"; public static final String NPE_TRANSIENT_TASKBAR = "b/257549303"; + public static final String FLAKY_BINDING = "b/270216650"; public static final String REQUEST_EMULATE_DISPLAY = "emulate-display"; public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display"; diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index 77fca96f04..c2fe3de407 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -33,6 +33,7 @@ import com.android.launcher3.celllayout.testcases.ReorderTestCase; import com.android.launcher3.celllayout.testcases.SimpleReorderCase; import com.android.launcher3.tapl.Widget; import com.android.launcher3.tapl.WidgetResizeFrame; +import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.ui.TaplTestsLauncher3; import com.android.launcher3.util.rule.ShellCommandRule; @@ -118,7 +119,14 @@ public class ReorderWidgets extends AbstractLauncherUiTest { // waitForLauncherCondition to wait for that condition, otherwise the condition would // always be true and it wouldn't wait for the changes to be applied. resetLoaderState(); - waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading()); + Log.d(TestProtocol.FLAKY_BINDING, "waiting for: isWorkspaceLoading=false"); + waitForLauncherCondition("Workspace didn't finish loading", l -> { + boolean isWorkspaceLoading = l.isWorkspaceLoading(); + + Log.d(TestProtocol.FLAKY_BINDING, "checking: isWorkspaceLoading=" + isWorkspaceLoading); + + return !isWorkspaceLoading; + }); Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(), mainWidgetCellPos.getCellY()); assertNotNull(widget); From 29fa0f3b66292a68b8d60ca88b5b8991f84ab850 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 22 Feb 2023 16:56:15 -0800 Subject: [PATCH 3/8] Moving IS_DEBUG_DEVICE to a compile time flag for better proguard support Bug: 270386012 Test: Presubmit Change-Id: Ic4a81567f5b9752ab17c725566ce728c3d767bd6 --- src/com/android/launcher3/Utilities.java | 6 +++--- src/com/android/launcher3/config/FeatureFlags.java | 8 ++++++-- src_build_config/com/android/launcher3/BuildConfig.java | 8 +++++++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 67bc7fc023..7d01f7baf7 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -131,10 +131,10 @@ public final class Utilities { /** * Indicates if the device has a debug build. Should only be used to store additional info or * add extra logging and not for changing the app behavior. + * @deprecated Use {@link BuildConfig#IS_DEBUG_DEVICE} directly */ - public static final boolean IS_DEBUG_DEVICE = - Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") || - Build.TYPE.toLowerCase(Locale.ROOT).equals("eng"); + @Deprecated + public static final boolean IS_DEBUG_DEVICE = BuildConfig.IS_DEBUG_DEVICE; /** * Returns true if theme is dark. diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index 0ec036cd67..84580fbc3f 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -42,18 +42,22 @@ public final class FeatureFlags { } public static boolean showFlagTogglerUi(Context context) { - return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(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 */ - public static final boolean IS_STUDIO_BUILD = BuildConfig.DEBUG; + @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; /** diff --git a/src_build_config/com/android/launcher3/BuildConfig.java b/src_build_config/com/android/launcher3/BuildConfig.java index 9a81d3f54c..1f2e0e5387 100644 --- a/src_build_config/com/android/launcher3/BuildConfig.java +++ b/src_build_config/com/android/launcher3/BuildConfig.java @@ -18,10 +18,16 @@ package com.android.launcher3; public final class BuildConfig { public static final String APPLICATION_ID = "com.android.launcher3"; - public static final boolean DEBUG = false; + + public static final boolean IS_STUDIO_BUILD = false; /** * Flag to state if the QSB is on the first screen and placed on the top, * this can be overwritten in other launchers with a different value, if needed. */ public static final boolean QSB_ON_FIRST_SCREEN = true; + + /** + * Flag to control various developer centric features + */ + public static final boolean IS_DEBUG_DEVICE = false; } From 3fbaaf9628539baaf137b4e420ea9c5064ce4e52 Mon Sep 17 00:00:00 2001 From: Jagrut Desai Date: Thu, 23 Feb 2023 10:38:39 -0800 Subject: [PATCH 4/8] Prevent Taskbar from stashing in immersive mode overview. Test: Visual, Video in Buganizer Bug: 262589756 Change-Id: Ifbdfb3a4104817e5f50833c42c3c6fc5964388b7 --- .../taskbar/TaskbarAutohideSuspendController.java | 9 +++++++++ .../launcher3/taskbar/TaskbarStashController.java | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java index 2bfc7dd05f..1a54576a7e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java @@ -41,12 +41,15 @@ public class TaskbarAutohideSuspendController implements public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2; // Taskbar EDU overlay is open above the Taskbar. */ public static final int FLAG_AUTOHIDE_SUSPEND_EDU_OPEN = 1 << 3; + // Taskbar in immersive mode in overview + public static final int FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER = 1 << 4; @IntDef(flag = true, value = { FLAG_AUTOHIDE_SUSPEND_FULLSCREEN, FLAG_AUTOHIDE_SUSPEND_DRAGGING, FLAG_AUTOHIDE_SUSPEND_TOUCHING, FLAG_AUTOHIDE_SUSPEND_EDU_OPEN, + FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER, }) @Retention(RetentionPolicy.SOURCE) public @interface AutohideSuspendFlag {} @@ -92,6 +95,10 @@ public class TaskbarAutohideSuspendController implements return mAutohideSuspendFlags != 0; } + public boolean isSuspendedForTransientTaskbarInOverview() { + return (mAutohideSuspendFlags & FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER) != 0; + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarAutohideSuspendController:"); @@ -106,6 +113,8 @@ public class TaskbarAutohideSuspendController implements appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING"); appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING"); appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_EDU_OPEN, "FLAG_AUTOHIDE_SUSPEND_EDU_OPEN"); + appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER, + "FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER"); return str.toString(); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 50f5d9e953..bbf861bd8b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -460,7 +460,9 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba return; } - if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()) { + if (stash && mControllers.taskbarAutohideSuspendController.isSuspended() + && !mControllers.taskbarAutohideSuspendController + .isSuspendedForTransientTaskbarInOverview()) { // Avoid stashing if autohide is currently suspended. return; } @@ -955,6 +957,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAGS_IN_APP)) { notifyStashChange(/* visible */ hasAnyFlag(FLAGS_IN_APP), /* stashed */ isStashedInApp()); + mControllers.taskbarAutohideSuspendController.updateFlag( + TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER, !isInApp()); } if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) { if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL)) { From 49863356e2479b4ec8dcf8b31aa4ab6b07ce3c45 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 24 Feb 2023 12:00:48 +0000 Subject: [PATCH 5/8] Set split button drawable to start instead of left Fix: 269493214 Test: Check overview actions in regulard and RTL Change-Id: Ice474294c482de8c552bda5e14efdce989fce4e7 --- .../src/com/android/quickstep/views/OverviewActionsView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java index f578b87294..caeda37e09 100644 --- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java @@ -322,7 +322,7 @@ public class OverviewActionsView extends FrameLayo requestLayout(); - mSplitButton.setCompoundDrawablesWithIntrinsicBounds( + mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds( (dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical), 0, 0, 0); } From 359ac14d132a0008f250d03fbc58d4d299407a00 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 23 Feb 2023 12:57:03 +0000 Subject: [PATCH 6/8] Fix various animation issues when total width of grid tasks < screen width Bug fixes: - Unusual long scroll when only focus task left after split select - Animation jump when tasks cannot fit screen width after dismiss or split select To fix the above issue, generified calculations when total grid task width < screen width: - Removed some special case handling when only focus task left (getSnapToFocusedTaskScrollDiff), and instead replace with generic logic that calculation that extra scroll position (shortTotalCompensation) needed when long row width is smaller than the grid size - Fixed snapped task grid translation calculation to account for shortTotalCompensation - Last task scroll calculation should account for shortTotalCompensation too - Calculate the expected shortTotalCompensation after dismiss, and use that to adjust the close gap between clearAll distance splitScrollOffset that we applied during split screen does not work well when shortTotalCompensation != 0. splitScrollOffset is not a good solution to handle split placeholder, as it allow tasks to scroll to weird position. I removed splitScrollOffset completely, and only apply split translation when split placeholder covers the tasks: - Removed splitScrollOffset on TaskView/ClearAll, so scroll position of TaskView will not change while in split to splify things. - When split placehodler will cover task's natural position (taskSize) in overview grid, apply split translation on all tasks similar to handheld - Removed isSplitPlaceholderFirstInGrid/isSplitPlaceholderLastInGrid adjustments Bug: 257952455 Test: Enter overview from home Test: Enter overview from app, with variations that quick switch and enter Test: Dismiss task from different position Test: Split select task from different position Test: Repeat with/without GRID_ONLY_OVERVIEW flag Test: Repeat with handheld Change-Id: I7689b5384845f03491041b6d910835c9ac4fab08 --- .../RecentsViewStateController.java | 5 +- .../FallbackRecentsStateController.java | 10 +- .../quickstep/views/ClearAllButton.java | 6 - .../android/quickstep/views/RecentsView.java | 341 ++++++++---------- .../com/android/quickstep/views/TaskView.java | 12 +- 5 files changed, 159 insertions(+), 215 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index e8e83288cd..07fcf48a07 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -121,8 +121,7 @@ public final class RecentsViewStateController extends private void handleSplitSelectionState(@NonNull LauncherState toState, @NonNull PendingAnimation builder, boolean animate) { if (toState != OVERVIEW_SPLIT_SELECT) { - // Not going to split, nothing to do but ensure taskviews are at correct offset - mRecentsView.resetSplitPrimaryScrollOffset(); + // Not going to split return; } @@ -153,8 +152,6 @@ public final class RecentsViewStateController extends as.start(); as.end(); } - - mRecentsView.applySplitPrimaryScrollOffset(); } private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config, diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 062e50e30b..11b1ab8ec9 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -130,15 +130,9 @@ public class FallbackRecentsStateController implements StateHandler 0) { TaskView taskView = requireTaskViewAt(0); @@ -1732,12 +1719,12 @@ public abstract class RecentsView 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f; - // Pick the next focused task from the preferred row. - for (int i = 0; i < taskCount; i++) { - TaskView taskView = requireTaskViewAt(i); - if (taskView == dismissedTaskView) { - continue; + if (isFocusedTaskDismissed) { + if (isSplitSelectionActive()) { + isStagingFocusedTask = true; + } else { + nextFocusedTaskFromTop = + mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f; + // Pick the next focused task from the preferred row. + for (int i = 0; i < taskCount; i++) { + TaskView taskView = requireTaskViewAt(i); + if (taskView == dismissedTaskView) { + continue; + } + boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId()); + if ((nextFocusedTaskFromTop && isTopRow + || (!nextFocusedTaskFromTop && !isTopRow))) { + nextFocusedTaskView = taskView; + break; + } } - boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId()); - if ((nextFocusedTaskFromTop && isTopRow - || (!nextFocusedTaskFromTop && !isTopRow))) { - nextFocusedTaskView = taskView; - break; + if (nextFocusedTaskView != null) { + nextFocusedTaskWidth = + nextFocusedTaskView.getLayoutParams().width + mPageSpacing; } } - if (nextFocusedTaskView != null) { - nextFocusedTaskWidth = - nextFocusedTaskView.getLayoutParams().width + mPageSpacing; - } } } else { getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC); @@ -3245,8 +3251,6 @@ public abstract class RecentsView topGridRowSize; boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId); boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed; + if (dismissedTaskFromTop || (isFocusedTaskDismissed && nextFocusedTaskFromTop)) { + topGridRowSize--; + } + if (dismissedTaskFromBottom || (isFocusedTaskDismissed && !nextFocusedTaskFromTop)) { + bottomGridRowSize--; + } + int longRowWidth = Math.max(topGridRowSize, bottomGridRowSize) + * (mLastComputedGridTaskSize.width() + mPageSpacing) + + (isStagingFocusedTask ? 0 : mLastComputedTaskSize.width() + mPageSpacing); + float gapWidth = 0; if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) { gapWidth = dismissedTaskWidth; - } else if ((topRowLonger && nextFocusedTaskFromTop) - || (bottomRowLonger && !nextFocusedTaskFromTop)) { + } else if (nextFocusedTaskView != null + && ((topRowLonger && nextFocusedTaskFromTop) + || (bottomRowLonger && !nextFocusedTaskFromTop))) { gapWidth = nextFocusedTaskWidth; } if (gapWidth > 0) { - if (taskCount > 2) { - // Compensate the removed gap. - longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth; - if (isClearAllHidden) { - // If ClearAllButton isn't fully shown, snap to the last task. - snapToLastTask = true; + if (mClearAllShortTotalWidthTranslation == 0) { + // Compensate the removed gap if we don't already have shortTotalCompensation, + // and adjust accordingly to the new shortTotalCompensation after dismiss. + int newClearAllShortTotalWidthTranslation = 0; + if (longRowWidth < mLastComputedGridSize.width()) { + DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + newClearAllShortTotalWidthTranslation = + (mIsRtl + ? mLastComputedTaskSize.right + : deviceProfile.widthPx - mLastComputedTaskSize.left) + - longRowWidth - deviceProfile.overviewGridSideMargin; } - } else { - // If only focused task will be left, snap to focused task instead. - longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden); + float gapCompensation = gapWidth - newClearAllShortTotalWidthTranslation; + longGridRowWidthDiff += mIsRtl ? -gapCompensation : gapCompensation; + } + if (isClearAllHidden) { + // If ClearAllButton isn't fully shown, snap to the last task. + snapToLastTask = true; } } - if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) { - // ClearAllButton will not be available in split select, snap to last task instead. - snapToLastTask = true; + if (isLandscapeSplit && !isStagingFocusedTask) { + // LastTask's scroll is the minimum scroll in split select, if current scroll is + // beyond that, we'll need to snap to last task instead. + TaskView lastTask = getLastGridTaskView(); + if (lastTask != null) { + int primaryScroll = mOrientationHandler.getPrimaryScroll(this); + int lastTaskScroll = getScrollForPage(indexOfChild(lastTask)); + if ((mIsRtl && primaryScroll < lastTaskScroll) + || (!mIsRtl && primaryScroll > lastTaskScroll)) { + snapToLastTask = true; + } + } } if (snapToLastTask) { longGridRowWidthDiff += getSnapToLastTaskScrollDiff(); - if (isSplitPlaceholderLastInGrid) { - // Shift all the tasks to make space for split placeholder. - longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize; - } } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) { // Use last task as reference point for scroll diff and snapping calculation as it's // the only invariant point in landscape split screen. @@ -3451,8 +3479,6 @@ public abstract class RecentsView lastTaskScroll)) { pageScroll = lastTaskScroll; @@ -5274,8 +5242,7 @@ public abstract class RecentsView= 0 && (mIsRtl diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index fb856058db..b9aaef63ca 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -375,7 +375,6 @@ public class TaskView extends FrameLayout implements Reusable { // Used when in SplitScreenSelectState private float mSplitSelectTranslationY; private float mSplitSelectTranslationX; - private float mSplitSelectScrollOffsetPrimary; @Nullable private ObjectAnimator mIconAndDimAnimator; @@ -1297,10 +1296,6 @@ public class TaskView extends FrameLayout implements Reusable { applyTranslationY(); } - public void setSplitScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) { - mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary; - } - private void setDismissTranslationX(float x) { mDismissTranslationX = x; applyTranslationX(); @@ -1364,19 +1359,18 @@ public class TaskView extends FrameLayout implements Reusable { applyTranslationX(); } - public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { + public float getScrollAdjustment(boolean gridEnabled) { float scrollAdjustment = 0; if (gridEnabled) { scrollAdjustment += mGridTranslationX; } else { scrollAdjustment += getPrimaryNonGridTranslationProperty().get(this); } - scrollAdjustment += mSplitSelectScrollOffsetPrimary; return scrollAdjustment; } - public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { - return getScrollAdjustment(fullscreenEnabled, gridEnabled); + public float getOffsetAdjustment(boolean gridEnabled) { + return getScrollAdjustment(gridEnabled); } public float getSizeAdjustment(boolean fullscreenEnabled) { From aec9d3136fe3f9664b72cbb342f114c64c53022b Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Mon, 16 Jan 2023 15:51:13 +0000 Subject: [PATCH 7/8] Remove focus task - Focus task is only removed under ENABLE_GRID_ONLY_OVERVIEW, but many fixes/refactoring are generic and apply with the flag off - Keep moving running task to front if go to overvied after quick switch, so live tile is always on top right Grid calculation: - Fixed some top/bottom calculation assumption that assume focus task is always present Size calculation: - With ENABLE_GRID_ONLY_OVERVIEW, taskSize == gridTaskSize, and task is aligned to top-right of gridRect (instead of focusTaskRect) Bug: 257952455 Test: Enter overview from home Test: Enter overview from app, with variations that quick switch and enter Test: Dismiss task from different position Test: Split select task from different position Test: Repeat with/without GRID_ONLY_OVERVIEW flag Test: Repeat with handheld Change-Id: I6580a8ac6c2c2059c33c4daca05b7d0354513e74 --- .../android/quickstep/AbsSwipeUpHandler.java | 14 ++--- .../quickstep/BaseActivityInterface.java | 55 ++++++++++++------- .../quickstep/FallbackActivityInterface.java | 2 +- .../quickstep/LauncherActivityInterface.java | 3 +- .../quickstep/OverviewCommandHelper.java | 2 +- .../QuickstepTestInformationHandler.java | 2 +- .../AnimatorControllerWithResistance.java | 3 +- .../android/quickstep/util/LayoutUtils.java | 3 +- .../quickstep/util/TaskViewSimulator.java | 3 +- .../android/quickstep/views/RecentsView.java | 53 ++++++++++-------- 10 files changed, 82 insertions(+), 58 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 1122e00090..e264a7f6b1 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -678,7 +678,7 @@ public abstract class AbsSwipeUpHandler, @Override public void onMotionPauseDetected() { mHasMotionEverBeenPaused = true; - maybeUpdateRecentsAttachedState(true/* animate */, true/* moveFocusedTask */); + maybeUpdateRecentsAttachedState(true/* animate */, true/* moveRunningTask */); Optional.ofNullable(mActivityInterface.getTaskbarController()) .ifPresent(TaskbarUIController::startTranslationSpring); performHapticFeedback(); @@ -696,7 +696,7 @@ public abstract class AbsSwipeUpHandler, } private void maybeUpdateRecentsAttachedState(boolean animate) { - maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */); + maybeUpdateRecentsAttachedState(animate, false /* moveRunningTask */); } /** @@ -706,9 +706,9 @@ public abstract class AbsSwipeUpHandler, * * Note this method has no effect unless the navigation mode is NO_BUTTON. * @param animate whether to animate when attaching RecentsView - * @param moveFocusedTask whether to move focused task to front when attaching + * @param moveRunningTask whether to move running task to front when attaching */ - private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveFocusedTask) { + private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) { if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) { return; } @@ -727,11 +727,11 @@ public abstract class AbsSwipeUpHandler, } else { recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask; } - if (moveFocusedTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow() + if (moveRunningTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow() && recentsAttachedToAppWindow) { - // Only move focused task if RecentsView has never been attached before, to avoid + // Only move running task if RecentsView has never been attached before, to avoid // TaskView jumping to new position as we move the tasks. - mRecentsView.moveFocusedTaskToFront(); + mRecentsView.moveRunningTaskToFront(); } mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 998439e891..d7ff8ab3fc 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -231,17 +231,20 @@ public abstract class BaseActivityInterface visibleRecentsView = activityInterface.getVisibleRecentsView(); if (visibleRecentsView != null) { - visibleRecentsView.moveFocusedTaskToFront(); + visibleRecentsView.moveRunningTaskToFront(); } if (mTaskAnimationManager.isRecentsAnimationRunning()) { cmd.mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(gestureState); diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index 54e4a0d3f1..5391f4d46c 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -59,7 +59,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { } Rect focusedTaskRect = new Rect(); LauncherActivityInterface.INSTANCE.calculateTaskSize(mContext, mDeviceProfile, - focusedTaskRect); + focusedTaskRect, PagedOrientationHandler.PORTRAIT); response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, focusedTaskRect.height()); return response; } diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java index 7c838332a6..baca76cfba 100644 --- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java +++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java @@ -158,7 +158,8 @@ public class AnimatorControllerWithResistance { Rect startRect = new Rect(); PagedOrientationHandler orientationHandler = params.recentsOrientedState .getOrientationHandler(); - LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect); + LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect, + orientationHandler); long distanceToCover = startRect.bottom; PendingAnimation resistAnim = params.resistAnim != null ? params.resistAnim diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java index f7136a5b68..79656c27a4 100644 --- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java +++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java @@ -43,7 +43,8 @@ public class LayoutUtils { PagedOrientationHandler orientationHandler) { // Track the bottom of the window. Rect taskSize = new Rect(); - LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize); + LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize, + orientationHandler); return orientationHandler.getDistanceToBottomOfRect(dp, taskSize); } diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java index 69f9ce3447..0b83eafa23 100644 --- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java @@ -157,7 +157,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { mSizeStrategy.calculateGridTaskSize(mContext, mDp, mTaskRect, mOrientationState.getOrientationHandler()); } else { - mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect); + mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect, + mOrientationState.getOrientationHandler()); } Rect fullTaskSize; diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 6ec0a4d10d..a02e29c79e 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1479,20 +1479,20 @@ public abstract class RecentsView setCurrentPage(getRunningTaskIndex())); setRunningTaskViewShowScreenshot(false); setRunningTaskHidden(runningTaskTileHidden); @@ -3262,7 +3264,8 @@ public abstract class RecentsView bottomGridRowSize; boolean bottomRowLonger = bottomGridRowSize > topGridRowSize; boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId); @@ -3274,8 +3277,10 @@ public abstract class RecentsView Date: Thu, 16 Feb 2023 15:40:44 -0800 Subject: [PATCH 8/8] Implement All Apps Icon upto the visual Specs. Test: Visual Bug: 267382941 Change-Id: If675c2f4767014598b23d8a2c2e684f5a8fb4f19 --- .../res/layout/taskbar_all_apps_button.xml | 1 - quickstep/res/values/dimens.xml | 3 ++ .../launcher3/taskbar/TaskbarView.java | 16 ++++++- .../ic_transient_taskbar_all_apps_button.xml | 48 +++++++++++++++++++ .../ic_transient_taskbar_all_apps_button.xml} | 0 res/drawable/ic_taskbar_all_apps_button.xml | 48 +++++++++++++++++++ src/com/android/launcher3/BubbleTextView.java | 11 +++++ .../launcher3/views/IconButtonView.java | 10 ++++ 8 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml rename res/{drawable/ic_all_apps_button.xml => drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml} (100%) create mode 100644 res/drawable/ic_taskbar_all_apps_button.xml diff --git a/quickstep/res/layout/taskbar_all_apps_button.xml b/quickstep/res/layout/taskbar_all_apps_button.xml index 6b665e5623..c50db2e24b 100644 --- a/quickstep/res/layout/taskbar_all_apps_button.xml +++ b/quickstep/res/layout/taskbar_all_apps_button.xml @@ -21,5 +21,4 @@ android:layout_height="@dimen/taskbar_icon_min_touch_size" android:contentDescription="@string/all_apps_button_label" android:backgroundTint="@android:color/transparent" - android:icon="@drawable/ic_all_apps_button" /> diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index bd71a9feb6..126ab7c442 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -286,6 +286,8 @@ 48dp 48dp 32dp + 6dp + 72dp @@ -295,6 +297,7 @@ 40dp 10dp 32dp + 4dp 16dp diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index c1e85aac2a..0b275a85ce 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -89,6 +89,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar private float mTransientTaskbarMinWidth; + private float mTransientTaskbarAllAppsButtonTranslationXOffset; + public TaskbarView(@NonNull Context context) { this(context, null); } @@ -108,9 +110,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar mActivityContext = ActivityContext.lookupContext(context); mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds(); Resources resources = getResources(); + boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivityContext); mIsRtl = Utilities.isRtl(resources); mTransientTaskbarMinWidth = mContext.getResources().getDimension( R.dimen.transient_taskbar_min_width); + mTransientTaskbarAllAppsButtonTranslationXOffset = + resources.getDimension(isTransientTaskbar + ? R.dimen.transient_taskbar_all_apps_button_translation_x_offset + : R.dimen.taskbar_all_apps_button_translation_x_offset); int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing); int actualIconSize = mActivityContext.getDeviceProfile().iconSizePx; @@ -130,9 +137,12 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) { mAllAppsButton = (IconButtonView) LayoutInflater.from(context) .inflate(R.layout.taskbar_all_apps_button, this, false); + mAllAppsButton.setIconDrawable(resources.getDrawable(isTransientTaskbar + ? R.drawable.ic_transient_taskbar_all_apps_button + : R.drawable.ic_taskbar_all_apps_button)); mAllAppsButton.setScaleX(mIsRtl ? -1 : 1); - mAllAppsButton.setForegroundTint(mActivityContext.getColor( - DisplayController.isTransientTaskbar(mActivityContext) + mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); + mAllAppsButton.setForegroundTint(mActivityContext.getColor(isTransientTaskbar ? R.color.all_apps_button_color : R.color.all_apps_button_color_dark)); @@ -276,6 +286,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar } if (mAllAppsButton != null) { + mAllAppsButton.setTranslationXForTaskbarAllAppsIcon(getChildCount() > 0 + ? mTransientTaskbarAllAppsButtonTranslationXOffset : 0f); addView(mAllAppsButton, mIsRtl ? getChildCount() : 0); // if only all apps button present, don't include divider view. diff --git a/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml b/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml new file mode 100644 index 0000000000..6e740aed4f --- /dev/null +++ b/res/drawable-sw600dp/ic_transient_taskbar_all_apps_button.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + diff --git a/res/drawable/ic_all_apps_button.xml b/res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml similarity index 100% rename from res/drawable/ic_all_apps_button.xml rename to res/drawable-sw720dp/ic_transient_taskbar_all_apps_button.xml diff --git a/res/drawable/ic_taskbar_all_apps_button.xml b/res/drawable/ic_taskbar_all_apps_button.xml new file mode 100644 index 0000000000..82fbbea617 --- /dev/null +++ b/res/drawable/ic_taskbar_all_apps_button.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index b109e8ab1c..bd5c863283 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -113,6 +113,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private float mScaleForReorderBounce = 1f; + private float mTranslationXForTaskbarAllAppsIcon = 0f; + private static final Property DOT_SCALE_PROPERTY = new Property(Float.TYPE, "dotScale") { @Override @@ -958,6 +960,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private void updateTranslation() { super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x + + mTranslationXForTaskbarAllAppsIcon + mTranslationForMoveFromCenterAnimation.x + mTranslationXForTaskbarAlignmentAnimation + mTranslationXForTaskbarRevealAnimation @@ -969,6 +972,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, + mTranslationYForTaskbarRevealAnimation); } + /** + * Sets translationX for taskbar all apps icon + */ + public void setTranslationXForTaskbarAllAppsIcon(float translationX) { + mTranslationXForTaskbarAllAppsIcon = translationX; + updateTranslation(); + } + public void setReorderBounceOffset(float x, float y) { mTranslationForReorderBounce.set(x, y); updateTranslation(); diff --git a/src/com/android/launcher3/views/IconButtonView.java b/src/com/android/launcher3/views/IconButtonView.java index 64e9327dfa..9969eebe06 100644 --- a/src/com/android/launcher3/views/IconButtonView.java +++ b/src/com/android/launcher3/views/IconButtonView.java @@ -31,6 +31,7 @@ import android.os.Build; import android.util.AttributeSet; import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; import com.android.launcher3.BubbleTextView; import com.android.launcher3.icons.BaseIconFactory; @@ -70,6 +71,15 @@ public class IconButtonView extends BubbleTextView { } } + /** Sets given Drawable as icon */ + public void setIconDrawable(@NonNull Drawable drawable) { + ColorStateList tintList = getBackgroundTintList(); + int tint = tintList == null ? Color.WHITE : tintList.getDefaultColor(); + try (BaseIconFactory factory = LauncherIcons.obtain(getContext())) { + setIcon(new IconDrawable(factory.getWhiteShadowLayer(), tint, drawable)); + } + } + /** Updates the color of the icon's foreground layer. */ public void setForegroundTint(@ColorInt int tintColor) { FastBitmapDrawable icon = getIcon();